[
  {
    "path": "Asdl.c",
    "content": "#include \"Python.h\"\n#include \"pycore_asdl.h\"\n\nGENERATE_ASDL_SEQ_CONSTRUCTOR(generic, void*);\nGENERATE_ASDL_SEQ_CONSTRUCTOR(identifier, PyObject*);\nGENERATE_ASDL_SEQ_CONSTRUCTOR(int, int);\n"
  },
  {
    "path": "Asm_Trampoline.S",
    "content": "    .text\n    .globl\t_Py_trampoline_func_start\n# The following assembly is equivalent to:\n# PyObject *\n# trampoline(PyThreadState *ts, _PyInterpreterFrame *f,\n#            int throwflag, py_evaluator evaluator)\n# {\n#     return evaluator(ts, f, throwflag);\n# }\n_Py_trampoline_func_start:\n#ifdef __x86_64__\n    sub    $8, %rsp\n    call    *%rcx\n    add    $8, %rsp\n    ret\n#endif // __x86_64__\n#if defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__)\n    // ARM64 little endian, 64bit ABI\n    // generate with aarch64-linux-gnu-gcc 12.1\n    stp     x29, x30, [sp, -16]!\n    mov     x29, sp\n    blr     x3\n    ldp     x29, x30, [sp], 16\n    ret\n#endif\n    .globl\t_Py_trampoline_func_end\n_Py_trampoline_func_end:\n    .section        .note.GNU-stack,\"\",@progbits\n"
  },
  {
    "path": "Assemble.c",
    "content": "#include <stdbool.h>\n\n#include \"Python.h\"\n#include \"pycore_code.h\"          // write_location_entry_start()\n#include \"pycore_compile.h\"\n#include \"pycore_opcode.h\"        // _PyOpcode_Caches[] and opcode category macros\n\n\n#define DEFAULT_CODE_SIZE 128\n#define DEFAULT_LNOTAB_SIZE 16\n#define DEFAULT_CNOTAB_SIZE 32\n\n#undef SUCCESS\n#undef ERROR\n#define SUCCESS 0\n#define ERROR -1\n\n#define RETURN_IF_ERROR(X)  \\\n    if ((X) == -1) {        \\\n        return ERROR;       \\\n    }\n\ntypedef _PyCompilerSrcLocation location;\ntypedef _PyCompile_Instruction instruction;\ntypedef _PyCompile_InstructionSequence instr_sequence;\n\nstatic inline bool\nsame_location(location a, location b)\n{\n    return a.lineno == b.lineno &&\n           a.end_lineno == b.end_lineno &&\n           a.col_offset == b.col_offset &&\n           a.end_col_offset == b.end_col_offset;\n}\n\nstruct assembler {\n    PyObject *a_bytecode;  /* bytes containing bytecode */\n    int a_offset;              /* offset into bytecode */\n    PyObject *a_except_table;  /* bytes containing exception table */\n    int a_except_table_off;    /* offset into exception table */\n    /* Location Info */\n    int a_lineno;          /* lineno of last emitted instruction */\n    PyObject* a_linetable; /* bytes containing location info */\n    int a_location_off;    /* offset of last written location info frame */\n};\n\nstatic int\nassemble_init(struct assembler *a, int firstlineno)\n{\n    memset(a, 0, sizeof(struct assembler));\n    a->a_lineno = firstlineno;\n    a->a_linetable = NULL;\n    a->a_location_off = 0;\n    a->a_except_table = NULL;\n    a->a_bytecode = PyBytes_FromStringAndSize(NULL, DEFAULT_CODE_SIZE);\n    if (a->a_bytecode == NULL) {\n        goto error;\n    }\n    a->a_linetable = PyBytes_FromStringAndSize(NULL, DEFAULT_CNOTAB_SIZE);\n    if (a->a_linetable == NULL) {\n        goto error;\n    }\n    a->a_except_table = PyBytes_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE);\n    if (a->a_except_table == NULL) {\n        goto error;\n    }\n    return SUCCESS;\nerror:\n    Py_XDECREF(a->a_bytecode);\n    Py_XDECREF(a->a_linetable);\n    Py_XDECREF(a->a_except_table);\n    return ERROR;\n}\n\nstatic void\nassemble_free(struct assembler *a)\n{\n    Py_XDECREF(a->a_bytecode);\n    Py_XDECREF(a->a_linetable);\n    Py_XDECREF(a->a_except_table);\n}\n\nstatic inline void\nwrite_except_byte(struct assembler *a, int byte) {\n    unsigned char *p = (unsigned char *) PyBytes_AS_STRING(a->a_except_table);\n    p[a->a_except_table_off++] = byte;\n}\n\n#define CONTINUATION_BIT 64\n\nstatic void\nassemble_emit_exception_table_item(struct assembler *a, int value, int msb)\n{\n    assert ((msb | 128) == 128);\n    assert(value >= 0 && value < (1 << 30));\n    if (value >= 1 << 24) {\n        write_except_byte(a, (value >> 24) | CONTINUATION_BIT | msb);\n        msb = 0;\n    }\n    if (value >= 1 << 18) {\n        write_except_byte(a, ((value >> 18)&0x3f) | CONTINUATION_BIT | msb);\n        msb = 0;\n    }\n    if (value >= 1 << 12) {\n        write_except_byte(a, ((value >> 12)&0x3f) | CONTINUATION_BIT | msb);\n        msb = 0;\n    }\n    if (value >= 1 << 6) {\n        write_except_byte(a, ((value >> 6)&0x3f) | CONTINUATION_BIT | msb);\n        msb = 0;\n    }\n    write_except_byte(a, (value&0x3f) | msb);\n}\n\n/* See Objects/exception_handling_notes.txt for details of layout */\n#define MAX_SIZE_OF_ENTRY 20\n\nstatic int\nassemble_emit_exception_table_entry(struct assembler *a, int start, int end,\n                                    _PyCompile_ExceptHandlerInfo *handler)\n{\n    Py_ssize_t len = PyBytes_GET_SIZE(a->a_except_table);\n    if (a->a_except_table_off + MAX_SIZE_OF_ENTRY >= len) {\n        RETURN_IF_ERROR(_PyBytes_Resize(&a->a_except_table, len * 2));\n    }\n    int size = end-start;\n    assert(end > start);\n    int target = handler->h_offset;\n    int depth = handler->h_startdepth - 1;\n    if (handler->h_preserve_lasti > 0) {\n        depth -= 1;\n    }\n    assert(depth >= 0);\n    int depth_lasti = (depth<<1) | handler->h_preserve_lasti;\n    assemble_emit_exception_table_item(a, start, (1<<7));\n    assemble_emit_exception_table_item(a, size, 0);\n    assemble_emit_exception_table_item(a, target, 0);\n    assemble_emit_exception_table_item(a, depth_lasti, 0);\n    return SUCCESS;\n}\n\nstatic int\nassemble_exception_table(struct assembler *a, instr_sequence *instrs)\n{\n    int ioffset = 0;\n    _PyCompile_ExceptHandlerInfo handler;\n    handler.h_offset = -1;\n    handler.h_startdepth = -1;\n    handler.h_preserve_lasti = -1;\n    int start = -1;\n    for (int i = 0; i < instrs->s_used; i++) {\n        instruction *instr = &instrs->s_instrs[i];\n        if (instr->i_except_handler_info.h_offset != handler.h_offset) {\n            if (handler.h_offset >= 0) {\n                RETURN_IF_ERROR(\n                    assemble_emit_exception_table_entry(a, start, ioffset, &handler));\n            }\n            start = ioffset;\n            handler = instr->i_except_handler_info;\n        }\n        ioffset += _PyCompile_InstrSize(instr->i_opcode, instr->i_oparg);\n    }\n    if (handler.h_offset >= 0) {\n        RETURN_IF_ERROR(assemble_emit_exception_table_entry(a, start, ioffset, &handler));\n    }\n    return SUCCESS;\n}\n\n\n/* Code location emitting code. See locations.md for a description of the format. */\n\n#define MSB 0x80\n\nstatic void\nwrite_location_byte(struct assembler* a, int val)\n{\n    PyBytes_AS_STRING(a->a_linetable)[a->a_location_off] = val&255;\n    a->a_location_off++;\n}\n\n\nstatic uint8_t *\nlocation_pointer(struct assembler* a)\n{\n    return (uint8_t *)PyBytes_AS_STRING(a->a_linetable) +\n        a->a_location_off;\n}\n\nstatic void\nwrite_location_first_byte(struct assembler* a, int code, int length)\n{\n    a->a_location_off += write_location_entry_start(\n        location_pointer(a), code, length);\n}\n\nstatic void\nwrite_location_varint(struct assembler* a, unsigned int val)\n{\n    uint8_t *ptr = location_pointer(a);\n    a->a_location_off += write_varint(ptr, val);\n}\n\n\nstatic void\nwrite_location_signed_varint(struct assembler* a, int val)\n{\n    uint8_t *ptr = location_pointer(a);\n    a->a_location_off += write_signed_varint(ptr, val);\n}\n\nstatic void\nwrite_location_info_short_form(struct assembler* a, int length, int column, int end_column)\n{\n    assert(length > 0 &&  length <= 8);\n    int column_low_bits = column & 7;\n    int column_group = column >> 3;\n    assert(column < 80);\n    assert(end_column >= column);\n    assert(end_column - column < 16);\n    write_location_first_byte(a, PY_CODE_LOCATION_INFO_SHORT0 + column_group, length);\n    write_location_byte(a, (column_low_bits << 4) | (end_column - column));\n}\n\nstatic void\nwrite_location_info_oneline_form(struct assembler* a, int length, int line_delta, int column, int end_column)\n{\n    assert(length > 0 &&  length <= 8);\n    assert(line_delta >= 0 && line_delta < 3);\n    assert(column < 128);\n    assert(end_column < 128);\n    write_location_first_byte(a, PY_CODE_LOCATION_INFO_ONE_LINE0 + line_delta, length);\n    write_location_byte(a, column);\n    write_location_byte(a, end_column);\n}\n\nstatic void\nwrite_location_info_long_form(struct assembler* a, location loc, int length)\n{\n    assert(length > 0 &&  length <= 8);\n    write_location_first_byte(a, PY_CODE_LOCATION_INFO_LONG, length);\n    write_location_signed_varint(a, loc.lineno - a->a_lineno);\n    assert(loc.end_lineno >= loc.lineno);\n    write_location_varint(a, loc.end_lineno - loc.lineno);\n    write_location_varint(a, loc.col_offset + 1);\n    write_location_varint(a, loc.end_col_offset + 1);\n}\n\nstatic void\nwrite_location_info_none(struct assembler* a, int length)\n{\n    write_location_first_byte(a, PY_CODE_LOCATION_INFO_NONE, length);\n}\n\nstatic void\nwrite_location_info_no_column(struct assembler* a, int length, int line_delta)\n{\n    write_location_first_byte(a, PY_CODE_LOCATION_INFO_NO_COLUMNS, length);\n    write_location_signed_varint(a, line_delta);\n}\n\n#define THEORETICAL_MAX_ENTRY_SIZE 25 /* 1 + 6 + 6 + 6 + 6 */\n\n\nstatic int\nwrite_location_info_entry(struct assembler* a, location loc, int isize)\n{\n    Py_ssize_t len = PyBytes_GET_SIZE(a->a_linetable);\n    if (a->a_location_off + THEORETICAL_MAX_ENTRY_SIZE >= len) {\n        assert(len > THEORETICAL_MAX_ENTRY_SIZE);\n        RETURN_IF_ERROR(_PyBytes_Resize(&a->a_linetable, len*2));\n    }\n    if (loc.lineno < 0) {\n        write_location_info_none(a, isize);\n        return SUCCESS;\n    }\n    int line_delta = loc.lineno - a->a_lineno;\n    int column = loc.col_offset;\n    int end_column = loc.end_col_offset;\n    assert(column >= -1);\n    assert(end_column >= -1);\n    if (column < 0 || end_column < 0) {\n        if (loc.end_lineno == loc.lineno || loc.end_lineno == -1) {\n            write_location_info_no_column(a, isize, line_delta);\n            a->a_lineno = loc.lineno;\n            return SUCCESS;\n        }\n    }\n    else if (loc.end_lineno == loc.lineno) {\n        if (line_delta == 0 && column < 80 && end_column - column < 16 && end_column >= column) {\n            write_location_info_short_form(a, isize, column, end_column);\n            return SUCCESS;\n        }\n        if (line_delta >= 0 && line_delta < 3 && column < 128 && end_column < 128) {\n            write_location_info_oneline_form(a, isize, line_delta, column, end_column);\n            a->a_lineno = loc.lineno;\n            return SUCCESS;\n        }\n    }\n    write_location_info_long_form(a, loc, isize);\n    a->a_lineno = loc.lineno;\n    return SUCCESS;\n}\n\nstatic int\nassemble_emit_location(struct assembler* a, location loc, int isize)\n{\n    if (isize == 0) {\n        return SUCCESS;\n    }\n    while (isize > 8) {\n        RETURN_IF_ERROR(write_location_info_entry(a, loc, 8));\n        isize -= 8;\n    }\n    return write_location_info_entry(a, loc, isize);\n}\n\nstatic int\nassemble_location_info(struct assembler *a, instr_sequence *instrs,\n                       int firstlineno)\n{\n    a->a_lineno = firstlineno;\n    location loc = NO_LOCATION;\n    int size = 0;\n    for (int i = 0; i < instrs->s_used; i++) {\n        instruction *instr = &instrs->s_instrs[i];\n        if (!same_location(loc, instr->i_loc)) {\n                RETURN_IF_ERROR(assemble_emit_location(a, loc, size));\n                loc = instr->i_loc;\n                size = 0;\n        }\n        size += _PyCompile_InstrSize(instr->i_opcode, instr->i_oparg);\n    }\n    RETURN_IF_ERROR(assemble_emit_location(a, loc, size));\n    return SUCCESS;\n}\n\nstatic void\nwrite_instr(_Py_CODEUNIT *codestr, instruction *instr, int ilen)\n{\n    int opcode = instr->i_opcode;\n    assert(!IS_PSEUDO_OPCODE(opcode));\n    int oparg = instr->i_oparg;\n    assert(HAS_ARG(opcode) || oparg == 0);\n    int caches = _PyOpcode_Caches[opcode];\n    switch (ilen - caches) {\n        case 4:\n            codestr->op.code = EXTENDED_ARG;\n            codestr->op.arg = (oparg >> 24) & 0xFF;\n            codestr++;\n            /* fall through */\n        case 3:\n            codestr->op.code = EXTENDED_ARG;\n            codestr->op.arg = (oparg >> 16) & 0xFF;\n            codestr++;\n            /* fall through */\n        case 2:\n            codestr->op.code = EXTENDED_ARG;\n            codestr->op.arg = (oparg >> 8) & 0xFF;\n            codestr++;\n            /* fall through */\n        case 1:\n            codestr->op.code = opcode;\n            codestr->op.arg = oparg & 0xFF;\n            codestr++;\n            break;\n        default:\n            Py_UNREACHABLE();\n    }\n    while (caches--) {\n        codestr->op.code = CACHE;\n        codestr->op.arg = 0;\n        codestr++;\n    }\n}\n\n/* assemble_emit_instr()\n   Extend the bytecode with a new instruction.\n   Update lnotab if necessary.\n*/\n\nstatic int\nassemble_emit_instr(struct assembler *a, instruction *instr)\n{\n    Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode);\n    _Py_CODEUNIT *code;\n\n    int size = _PyCompile_InstrSize(instr->i_opcode, instr->i_oparg);\n    if (a->a_offset + size >= len / (int)sizeof(_Py_CODEUNIT)) {\n        if (len > PY_SSIZE_T_MAX / 2) {\n            return ERROR;\n        }\n        RETURN_IF_ERROR(_PyBytes_Resize(&a->a_bytecode, len * 2));\n    }\n    code = (_Py_CODEUNIT *)PyBytes_AS_STRING(a->a_bytecode) + a->a_offset;\n    a->a_offset += size;\n    write_instr(code, instr, size);\n    return SUCCESS;\n}\n\nstatic int\nassemble_emit(struct assembler *a, instr_sequence *instrs,\n              int first_lineno, PyObject *const_cache)\n{\n    RETURN_IF_ERROR(assemble_init(a, first_lineno));\n\n    for (int i = 0; i < instrs->s_used; i++) {\n        instruction *instr = &instrs->s_instrs[i];\n        RETURN_IF_ERROR(assemble_emit_instr(a, instr));\n    }\n\n    RETURN_IF_ERROR(assemble_location_info(a, instrs, a->a_lineno));\n\n    RETURN_IF_ERROR(assemble_exception_table(a, instrs));\n\n    RETURN_IF_ERROR(_PyBytes_Resize(&a->a_except_table, a->a_except_table_off));\n    RETURN_IF_ERROR(_PyCompile_ConstCacheMergeOne(const_cache, &a->a_except_table));\n\n    RETURN_IF_ERROR(_PyBytes_Resize(&a->a_linetable, a->a_location_off));\n    RETURN_IF_ERROR(_PyCompile_ConstCacheMergeOne(const_cache, &a->a_linetable));\n\n    RETURN_IF_ERROR(_PyBytes_Resize(&a->a_bytecode, a->a_offset * sizeof(_Py_CODEUNIT)));\n    RETURN_IF_ERROR(_PyCompile_ConstCacheMergeOne(const_cache, &a->a_bytecode));\n    return SUCCESS;\n}\n\nstatic PyObject *\ndict_keys_inorder(PyObject *dict, Py_ssize_t offset)\n{\n    PyObject *tuple, *k, *v;\n    Py_ssize_t i, pos = 0, size = PyDict_GET_SIZE(dict);\n\n    tuple = PyTuple_New(size);\n    if (tuple == NULL)\n        return NULL;\n    while (PyDict_Next(dict, &pos, &k, &v)) {\n        i = PyLong_AS_LONG(v);\n        assert((i - offset) < size);\n        assert((i - offset) >= 0);\n        PyTuple_SET_ITEM(tuple, i - offset, Py_NewRef(k));\n    }\n    return tuple;\n}\n\n// This is in codeobject.c.\nextern void _Py_set_localsplus_info(int, PyObject *, unsigned char,\n                                   PyObject *, PyObject *);\n\nstatic void\ncompute_localsplus_info(_PyCompile_CodeUnitMetadata *umd, int nlocalsplus,\n                        PyObject *names, PyObject *kinds)\n{\n    PyObject *k, *v;\n    Py_ssize_t pos = 0;\n    while (PyDict_Next(umd->u_varnames, &pos, &k, &v)) {\n        int offset = (int)PyLong_AS_LONG(v);\n        assert(offset >= 0);\n        assert(offset < nlocalsplus);\n        // For now we do not distinguish arg kinds.\n        _PyLocals_Kind kind = CO_FAST_LOCAL;\n        if (PyDict_Contains(umd->u_fasthidden, k)) {\n            kind |= CO_FAST_HIDDEN;\n        }\n        if (PyDict_GetItem(umd->u_cellvars, k) != NULL) {\n            kind |= CO_FAST_CELL;\n        }\n        _Py_set_localsplus_info(offset, k, kind, names, kinds);\n    }\n    int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);\n\n    // This counter mirrors the fix done in fix_cell_offsets().\n    int numdropped = 0;\n    pos = 0;\n    while (PyDict_Next(umd->u_cellvars, &pos, &k, &v)) {\n        if (PyDict_GetItem(umd->u_varnames, k) != NULL) {\n            // Skip cells that are already covered by locals.\n            numdropped += 1;\n            continue;\n        }\n        int offset = (int)PyLong_AS_LONG(v);\n        assert(offset >= 0);\n        offset += nlocals - numdropped;\n        assert(offset < nlocalsplus);\n        _Py_set_localsplus_info(offset, k, CO_FAST_CELL, names, kinds);\n    }\n\n    pos = 0;\n    while (PyDict_Next(umd->u_freevars, &pos, &k, &v)) {\n        int offset = (int)PyLong_AS_LONG(v);\n        assert(offset >= 0);\n        offset += nlocals - numdropped;\n        assert(offset < nlocalsplus);\n        _Py_set_localsplus_info(offset, k, CO_FAST_FREE, names, kinds);\n    }\n}\n\nstatic PyCodeObject *\nmakecode(_PyCompile_CodeUnitMetadata *umd, struct assembler *a, PyObject *const_cache,\n         PyObject *constslist, int maxdepth, int nlocalsplus, int code_flags,\n         PyObject *filename)\n{\n    PyCodeObject *co = NULL;\n    PyObject *names = NULL;\n    PyObject *consts = NULL;\n    PyObject *localsplusnames = NULL;\n    PyObject *localspluskinds = NULL;\n    names = dict_keys_inorder(umd->u_names, 0);\n    if (!names) {\n        goto error;\n    }\n    if (_PyCompile_ConstCacheMergeOne(const_cache, &names) < 0) {\n        goto error;\n    }\n\n    consts = PyList_AsTuple(constslist); /* PyCode_New requires a tuple */\n    if (consts == NULL) {\n        goto error;\n    }\n    if (_PyCompile_ConstCacheMergeOne(const_cache, &consts) < 0) {\n        goto error;\n    }\n\n    assert(umd->u_posonlyargcount < INT_MAX);\n    assert(umd->u_argcount < INT_MAX);\n    assert(umd->u_kwonlyargcount < INT_MAX);\n    int posonlyargcount = (int)umd->u_posonlyargcount;\n    int posorkwargcount = (int)umd->u_argcount;\n    assert(INT_MAX - posonlyargcount - posorkwargcount > 0);\n    int kwonlyargcount = (int)umd->u_kwonlyargcount;\n\n    localsplusnames = PyTuple_New(nlocalsplus);\n    if (localsplusnames == NULL) {\n        goto error;\n    }\n    localspluskinds = PyBytes_FromStringAndSize(NULL, nlocalsplus);\n    if (localspluskinds == NULL) {\n        goto error;\n    }\n    compute_localsplus_info(umd, nlocalsplus, localsplusnames, localspluskinds);\n\n    struct _PyCodeConstructor con = {\n        .filename = filename,\n        .name = umd->u_name,\n        .qualname = umd->u_qualname ? umd->u_qualname : umd->u_name,\n        .flags = code_flags,\n\n        .code = a->a_bytecode,\n        .firstlineno = umd->u_firstlineno,\n        .linetable = a->a_linetable,\n\n        .consts = consts,\n        .names = names,\n\n        .localsplusnames = localsplusnames,\n        .localspluskinds = localspluskinds,\n\n        .argcount = posonlyargcount + posorkwargcount,\n        .posonlyargcount = posonlyargcount,\n        .kwonlyargcount = kwonlyargcount,\n\n        .stacksize = maxdepth,\n\n        .exceptiontable = a->a_except_table,\n    };\n\n   if (_PyCode_Validate(&con) < 0) {\n        goto error;\n    }\n\n    if (_PyCompile_ConstCacheMergeOne(const_cache, &localsplusnames) < 0) {\n        goto error;\n    }\n    con.localsplusnames = localsplusnames;\n\n    co = _PyCode_New(&con);\n    if (co == NULL) {\n        goto error;\n    }\n\nerror:\n    Py_XDECREF(names);\n    Py_XDECREF(consts);\n    Py_XDECREF(localsplusnames);\n    Py_XDECREF(localspluskinds);\n    return co;\n}\n\n\nPyCodeObject *\n_PyAssemble_MakeCodeObject(_PyCompile_CodeUnitMetadata *umd, PyObject *const_cache,\n                           PyObject *consts, int maxdepth, instr_sequence *instrs,\n                           int nlocalsplus, int code_flags, PyObject *filename)\n{\n    PyCodeObject *co = NULL;\n\n    struct assembler a;\n    int res = assemble_emit(&a, instrs, umd->u_firstlineno, const_cache);\n    if (res == SUCCESS) {\n        co = makecode(umd, &a, const_cache, consts, maxdepth, nlocalsplus,\n                      code_flags, filename);\n    }\n    assemble_free(&a);\n    return co;\n}\n"
  },
  {
    "path": "Ast.c",
    "content": "/*\n * This file exposes PyAST_Validate interface to check the integrity\n * of the given abstract syntax tree (potentially constructed manually).\n */\n#include \"Python.h\"\n#include \"pycore_ast.h\"           // asdl_stmt_seq\n#include \"pycore_pystate.h\"       // _PyThreadState_GET()\n\n#include <assert.h>\n#include <stdbool.h>\n\nstruct validator {\n    int recursion_depth;            /* current recursion depth */\n    int recursion_limit;            /* recursion limit */\n};\n\nstatic int validate_stmts(struct validator *, asdl_stmt_seq *);\nstatic int validate_exprs(struct validator *, asdl_expr_seq *, expr_context_ty, int);\nstatic int validate_patterns(struct validator *, asdl_pattern_seq *, int);\nstatic int validate_type_params(struct validator *, asdl_type_param_seq *);\nstatic int _validate_nonempty_seq(asdl_seq *, const char *, const char *);\nstatic int validate_stmt(struct validator *, stmt_ty);\nstatic int validate_expr(struct validator *, expr_ty, expr_context_ty);\nstatic int validate_pattern(struct validator *, pattern_ty, int);\nstatic int validate_typeparam(struct validator *, type_param_ty);\n\n#define VALIDATE_POSITIONS(node) \\\n    if (node->lineno > node->end_lineno) { \\\n        PyErr_Format(PyExc_ValueError, \\\n                     \"AST node line range (%d, %d) is not valid\", \\\n                     node->lineno, node->end_lineno); \\\n        return 0; \\\n    } \\\n    if ((node->lineno < 0 && node->end_lineno != node->lineno) || \\\n        (node->col_offset < 0 && node->col_offset != node->end_col_offset)) { \\\n        PyErr_Format(PyExc_ValueError, \\\n                     \"AST node column range (%d, %d) for line range (%d, %d) is not valid\", \\\n                     node->col_offset, node->end_col_offset, node->lineno, node->end_lineno); \\\n        return 0; \\\n    } \\\n    if (node->lineno == node->end_lineno && node->col_offset > node->end_col_offset) { \\\n        PyErr_Format(PyExc_ValueError, \\\n                     \"line %d, column %d-%d is not a valid range\", \\\n                     node->lineno, node->col_offset, node->end_col_offset); \\\n        return 0; \\\n    }\n\nstatic int\nvalidate_name(PyObject *name)\n{\n    assert(!PyErr_Occurred());\n    assert(PyUnicode_Check(name));\n    static const char * const forbidden[] = {\n        \"None\",\n        \"True\",\n        \"False\",\n        NULL\n    };\n    for (int i = 0; forbidden[i] != NULL; i++) {\n        if (_PyUnicode_EqualToASCIIString(name, forbidden[i])) {\n            PyErr_Format(PyExc_ValueError, \"identifier field can't represent '%s' constant\", forbidden[i]);\n            return 0;\n        }\n    }\n    return 1;\n}\n\nstatic int\nvalidate_comprehension(struct validator *state, asdl_comprehension_seq *gens)\n{\n    assert(!PyErr_Occurred());\n    if (!asdl_seq_LEN(gens)) {\n        PyErr_SetString(PyExc_ValueError, \"comprehension with no generators\");\n        return 0;\n    }\n    for (Py_ssize_t i = 0; i < asdl_seq_LEN(gens); i++) {\n        comprehension_ty comp = asdl_seq_GET(gens, i);\n        if (!validate_expr(state, comp->target, Store) ||\n            !validate_expr(state, comp->iter, Load) ||\n            !validate_exprs(state, comp->ifs, Load, 0))\n            return 0;\n    }\n    return 1;\n}\n\nstatic int\nvalidate_keywords(struct validator *state, asdl_keyword_seq *keywords)\n{\n    assert(!PyErr_Occurred());\n    for (Py_ssize_t i = 0; i < asdl_seq_LEN(keywords); i++)\n        if (!validate_expr(state, (asdl_seq_GET(keywords, i))->value, Load))\n            return 0;\n    return 1;\n}\n\nstatic int\nvalidate_args(struct validator *state, asdl_arg_seq *args)\n{\n    assert(!PyErr_Occurred());\n    for (Py_ssize_t i = 0; i < asdl_seq_LEN(args); i++) {\n        arg_ty arg = asdl_seq_GET(args, i);\n        VALIDATE_POSITIONS(arg);\n        if (arg->annotation && !validate_expr(state, arg->annotation, Load))\n            return 0;\n    }\n    return 1;\n}\n\nstatic const char *\nexpr_context_name(expr_context_ty ctx)\n{\n    switch (ctx) {\n    case Load:\n        return \"Load\";\n    case Store:\n        return \"Store\";\n    case Del:\n        return \"Del\";\n    // No default case so compiler emits warning for unhandled cases\n    }\n    Py_UNREACHABLE();\n}\n\nstatic int\nvalidate_arguments(struct validator *state, arguments_ty args)\n{\n    assert(!PyErr_Occurred());\n    if (!validate_args(state, args->posonlyargs) || !validate_args(state, args->args)) {\n        return 0;\n    }\n    if (args->vararg && args->vararg->annotation\n        && !validate_expr(state, args->vararg->annotation, Load)) {\n            return 0;\n    }\n    if (!validate_args(state, args->kwonlyargs))\n        return 0;\n    if (args->kwarg && args->kwarg->annotation\n        && !validate_expr(state, args->kwarg->annotation, Load)) {\n            return 0;\n    }\n    if (asdl_seq_LEN(args->defaults) > asdl_seq_LEN(args->posonlyargs) + asdl_seq_LEN(args->args)) {\n        PyErr_SetString(PyExc_ValueError, \"more positional defaults than args on arguments\");\n        return 0;\n    }\n    if (asdl_seq_LEN(args->kw_defaults) != asdl_seq_LEN(args->kwonlyargs)) {\n        PyErr_SetString(PyExc_ValueError, \"length of kwonlyargs is not the same as \"\n                        \"kw_defaults on arguments\");\n        return 0;\n    }\n    return validate_exprs(state, args->defaults, Load, 0) && validate_exprs(state, args->kw_defaults, Load, 1);\n}\n\nstatic int\nvalidate_constant(struct validator *state, PyObject *value)\n{\n    assert(!PyErr_Occurred());\n    if (value == Py_None || value == Py_Ellipsis)\n        return 1;\n\n    if (PyLong_CheckExact(value)\n            || PyFloat_CheckExact(value)\n            || PyComplex_CheckExact(value)\n            || PyBool_Check(value)\n            || PyUnicode_CheckExact(value)\n            || PyBytes_CheckExact(value))\n        return 1;\n\n    if (PyTuple_CheckExact(value) || PyFrozenSet_CheckExact(value)) {\n        if (++state->recursion_depth > state->recursion_limit) {\n            PyErr_SetString(PyExc_RecursionError,\n                            \"maximum recursion depth exceeded during compilation\");\n            return 0;\n        }\n\n        PyObject *it = PyObject_GetIter(value);\n        if (it == NULL)\n            return 0;\n\n        while (1) {\n            PyObject *item = PyIter_Next(it);\n            if (item == NULL) {\n                if (PyErr_Occurred()) {\n                    Py_DECREF(it);\n                    return 0;\n                }\n                break;\n            }\n\n            if (!validate_constant(state, item)) {\n                Py_DECREF(it);\n                Py_DECREF(item);\n                return 0;\n            }\n            Py_DECREF(item);\n        }\n\n        Py_DECREF(it);\n        --state->recursion_depth;\n        return 1;\n    }\n\n    if (!PyErr_Occurred()) {\n        PyErr_Format(PyExc_TypeError,\n                     \"got an invalid type in Constant: %s\",\n                     _PyType_Name(Py_TYPE(value)));\n    }\n    return 0;\n}\n\nstatic int\nvalidate_expr(struct validator *state, expr_ty exp, expr_context_ty ctx)\n{\n    assert(!PyErr_Occurred());\n    VALIDATE_POSITIONS(exp);\n    int ret = -1;\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n                        \"maximum recursion depth exceeded during compilation\");\n        return 0;\n    }\n    int check_ctx = 1;\n    expr_context_ty actual_ctx;\n\n    /* First check expression context. */\n    switch (exp->kind) {\n    case Attribute_kind:\n        actual_ctx = exp->v.Attribute.ctx;\n        break;\n    case Subscript_kind:\n        actual_ctx = exp->v.Subscript.ctx;\n        break;\n    case Starred_kind:\n        actual_ctx = exp->v.Starred.ctx;\n        break;\n    case Name_kind:\n        if (!validate_name(exp->v.Name.id)) {\n            return 0;\n        }\n        actual_ctx = exp->v.Name.ctx;\n        break;\n    case List_kind:\n        actual_ctx = exp->v.List.ctx;\n        break;\n    case Tuple_kind:\n        actual_ctx = exp->v.Tuple.ctx;\n        break;\n    default:\n        if (ctx != Load) {\n            PyErr_Format(PyExc_ValueError, \"expression which can't be \"\n                         \"assigned to in %s context\", expr_context_name(ctx));\n            return 0;\n        }\n        check_ctx = 0;\n        /* set actual_ctx to prevent gcc warning */\n        actual_ctx = 0;\n    }\n    if (check_ctx && actual_ctx != ctx) {\n        PyErr_Format(PyExc_ValueError, \"expression must have %s context but has %s instead\",\n                     expr_context_name(ctx), expr_context_name(actual_ctx));\n        return 0;\n    }\n\n    /* Now validate expression. */\n    switch (exp->kind) {\n    case BoolOp_kind:\n        if (asdl_seq_LEN(exp->v.BoolOp.values) < 2) {\n            PyErr_SetString(PyExc_ValueError, \"BoolOp with less than 2 values\");\n            return 0;\n        }\n        ret = validate_exprs(state, exp->v.BoolOp.values, Load, 0);\n        break;\n    case BinOp_kind:\n        ret = validate_expr(state, exp->v.BinOp.left, Load) &&\n            validate_expr(state, exp->v.BinOp.right, Load);\n        break;\n    case UnaryOp_kind:\n        ret = validate_expr(state, exp->v.UnaryOp.operand, Load);\n        break;\n    case Lambda_kind:\n        ret = validate_arguments(state, exp->v.Lambda.args) &&\n            validate_expr(state, exp->v.Lambda.body, Load);\n        break;\n    case IfExp_kind:\n        ret = validate_expr(state, exp->v.IfExp.test, Load) &&\n            validate_expr(state, exp->v.IfExp.body, Load) &&\n            validate_expr(state, exp->v.IfExp.orelse, Load);\n        break;\n    case Dict_kind:\n        if (asdl_seq_LEN(exp->v.Dict.keys) != asdl_seq_LEN(exp->v.Dict.values)) {\n            PyErr_SetString(PyExc_ValueError,\n                            \"Dict doesn't have the same number of keys as values\");\n            return 0;\n        }\n        /* null_ok=1 for keys expressions to allow dict unpacking to work in\n           dict literals, i.e. ``{**{a:b}}`` */\n        ret = validate_exprs(state, exp->v.Dict.keys, Load, /*null_ok=*/ 1) &&\n            validate_exprs(state, exp->v.Dict.values, Load, /*null_ok=*/ 0);\n        break;\n    case Set_kind:\n        ret = validate_exprs(state, exp->v.Set.elts, Load, 0);\n        break;\n#define COMP(NAME) \\\n        case NAME ## _kind: \\\n            ret = validate_comprehension(state, exp->v.NAME.generators) && \\\n                validate_expr(state, exp->v.NAME.elt, Load); \\\n            break;\n    COMP(ListComp)\n    COMP(SetComp)\n    COMP(GeneratorExp)\n#undef COMP\n    case DictComp_kind:\n        ret = validate_comprehension(state, exp->v.DictComp.generators) &&\n            validate_expr(state, exp->v.DictComp.key, Load) &&\n            validate_expr(state, exp->v.DictComp.value, Load);\n        break;\n    case Yield_kind:\n        ret = !exp->v.Yield.value || validate_expr(state, exp->v.Yield.value, Load);\n        break;\n    case YieldFrom_kind:\n        ret = validate_expr(state, exp->v.YieldFrom.value, Load);\n        break;\n    case Await_kind:\n        ret = validate_expr(state, exp->v.Await.value, Load);\n        break;\n    case Compare_kind:\n        if (!asdl_seq_LEN(exp->v.Compare.comparators)) {\n            PyErr_SetString(PyExc_ValueError, \"Compare with no comparators\");\n            return 0;\n        }\n        if (asdl_seq_LEN(exp->v.Compare.comparators) !=\n            asdl_seq_LEN(exp->v.Compare.ops)) {\n            PyErr_SetString(PyExc_ValueError, \"Compare has a different number \"\n                            \"of comparators and operands\");\n            return 0;\n        }\n        ret = validate_exprs(state, exp->v.Compare.comparators, Load, 0) &&\n            validate_expr(state, exp->v.Compare.left, Load);\n        break;\n    case Call_kind:\n        ret = validate_expr(state, exp->v.Call.func, Load) &&\n            validate_exprs(state, exp->v.Call.args, Load, 0) &&\n            validate_keywords(state, exp->v.Call.keywords);\n        break;\n    case Constant_kind:\n        if (!validate_constant(state, exp->v.Constant.value)) {\n            return 0;\n        }\n        ret = 1;\n        break;\n    case JoinedStr_kind:\n        ret = validate_exprs(state, exp->v.JoinedStr.values, Load, 0);\n        break;\n    case FormattedValue_kind:\n        if (validate_expr(state, exp->v.FormattedValue.value, Load) == 0)\n            return 0;\n        if (exp->v.FormattedValue.format_spec) {\n            ret = validate_expr(state, exp->v.FormattedValue.format_spec, Load);\n            break;\n        }\n        ret = 1;\n        break;\n    case Attribute_kind:\n        ret = validate_expr(state, exp->v.Attribute.value, Load);\n        break;\n    case Subscript_kind:\n        ret = validate_expr(state, exp->v.Subscript.slice, Load) &&\n            validate_expr(state, exp->v.Subscript.value, Load);\n        break;\n    case Starred_kind:\n        ret = validate_expr(state, exp->v.Starred.value, ctx);\n        break;\n    case Slice_kind:\n        ret = (!exp->v.Slice.lower || validate_expr(state, exp->v.Slice.lower, Load)) &&\n            (!exp->v.Slice.upper || validate_expr(state, exp->v.Slice.upper, Load)) &&\n            (!exp->v.Slice.step || validate_expr(state, exp->v.Slice.step, Load));\n        break;\n    case List_kind:\n        ret = validate_exprs(state, exp->v.List.elts, ctx, 0);\n        break;\n    case Tuple_kind:\n        ret = validate_exprs(state, exp->v.Tuple.elts, ctx, 0);\n        break;\n    case NamedExpr_kind:\n        ret = validate_expr(state, exp->v.NamedExpr.value, Load);\n        break;\n    /* This last case doesn't have any checking. */\n    case Name_kind:\n        ret = 1;\n        break;\n    // No default case so compiler emits warning for unhandled cases\n    }\n    if (ret < 0) {\n        PyErr_SetString(PyExc_SystemError, \"unexpected expression\");\n        ret = 0;\n    }\n    state->recursion_depth--;\n    return ret;\n}\n\n\n// Note: the ensure_literal_* functions are only used to validate a restricted\n//       set of non-recursive literals that have already been checked with\n//       validate_expr, so they don't accept the validator state\nstatic int\nensure_literal_number(expr_ty exp, bool allow_real, bool allow_imaginary)\n{\n    assert(exp->kind == Constant_kind);\n    PyObject *value = exp->v.Constant.value;\n    return (allow_real && PyFloat_CheckExact(value)) ||\n           (allow_real && PyLong_CheckExact(value)) ||\n           (allow_imaginary && PyComplex_CheckExact(value));\n}\n\nstatic int\nensure_literal_negative(expr_ty exp, bool allow_real, bool allow_imaginary)\n{\n    assert(exp->kind == UnaryOp_kind);\n    // Must be negation ...\n    if (exp->v.UnaryOp.op != USub) {\n        return 0;\n    }\n    // ... of a constant ...\n    expr_ty operand = exp->v.UnaryOp.operand;\n    if (operand->kind != Constant_kind) {\n        return 0;\n    }\n    // ... number\n    return ensure_literal_number(operand, allow_real, allow_imaginary);\n}\n\nstatic int\nensure_literal_complex(expr_ty exp)\n{\n    assert(exp->kind == BinOp_kind);\n    expr_ty left = exp->v.BinOp.left;\n    expr_ty right = exp->v.BinOp.right;\n    // Ensure op is addition or subtraction\n    if (exp->v.BinOp.op != Add && exp->v.BinOp.op != Sub) {\n        return 0;\n    }\n    // Check LHS is a real number (potentially signed)\n    switch (left->kind)\n    {\n        case Constant_kind:\n            if (!ensure_literal_number(left, /*real=*/true, /*imaginary=*/false)) {\n                return 0;\n            }\n            break;\n        case UnaryOp_kind:\n            if (!ensure_literal_negative(left, /*real=*/true, /*imaginary=*/false)) {\n                return 0;\n            }\n            break;\n        default:\n            return 0;\n    }\n    // Check RHS is an imaginary number (no separate sign allowed)\n    switch (right->kind)\n    {\n        case Constant_kind:\n            if (!ensure_literal_number(right, /*real=*/false, /*imaginary=*/true)) {\n                return 0;\n            }\n            break;\n        default:\n            return 0;\n    }\n    return 1;\n}\n\nstatic int\nvalidate_pattern_match_value(struct validator *state, expr_ty exp)\n{\n    assert(!PyErr_Occurred());\n    if (!validate_expr(state, exp, Load)) {\n        return 0;\n    }\n\n    switch (exp->kind)\n    {\n        case Constant_kind:\n            /* Ellipsis and immutable sequences are not allowed.\n               For True, False and None, MatchSingleton() should\n               be used */\n            if (!validate_expr(state, exp, Load)) {\n                return 0;\n            }\n            PyObject *literal = exp->v.Constant.value;\n            if (PyLong_CheckExact(literal) || PyFloat_CheckExact(literal) ||\n                PyBytes_CheckExact(literal) || PyComplex_CheckExact(literal) ||\n                PyUnicode_CheckExact(literal)) {\n                return 1;\n            }\n            PyErr_SetString(PyExc_ValueError,\n                            \"unexpected constant inside of a literal pattern\");\n            return 0;\n        case Attribute_kind:\n            // Constants and attribute lookups are always permitted\n            return 1;\n        case UnaryOp_kind:\n            // Negated numbers are permitted (whether real or imaginary)\n            // Compiler will complain if AST folding doesn't create a constant\n            if (ensure_literal_negative(exp, /*real=*/true, /*imaginary=*/true)) {\n                return 1;\n            }\n            break;\n        case BinOp_kind:\n            // Complex literals are permitted\n            // Compiler will complain if AST folding doesn't create a constant\n            if (ensure_literal_complex(exp)) {\n                return 1;\n            }\n            break;\n        case JoinedStr_kind:\n            // Handled in the later stages\n            return 1;\n        default:\n            break;\n    }\n    PyErr_SetString(PyExc_ValueError,\n                    \"patterns may only match literals and attribute lookups\");\n    return 0;\n}\n\nstatic int\nvalidate_capture(PyObject *name)\n{\n    assert(!PyErr_Occurred());\n    if (_PyUnicode_EqualToASCIIString(name, \"_\")) {\n        PyErr_Format(PyExc_ValueError, \"can't capture name '_' in patterns\");\n        return 0;\n    }\n    return validate_name(name);\n}\n\nstatic int\nvalidate_pattern(struct validator *state, pattern_ty p, int star_ok)\n{\n    assert(!PyErr_Occurred());\n    VALIDATE_POSITIONS(p);\n    int ret = -1;\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n                        \"maximum recursion depth exceeded during compilation\");\n        return 0;\n    }\n    switch (p->kind) {\n        case MatchValue_kind:\n            ret = validate_pattern_match_value(state, p->v.MatchValue.value);\n            break;\n        case MatchSingleton_kind:\n            ret = p->v.MatchSingleton.value == Py_None || PyBool_Check(p->v.MatchSingleton.value);\n            if (!ret) {\n                PyErr_SetString(PyExc_ValueError,\n                                \"MatchSingleton can only contain True, False and None\");\n            }\n            break;\n        case MatchSequence_kind:\n            ret = validate_patterns(state, p->v.MatchSequence.patterns, /*star_ok=*/1);\n            break;\n        case MatchMapping_kind:\n            if (asdl_seq_LEN(p->v.MatchMapping.keys) != asdl_seq_LEN(p->v.MatchMapping.patterns)) {\n                PyErr_SetString(PyExc_ValueError,\n                                \"MatchMapping doesn't have the same number of keys as patterns\");\n                ret = 0;\n                break;\n            }\n\n            if (p->v.MatchMapping.rest && !validate_capture(p->v.MatchMapping.rest)) {\n                ret = 0;\n                break;\n            }\n\n            asdl_expr_seq *keys = p->v.MatchMapping.keys;\n            for (Py_ssize_t i = 0; i < asdl_seq_LEN(keys); i++) {\n                expr_ty key = asdl_seq_GET(keys, i);\n                if (key->kind == Constant_kind) {\n                    PyObject *literal = key->v.Constant.value;\n                    if (literal == Py_None || PyBool_Check(literal)) {\n                        /* validate_pattern_match_value will ensure the key\n                           doesn't contain True, False and None but it is\n                           syntactically valid, so we will pass those on in\n                           a special case. */\n                        continue;\n                    }\n                }\n                if (!validate_pattern_match_value(state, key)) {\n                    ret = 0;\n                    break;\n                }\n            }\n            if (ret == 0) {\n                break;\n            }\n            ret = validate_patterns(state, p->v.MatchMapping.patterns, /*star_ok=*/0);\n            break;\n        case MatchClass_kind:\n            if (asdl_seq_LEN(p->v.MatchClass.kwd_attrs) != asdl_seq_LEN(p->v.MatchClass.kwd_patterns)) {\n                PyErr_SetString(PyExc_ValueError,\n                                \"MatchClass doesn't have the same number of keyword attributes as patterns\");\n                ret = 0;\n                break;\n            }\n            if (!validate_expr(state, p->v.MatchClass.cls, Load)) {\n                ret = 0;\n                break;\n            }\n\n            expr_ty cls = p->v.MatchClass.cls;\n            while (1) {\n                if (cls->kind == Name_kind) {\n                    break;\n                }\n                else if (cls->kind == Attribute_kind) {\n                    cls = cls->v.Attribute.value;\n                    continue;\n                }\n                else {\n                    PyErr_SetString(PyExc_ValueError,\n                                    \"MatchClass cls field can only contain Name or Attribute nodes.\");\n                    ret = 0;\n                    break;\n                }\n            }\n            if (ret == 0) {\n                break;\n            }\n\n            for (Py_ssize_t i = 0; i < asdl_seq_LEN(p->v.MatchClass.kwd_attrs); i++) {\n                PyObject *identifier = asdl_seq_GET(p->v.MatchClass.kwd_attrs, i);\n                if (!validate_name(identifier)) {\n                    ret = 0;\n                    break;\n                }\n            }\n            if (ret == 0) {\n                break;\n            }\n\n            if (!validate_patterns(state, p->v.MatchClass.patterns, /*star_ok=*/0)) {\n                ret = 0;\n                break;\n            }\n\n            ret = validate_patterns(state, p->v.MatchClass.kwd_patterns, /*star_ok=*/0);\n            break;\n        case MatchStar_kind:\n            if (!star_ok) {\n                PyErr_SetString(PyExc_ValueError, \"can't use MatchStar here\");\n                ret = 0;\n                break;\n            }\n            ret = p->v.MatchStar.name == NULL || validate_capture(p->v.MatchStar.name);\n            break;\n        case MatchAs_kind:\n            if (p->v.MatchAs.name && !validate_capture(p->v.MatchAs.name)) {\n                ret = 0;\n                break;\n            }\n            if (p->v.MatchAs.pattern == NULL) {\n                ret = 1;\n            }\n            else if (p->v.MatchAs.name == NULL) {\n                PyErr_SetString(PyExc_ValueError,\n                                \"MatchAs must specify a target name if a pattern is given\");\n                ret = 0;\n            }\n            else {\n                ret = validate_pattern(state, p->v.MatchAs.pattern, /*star_ok=*/0);\n            }\n            break;\n        case MatchOr_kind:\n            if (asdl_seq_LEN(p->v.MatchOr.patterns) < 2) {\n                PyErr_SetString(PyExc_ValueError,\n                                \"MatchOr requires at least 2 patterns\");\n                ret = 0;\n                break;\n            }\n            ret = validate_patterns(state, p->v.MatchOr.patterns, /*star_ok=*/0);\n            break;\n    // No default case, so the compiler will emit a warning if new pattern\n    // kinds are added without being handled here\n    }\n    if (ret < 0) {\n        PyErr_SetString(PyExc_SystemError, \"unexpected pattern\");\n        ret = 0;\n    }\n    state->recursion_depth--;\n    return ret;\n}\n\nstatic int\n_validate_nonempty_seq(asdl_seq *seq, const char *what, const char *owner)\n{\n    if (asdl_seq_LEN(seq))\n        return 1;\n    PyErr_Format(PyExc_ValueError, \"empty %s on %s\", what, owner);\n    return 0;\n}\n#define validate_nonempty_seq(seq, what, owner) _validate_nonempty_seq((asdl_seq*)seq, what, owner)\n\nstatic int\nvalidate_assignlist(struct validator *state, asdl_expr_seq *targets, expr_context_ty ctx)\n{\n    assert(!PyErr_Occurred());\n    return validate_nonempty_seq(targets, \"targets\", ctx == Del ? \"Delete\" : \"Assign\") &&\n        validate_exprs(state, targets, ctx, 0);\n}\n\nstatic int\nvalidate_body(struct validator *state, asdl_stmt_seq *body, const char *owner)\n{\n    assert(!PyErr_Occurred());\n    return validate_nonempty_seq(body, \"body\", owner) && validate_stmts(state, body);\n}\n\nstatic int\nvalidate_stmt(struct validator *state, stmt_ty stmt)\n{\n    assert(!PyErr_Occurred());\n    VALIDATE_POSITIONS(stmt);\n    int ret = -1;\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n                        \"maximum recursion depth exceeded during compilation\");\n        return 0;\n    }\n    switch (stmt->kind) {\n    case FunctionDef_kind:\n        ret = validate_body(state, stmt->v.FunctionDef.body, \"FunctionDef\") &&\n            validate_type_params(state, stmt->v.FunctionDef.type_params) &&\n            validate_arguments(state, stmt->v.FunctionDef.args) &&\n            validate_exprs(state, stmt->v.FunctionDef.decorator_list, Load, 0) &&\n            (!stmt->v.FunctionDef.returns ||\n             validate_expr(state, stmt->v.FunctionDef.returns, Load));\n        break;\n    case ClassDef_kind:\n        ret = validate_body(state, stmt->v.ClassDef.body, \"ClassDef\") &&\n            validate_type_params(state, stmt->v.ClassDef.type_params) &&\n            validate_exprs(state, stmt->v.ClassDef.bases, Load, 0) &&\n            validate_keywords(state, stmt->v.ClassDef.keywords) &&\n            validate_exprs(state, stmt->v.ClassDef.decorator_list, Load, 0);\n        break;\n    case Return_kind:\n        ret = !stmt->v.Return.value || validate_expr(state, stmt->v.Return.value, Load);\n        break;\n    case Delete_kind:\n        ret = validate_assignlist(state, stmt->v.Delete.targets, Del);\n        break;\n    case Assign_kind:\n        ret = validate_assignlist(state, stmt->v.Assign.targets, Store) &&\n            validate_expr(state, stmt->v.Assign.value, Load);\n        break;\n    case AugAssign_kind:\n        ret = validate_expr(state, stmt->v.AugAssign.target, Store) &&\n            validate_expr(state, stmt->v.AugAssign.value, Load);\n        break;\n    case AnnAssign_kind:\n        if (stmt->v.AnnAssign.target->kind != Name_kind &&\n            stmt->v.AnnAssign.simple) {\n            PyErr_SetString(PyExc_TypeError,\n                            \"AnnAssign with simple non-Name target\");\n            return 0;\n        }\n        ret = validate_expr(state, stmt->v.AnnAssign.target, Store) &&\n               (!stmt->v.AnnAssign.value ||\n                validate_expr(state, stmt->v.AnnAssign.value, Load)) &&\n               validate_expr(state, stmt->v.AnnAssign.annotation, Load);\n        break;\n    case TypeAlias_kind:\n        ret = validate_expr(state, stmt->v.TypeAlias.name, Store) &&\n            validate_type_params(state, stmt->v.TypeAlias.type_params) &&\n            validate_expr(state, stmt->v.TypeAlias.value, Load);\n        break;\n    case For_kind:\n        ret = validate_expr(state, stmt->v.For.target, Store) &&\n            validate_expr(state, stmt->v.For.iter, Load) &&\n            validate_body(state, stmt->v.For.body, \"For\") &&\n            validate_stmts(state, stmt->v.For.orelse);\n        break;\n    case AsyncFor_kind:\n        ret = validate_expr(state, stmt->v.AsyncFor.target, Store) &&\n            validate_expr(state, stmt->v.AsyncFor.iter, Load) &&\n            validate_body(state, stmt->v.AsyncFor.body, \"AsyncFor\") &&\n            validate_stmts(state, stmt->v.AsyncFor.orelse);\n        break;\n    case While_kind:\n        ret = validate_expr(state, stmt->v.While.test, Load) &&\n            validate_body(state, stmt->v.While.body, \"While\") &&\n            validate_stmts(state, stmt->v.While.orelse);\n        break;\n    case If_kind:\n        ret = validate_expr(state, stmt->v.If.test, Load) &&\n            validate_body(state, stmt->v.If.body, \"If\") &&\n            validate_stmts(state, stmt->v.If.orelse);\n        break;\n    case With_kind:\n        if (!validate_nonempty_seq(stmt->v.With.items, \"items\", \"With\"))\n            return 0;\n        for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.With.items); i++) {\n            withitem_ty item = asdl_seq_GET(stmt->v.With.items, i);\n            if (!validate_expr(state, item->context_expr, Load) ||\n                (item->optional_vars && !validate_expr(state, item->optional_vars, Store)))\n                return 0;\n        }\n        ret = validate_body(state, stmt->v.With.body, \"With\");\n        break;\n    case AsyncWith_kind:\n        if (!validate_nonempty_seq(stmt->v.AsyncWith.items, \"items\", \"AsyncWith\"))\n            return 0;\n        for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.AsyncWith.items); i++) {\n            withitem_ty item = asdl_seq_GET(stmt->v.AsyncWith.items, i);\n            if (!validate_expr(state, item->context_expr, Load) ||\n                (item->optional_vars && !validate_expr(state, item->optional_vars, Store)))\n                return 0;\n        }\n        ret = validate_body(state, stmt->v.AsyncWith.body, \"AsyncWith\");\n        break;\n    case Match_kind:\n        if (!validate_expr(state, stmt->v.Match.subject, Load)\n            || !validate_nonempty_seq(stmt->v.Match.cases, \"cases\", \"Match\")) {\n            return 0;\n        }\n        for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.Match.cases); i++) {\n            match_case_ty m = asdl_seq_GET(stmt->v.Match.cases, i);\n            if (!validate_pattern(state, m->pattern, /*star_ok=*/0)\n                || (m->guard && !validate_expr(state, m->guard, Load))\n                || !validate_body(state, m->body, \"match_case\")) {\n                return 0;\n            }\n        }\n        ret = 1;\n        break;\n    case Raise_kind:\n        if (stmt->v.Raise.exc) {\n            ret = validate_expr(state, stmt->v.Raise.exc, Load) &&\n                (!stmt->v.Raise.cause || validate_expr(state, stmt->v.Raise.cause, Load));\n            break;\n        }\n        if (stmt->v.Raise.cause) {\n            PyErr_SetString(PyExc_ValueError, \"Raise with cause but no exception\");\n            return 0;\n        }\n        ret = 1;\n        break;\n    case Try_kind:\n        if (!validate_body(state, stmt->v.Try.body, \"Try\"))\n            return 0;\n        if (!asdl_seq_LEN(stmt->v.Try.handlers) &&\n            !asdl_seq_LEN(stmt->v.Try.finalbody)) {\n            PyErr_SetString(PyExc_ValueError, \"Try has neither except handlers nor finalbody\");\n            return 0;\n        }\n        if (!asdl_seq_LEN(stmt->v.Try.handlers) &&\n            asdl_seq_LEN(stmt->v.Try.orelse)) {\n            PyErr_SetString(PyExc_ValueError, \"Try has orelse but no except handlers\");\n            return 0;\n        }\n        for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.Try.handlers); i++) {\n            excepthandler_ty handler = asdl_seq_GET(stmt->v.Try.handlers, i);\n            VALIDATE_POSITIONS(handler);\n            if ((handler->v.ExceptHandler.type &&\n                 !validate_expr(state, handler->v.ExceptHandler.type, Load)) ||\n                !validate_body(state, handler->v.ExceptHandler.body, \"ExceptHandler\"))\n                return 0;\n        }\n        ret = (!asdl_seq_LEN(stmt->v.Try.finalbody) ||\n                validate_stmts(state, stmt->v.Try.finalbody)) &&\n            (!asdl_seq_LEN(stmt->v.Try.orelse) ||\n             validate_stmts(state, stmt->v.Try.orelse));\n        break;\n    case TryStar_kind:\n        if (!validate_body(state, stmt->v.TryStar.body, \"TryStar\"))\n            return 0;\n        if (!asdl_seq_LEN(stmt->v.TryStar.handlers) &&\n            !asdl_seq_LEN(stmt->v.TryStar.finalbody)) {\n            PyErr_SetString(PyExc_ValueError, \"TryStar has neither except handlers nor finalbody\");\n            return 0;\n        }\n        if (!asdl_seq_LEN(stmt->v.TryStar.handlers) &&\n            asdl_seq_LEN(stmt->v.TryStar.orelse)) {\n            PyErr_SetString(PyExc_ValueError, \"TryStar has orelse but no except handlers\");\n            return 0;\n        }\n        for (Py_ssize_t i = 0; i < asdl_seq_LEN(stmt->v.TryStar.handlers); i++) {\n            excepthandler_ty handler = asdl_seq_GET(stmt->v.TryStar.handlers, i);\n            if ((handler->v.ExceptHandler.type &&\n                 !validate_expr(state, handler->v.ExceptHandler.type, Load)) ||\n                !validate_body(state, handler->v.ExceptHandler.body, \"ExceptHandler\"))\n                return 0;\n        }\n        ret = (!asdl_seq_LEN(stmt->v.TryStar.finalbody) ||\n                validate_stmts(state, stmt->v.TryStar.finalbody)) &&\n            (!asdl_seq_LEN(stmt->v.TryStar.orelse) ||\n             validate_stmts(state, stmt->v.TryStar.orelse));\n        break;\n    case Assert_kind:\n        ret = validate_expr(state, stmt->v.Assert.test, Load) &&\n            (!stmt->v.Assert.msg || validate_expr(state, stmt->v.Assert.msg, Load));\n        break;\n    case Import_kind:\n        ret = validate_nonempty_seq(stmt->v.Import.names, \"names\", \"Import\");\n        break;\n    case ImportFrom_kind:\n        if (stmt->v.ImportFrom.level < 0) {\n            PyErr_SetString(PyExc_ValueError, \"Negative ImportFrom level\");\n            return 0;\n        }\n        ret = validate_nonempty_seq(stmt->v.ImportFrom.names, \"names\", \"ImportFrom\");\n        break;\n    case Global_kind:\n        ret = validate_nonempty_seq(stmt->v.Global.names, \"names\", \"Global\");\n        break;\n    case Nonlocal_kind:\n        ret = validate_nonempty_seq(stmt->v.Nonlocal.names, \"names\", \"Nonlocal\");\n        break;\n    case Expr_kind:\n        ret = validate_expr(state, stmt->v.Expr.value, Load);\n        break;\n    case AsyncFunctionDef_kind:\n        ret = validate_body(state, stmt->v.AsyncFunctionDef.body, \"AsyncFunctionDef\") &&\n            validate_type_params(state, stmt->v.AsyncFunctionDef.type_params) &&\n            validate_arguments(state, stmt->v.AsyncFunctionDef.args) &&\n            validate_exprs(state, stmt->v.AsyncFunctionDef.decorator_list, Load, 0) &&\n            (!stmt->v.AsyncFunctionDef.returns ||\n             validate_expr(state, stmt->v.AsyncFunctionDef.returns, Load));\n        break;\n    case Pass_kind:\n    case Break_kind:\n    case Continue_kind:\n        ret = 1;\n        break;\n    // No default case so compiler emits warning for unhandled cases\n    }\n    if (ret < 0) {\n        PyErr_SetString(PyExc_SystemError, \"unexpected statement\");\n        ret = 0;\n    }\n    state->recursion_depth--;\n    return ret;\n}\n\nstatic int\nvalidate_stmts(struct validator *state, asdl_stmt_seq *seq)\n{\n    assert(!PyErr_Occurred());\n    for (Py_ssize_t i = 0; i < asdl_seq_LEN(seq); i++) {\n        stmt_ty stmt = asdl_seq_GET(seq, i);\n        if (stmt) {\n            if (!validate_stmt(state, stmt))\n                return 0;\n        }\n        else {\n            PyErr_SetString(PyExc_ValueError,\n                            \"None disallowed in statement list\");\n            return 0;\n        }\n    }\n    return 1;\n}\n\nstatic int\nvalidate_exprs(struct validator *state, asdl_expr_seq *exprs, expr_context_ty ctx, int null_ok)\n{\n    assert(!PyErr_Occurred());\n    for (Py_ssize_t i = 0; i < asdl_seq_LEN(exprs); i++) {\n        expr_ty expr = asdl_seq_GET(exprs, i);\n        if (expr) {\n            if (!validate_expr(state, expr, ctx))\n                return 0;\n        }\n        else if (!null_ok) {\n            PyErr_SetString(PyExc_ValueError,\n                            \"None disallowed in expression list\");\n            return 0;\n        }\n\n    }\n    return 1;\n}\n\nstatic int\nvalidate_patterns(struct validator *state, asdl_pattern_seq *patterns, int star_ok)\n{\n    assert(!PyErr_Occurred());\n    for (Py_ssize_t i = 0; i < asdl_seq_LEN(patterns); i++) {\n        pattern_ty pattern = asdl_seq_GET(patterns, i);\n        if (!validate_pattern(state, pattern, star_ok)) {\n            return 0;\n        }\n    }\n    return 1;\n}\n\nstatic int\nvalidate_typeparam(struct validator *state, type_param_ty tp)\n{\n    VALIDATE_POSITIONS(tp);\n    int ret = -1;\n    switch (tp->kind) {\n        case TypeVar_kind:\n            ret = validate_name(tp->v.TypeVar.name) &&\n                (!tp->v.TypeVar.bound ||\n                 validate_expr(state, tp->v.TypeVar.bound, Load));\n            break;\n        case ParamSpec_kind:\n            ret = validate_name(tp->v.ParamSpec.name);\n            break;\n        case TypeVarTuple_kind:\n            ret = validate_name(tp->v.TypeVarTuple.name);\n            break;\n    }\n    return ret;\n}\n\nstatic int\nvalidate_type_params(struct validator *state, asdl_type_param_seq *tps)\n{\n    Py_ssize_t i;\n    for (i = 0; i < asdl_seq_LEN(tps); i++) {\n        type_param_ty tp = asdl_seq_GET(tps, i);\n        if (tp) {\n            if (!validate_typeparam(state, tp))\n                return 0;\n        }\n    }\n    return 1;\n}\n\n\n/* See comments in symtable.c. */\n#define COMPILER_STACK_FRAME_SCALE 3\n\nint\n_PyAST_Validate(mod_ty mod)\n{\n    assert(!PyErr_Occurred());\n    int res = -1;\n    struct validator state;\n    PyThreadState *tstate;\n    int starting_recursion_depth;\n\n    /* Setup recursion depth check counters */\n    tstate = _PyThreadState_GET();\n    if (!tstate) {\n        return 0;\n    }\n    /* Be careful here to prevent overflow. */\n    int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;\n    starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;\n    state.recursion_depth = starting_recursion_depth;\n    state.recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;\n\n    switch (mod->kind) {\n    case Module_kind:\n        res = validate_stmts(&state, mod->v.Module.body);\n        break;\n    case Interactive_kind:\n        res = validate_stmts(&state, mod->v.Interactive.body);\n        break;\n    case Expression_kind:\n        res = validate_expr(&state, mod->v.Expression.body, Load);\n        break;\n    case FunctionType_kind:\n        res = validate_exprs(&state, mod->v.FunctionType.argtypes, Load, /*null_ok=*/0) &&\n              validate_expr(&state, mod->v.FunctionType.returns, Load);\n        break;\n    // No default case so compiler emits warning for unhandled cases\n    }\n\n    if (res < 0) {\n        PyErr_SetString(PyExc_SystemError, \"impossible module node\");\n        return 0;\n    }\n\n    /* Check that the recursion depth counting balanced correctly */\n    if (res && state.recursion_depth != starting_recursion_depth) {\n        PyErr_Format(PyExc_SystemError,\n            \"AST validator recursion depth mismatch (before=%d, after=%d)\",\n            starting_recursion_depth, state.recursion_depth);\n        return 0;\n    }\n    return res;\n}\n\nPyObject *\n_PyAST_GetDocString(asdl_stmt_seq *body)\n{\n    if (!asdl_seq_LEN(body)) {\n        return NULL;\n    }\n    stmt_ty st = asdl_seq_GET(body, 0);\n    if (st->kind != Expr_kind) {\n        return NULL;\n    }\n    expr_ty e = st->v.Expr.value;\n    if (e->kind == Constant_kind && PyUnicode_CheckExact(e->v.Constant.value)) {\n        return e->v.Constant.value;\n    }\n    return NULL;\n}\n"
  },
  {
    "path": "Ast_Opt.c",
    "content": "/* AST Optimizer */\n#include \"Python.h\"\n#include \"pycore_ast.h\"           // _PyAST_GetDocString()\n#include \"pycore_long.h\"           // _PyLong\n#include \"pycore_pystate.h\"       // _PyThreadState_GET()\n#include \"pycore_format.h\"        // F_LJUST\n\n\ntypedef struct {\n    int optimize;\n    int ff_features;\n\n    int recursion_depth;            /* current recursion depth */\n    int recursion_limit;            /* recursion limit */\n} _PyASTOptimizeState;\n\n\nstatic int\nmake_const(expr_ty node, PyObject *val, PyArena *arena)\n{\n    // Even if no new value was calculated, make_const may still\n    // need to clear an error (e.g. for division by zero)\n    if (val == NULL) {\n        if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {\n            return 0;\n        }\n        PyErr_Clear();\n        return 1;\n    }\n    if (_PyArena_AddPyObject(arena, val) < 0) {\n        Py_DECREF(val);\n        return 0;\n    }\n    node->kind = Constant_kind;\n    node->v.Constant.kind = NULL;\n    node->v.Constant.value = val;\n    return 1;\n}\n\n#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))\n\nstatic int\nhas_starred(asdl_expr_seq *elts)\n{\n    Py_ssize_t n = asdl_seq_LEN(elts);\n    for (Py_ssize_t i = 0; i < n; i++) {\n        expr_ty e = (expr_ty)asdl_seq_GET(elts, i);\n        if (e->kind == Starred_kind) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\n\nstatic PyObject*\nunary_not(PyObject *v)\n{\n    int r = PyObject_IsTrue(v);\n    if (r < 0)\n        return NULL;\n    return PyBool_FromLong(!r);\n}\n\nstatic int\nfold_unaryop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)\n{\n    expr_ty arg = node->v.UnaryOp.operand;\n\n    if (arg->kind != Constant_kind) {\n        /* Fold not into comparison */\n        if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&\n                asdl_seq_LEN(arg->v.Compare.ops) == 1) {\n            /* Eq and NotEq are often implemented in terms of one another, so\n               folding not (self == other) into self != other breaks implementation\n               of !=. Detecting such cases doesn't seem worthwhile.\n               Python uses </> for 'is subset'/'is superset' operations on sets.\n               They don't satisfy not folding laws. */\n            cmpop_ty op = asdl_seq_GET(arg->v.Compare.ops, 0);\n            switch (op) {\n            case Is:\n                op = IsNot;\n                break;\n            case IsNot:\n                op = Is;\n                break;\n            case In:\n                op = NotIn;\n                break;\n            case NotIn:\n                op = In;\n                break;\n            // The remaining comparison operators can't be safely inverted\n            case Eq:\n            case NotEq:\n            case Lt:\n            case LtE:\n            case Gt:\n            case GtE:\n                op = 0; // The AST enums leave \"0\" free as an \"unused\" marker\n                break;\n            // No default case, so the compiler will emit a warning if new\n            // comparison operators are added without being handled here\n            }\n            if (op) {\n                asdl_seq_SET(arg->v.Compare.ops, 0, op);\n                COPY_NODE(node, arg);\n                return 1;\n            }\n        }\n        return 1;\n    }\n\n    typedef PyObject *(*unary_op)(PyObject*);\n    static const unary_op ops[] = {\n        [Invert] = PyNumber_Invert,\n        [Not] = unary_not,\n        [UAdd] = PyNumber_Positive,\n        [USub] = PyNumber_Negative,\n    };\n    PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);\n    return make_const(node, newval, arena);\n}\n\n/* Check whether a collection doesn't containing too much items (including\n   subcollections).  This protects from creating a constant that needs\n   too much time for calculating a hash.\n   \"limit\" is the maximal number of items.\n   Returns the negative number if the total number of items exceeds the\n   limit.  Otherwise returns the limit minus the total number of items.\n*/\n\nstatic Py_ssize_t\ncheck_complexity(PyObject *obj, Py_ssize_t limit)\n{\n    if (PyTuple_Check(obj)) {\n        Py_ssize_t i;\n        limit -= PyTuple_GET_SIZE(obj);\n        for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {\n            limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);\n        }\n        return limit;\n    }\n    else if (PyFrozenSet_Check(obj)) {\n        Py_ssize_t i = 0;\n        PyObject *item;\n        Py_hash_t hash;\n        limit -= PySet_GET_SIZE(obj);\n        while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {\n            limit = check_complexity(item, limit);\n        }\n    }\n    return limit;\n}\n\n#define MAX_INT_SIZE           128  /* bits */\n#define MAX_COLLECTION_SIZE    256  /* items */\n#define MAX_STR_SIZE          4096  /* characters */\n#define MAX_TOTAL_ITEMS       1024  /* including nested collections */\n\nstatic PyObject *\nsafe_multiply(PyObject *v, PyObject *w)\n{\n    if (PyLong_Check(v) && PyLong_Check(w) &&\n        !_PyLong_IsZero((PyLongObject *)v) && !_PyLong_IsZero((PyLongObject *)w)\n    ) {\n        size_t vbits = _PyLong_NumBits(v);\n        size_t wbits = _PyLong_NumBits(w);\n        if (vbits == (size_t)-1 || wbits == (size_t)-1) {\n            return NULL;\n        }\n        if (vbits + wbits > MAX_INT_SIZE) {\n            return NULL;\n        }\n    }\n    else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {\n        Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :\n                                             PySet_GET_SIZE(w);\n        if (size) {\n            long n = PyLong_AsLong(v);\n            if (n < 0 || n > MAX_COLLECTION_SIZE / size) {\n                return NULL;\n            }\n            if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {\n                return NULL;\n            }\n        }\n    }\n    else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {\n        Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :\n                                               PyBytes_GET_SIZE(w);\n        if (size) {\n            long n = PyLong_AsLong(v);\n            if (n < 0 || n > MAX_STR_SIZE / size) {\n                return NULL;\n            }\n        }\n    }\n    else if (PyLong_Check(w) &&\n             (PyTuple_Check(v) || PyFrozenSet_Check(v) ||\n              PyUnicode_Check(v) || PyBytes_Check(v)))\n    {\n        return safe_multiply(w, v);\n    }\n\n    return PyNumber_Multiply(v, w);\n}\n\nstatic PyObject *\nsafe_power(PyObject *v, PyObject *w)\n{\n    if (PyLong_Check(v) && PyLong_Check(w) &&\n        !_PyLong_IsZero((PyLongObject *)v) && _PyLong_IsPositive((PyLongObject *)w)\n    ) {\n        size_t vbits = _PyLong_NumBits(v);\n        size_t wbits = PyLong_AsSize_t(w);\n        if (vbits == (size_t)-1 || wbits == (size_t)-1) {\n            return NULL;\n        }\n        if (vbits > MAX_INT_SIZE / wbits) {\n            return NULL;\n        }\n    }\n\n    return PyNumber_Power(v, w, Py_None);\n}\n\nstatic PyObject *\nsafe_lshift(PyObject *v, PyObject *w)\n{\n    if (PyLong_Check(v) && PyLong_Check(w) &&\n        !_PyLong_IsZero((PyLongObject *)v) && !_PyLong_IsZero((PyLongObject *)w)\n    ) {\n        size_t vbits = _PyLong_NumBits(v);\n        size_t wbits = PyLong_AsSize_t(w);\n        if (vbits == (size_t)-1 || wbits == (size_t)-1) {\n            return NULL;\n        }\n        if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {\n            return NULL;\n        }\n    }\n\n    return PyNumber_Lshift(v, w);\n}\n\nstatic PyObject *\nsafe_mod(PyObject *v, PyObject *w)\n{\n    if (PyUnicode_Check(v) || PyBytes_Check(v)) {\n        return NULL;\n    }\n\n    return PyNumber_Remainder(v, w);\n}\n\n\nstatic expr_ty\nparse_literal(PyObject *fmt, Py_ssize_t *ppos, PyArena *arena)\n{\n    const void *data = PyUnicode_DATA(fmt);\n    int kind = PyUnicode_KIND(fmt);\n    Py_ssize_t size = PyUnicode_GET_LENGTH(fmt);\n    Py_ssize_t start, pos;\n    int has_percents = 0;\n    start = pos = *ppos;\n    while (pos < size) {\n        if (PyUnicode_READ(kind, data, pos) != '%') {\n            pos++;\n        }\n        else if (pos+1 < size && PyUnicode_READ(kind, data, pos+1) == '%') {\n            has_percents = 1;\n            pos += 2;\n        }\n        else {\n            break;\n        }\n    }\n    *ppos = pos;\n    if (pos == start) {\n        return NULL;\n    }\n    PyObject *str = PyUnicode_Substring(fmt, start, pos);\n    /* str = str.replace('%%', '%') */\n    if (str && has_percents) {\n        _Py_DECLARE_STR(percent, \"%\");\n        _Py_DECLARE_STR(dbl_percent, \"%%\");\n        Py_SETREF(str, PyUnicode_Replace(str, &_Py_STR(dbl_percent),\n                                         &_Py_STR(percent), -1));\n    }\n    if (!str) {\n        return NULL;\n    }\n\n    if (_PyArena_AddPyObject(arena, str) < 0) {\n        Py_DECREF(str);\n        return NULL;\n    }\n    return _PyAST_Constant(str, NULL, -1, -1, -1, -1, arena);\n}\n\n#define MAXDIGITS 3\n\nstatic int\nsimple_format_arg_parse(PyObject *fmt, Py_ssize_t *ppos,\n                        int *spec, int *flags, int *width, int *prec)\n{\n    Py_ssize_t pos = *ppos, len = PyUnicode_GET_LENGTH(fmt);\n    Py_UCS4 ch;\n\n#define NEXTC do {                      \\\n    if (pos >= len) {                   \\\n        return 0;                       \\\n    }                                   \\\n    ch = PyUnicode_READ_CHAR(fmt, pos); \\\n    pos++;                              \\\n} while (0)\n\n    *flags = 0;\n    while (1) {\n        NEXTC;\n        switch (ch) {\n            case '-': *flags |= F_LJUST; continue;\n            case '+': *flags |= F_SIGN; continue;\n            case ' ': *flags |= F_BLANK; continue;\n            case '#': *flags |= F_ALT; continue;\n            case '0': *flags |= F_ZERO; continue;\n        }\n        break;\n    }\n    if ('0' <= ch && ch <= '9') {\n        *width = 0;\n        int digits = 0;\n        while ('0' <= ch && ch <= '9') {\n            *width = *width * 10 + (ch - '0');\n            NEXTC;\n            if (++digits >= MAXDIGITS) {\n                return 0;\n            }\n        }\n    }\n\n    if (ch == '.') {\n        NEXTC;\n        *prec = 0;\n        if ('0' <= ch && ch <= '9') {\n            int digits = 0;\n            while ('0' <= ch && ch <= '9') {\n                *prec = *prec * 10 + (ch - '0');\n                NEXTC;\n                if (++digits >= MAXDIGITS) {\n                    return 0;\n                }\n            }\n        }\n    }\n    *spec = ch;\n    *ppos = pos;\n    return 1;\n\n#undef NEXTC\n}\n\nstatic expr_ty\nparse_format(PyObject *fmt, Py_ssize_t *ppos, expr_ty arg, PyArena *arena)\n{\n    int spec, flags, width = -1, prec = -1;\n    if (!simple_format_arg_parse(fmt, ppos, &spec, &flags, &width, &prec)) {\n        // Unsupported format.\n        return NULL;\n    }\n    if (spec == 's' || spec == 'r' || spec == 'a') {\n        char buf[1 + MAXDIGITS + 1 + MAXDIGITS + 1], *p = buf;\n        if (!(flags & F_LJUST) && width > 0) {\n            *p++ = '>';\n        }\n        if (width >= 0) {\n            p += snprintf(p, MAXDIGITS + 1, \"%d\", width);\n        }\n        if (prec >= 0) {\n            p += snprintf(p, MAXDIGITS + 2, \".%d\", prec);\n        }\n        expr_ty format_spec = NULL;\n        if (p != buf) {\n            PyObject *str = PyUnicode_FromString(buf);\n            if (str == NULL) {\n                return NULL;\n            }\n            if (_PyArena_AddPyObject(arena, str) < 0) {\n                Py_DECREF(str);\n                return NULL;\n            }\n            format_spec = _PyAST_Constant(str, NULL, -1, -1, -1, -1, arena);\n            if (format_spec == NULL) {\n                return NULL;\n            }\n        }\n        return _PyAST_FormattedValue(arg, spec, format_spec,\n                                     arg->lineno, arg->col_offset,\n                                     arg->end_lineno, arg->end_col_offset,\n                                     arena);\n    }\n    // Unsupported format.\n    return NULL;\n}\n\nstatic int\noptimize_format(expr_ty node, PyObject *fmt, asdl_expr_seq *elts, PyArena *arena)\n{\n    Py_ssize_t pos = 0;\n    Py_ssize_t cnt = 0;\n    asdl_expr_seq *seq = _Py_asdl_expr_seq_new(asdl_seq_LEN(elts) * 2 + 1, arena);\n    if (!seq) {\n        return 0;\n    }\n    seq->size = 0;\n\n    while (1) {\n        expr_ty lit = parse_literal(fmt, &pos, arena);\n        if (lit) {\n            asdl_seq_SET(seq, seq->size++, lit);\n        }\n        else if (PyErr_Occurred()) {\n            return 0;\n        }\n\n        if (pos >= PyUnicode_GET_LENGTH(fmt)) {\n            break;\n        }\n        if (cnt >= asdl_seq_LEN(elts)) {\n            // More format units than items.\n            return 1;\n        }\n        assert(PyUnicode_READ_CHAR(fmt, pos) == '%');\n        pos++;\n        expr_ty expr = parse_format(fmt, &pos, asdl_seq_GET(elts, cnt), arena);\n        cnt++;\n        if (!expr) {\n            return !PyErr_Occurred();\n        }\n        asdl_seq_SET(seq, seq->size++, expr);\n    }\n    if (cnt < asdl_seq_LEN(elts)) {\n        // More items than format units.\n        return 1;\n    }\n    expr_ty res = _PyAST_JoinedStr(seq,\n                                   node->lineno, node->col_offset,\n                                   node->end_lineno, node->end_col_offset,\n                                   arena);\n    if (!res) {\n        return 0;\n    }\n    COPY_NODE(node, res);\n//     PySys_FormatStderr(\"format = %R\\n\", fmt);\n    return 1;\n}\n\nstatic int\nfold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)\n{\n    expr_ty lhs, rhs;\n    lhs = node->v.BinOp.left;\n    rhs = node->v.BinOp.right;\n    if (lhs->kind != Constant_kind) {\n        return 1;\n    }\n    PyObject *lv = lhs->v.Constant.value;\n\n    if (node->v.BinOp.op == Mod &&\n        rhs->kind == Tuple_kind &&\n        PyUnicode_Check(lv) &&\n        !has_starred(rhs->v.Tuple.elts))\n    {\n        return optimize_format(node, lv, rhs->v.Tuple.elts, arena);\n    }\n\n    if (rhs->kind != Constant_kind) {\n        return 1;\n    }\n\n    PyObject *rv = rhs->v.Constant.value;\n    PyObject *newval = NULL;\n\n    switch (node->v.BinOp.op) {\n    case Add:\n        newval = PyNumber_Add(lv, rv);\n        break;\n    case Sub:\n        newval = PyNumber_Subtract(lv, rv);\n        break;\n    case Mult:\n        newval = safe_multiply(lv, rv);\n        break;\n    case Div:\n        newval = PyNumber_TrueDivide(lv, rv);\n        break;\n    case FloorDiv:\n        newval = PyNumber_FloorDivide(lv, rv);\n        break;\n    case Mod:\n        newval = safe_mod(lv, rv);\n        break;\n    case Pow:\n        newval = safe_power(lv, rv);\n        break;\n    case LShift:\n        newval = safe_lshift(lv, rv);\n        break;\n    case RShift:\n        newval = PyNumber_Rshift(lv, rv);\n        break;\n    case BitOr:\n        newval = PyNumber_Or(lv, rv);\n        break;\n    case BitXor:\n        newval = PyNumber_Xor(lv, rv);\n        break;\n    case BitAnd:\n        newval = PyNumber_And(lv, rv);\n        break;\n    // No builtin constants implement the following operators\n    case MatMult:\n        return 1;\n    // No default case, so the compiler will emit a warning if new binary\n    // operators are added without being handled here\n    }\n\n    return make_const(node, newval, arena);\n}\n\nstatic PyObject*\nmake_const_tuple(asdl_expr_seq *elts)\n{\n    for (int i = 0; i < asdl_seq_LEN(elts); i++) {\n        expr_ty e = (expr_ty)asdl_seq_GET(elts, i);\n        if (e->kind != Constant_kind) {\n            return NULL;\n        }\n    }\n\n    PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));\n    if (newval == NULL) {\n        return NULL;\n    }\n\n    for (int i = 0; i < asdl_seq_LEN(elts); i++) {\n        expr_ty e = (expr_ty)asdl_seq_GET(elts, i);\n        PyObject *v = e->v.Constant.value;\n        PyTuple_SET_ITEM(newval, i, Py_NewRef(v));\n    }\n    return newval;\n}\n\nstatic int\nfold_tuple(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)\n{\n    PyObject *newval;\n\n    if (node->v.Tuple.ctx != Load)\n        return 1;\n\n    newval = make_const_tuple(node->v.Tuple.elts);\n    return make_const(node, newval, arena);\n}\n\nstatic int\nfold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)\n{\n    PyObject *newval;\n    expr_ty arg, idx;\n\n    arg = node->v.Subscript.value;\n    idx = node->v.Subscript.slice;\n    if (node->v.Subscript.ctx != Load ||\n            arg->kind != Constant_kind ||\n            idx->kind != Constant_kind)\n    {\n        return 1;\n    }\n\n    newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);\n    return make_const(node, newval, arena);\n}\n\n/* Change literal list or set of constants into constant\n   tuple or frozenset respectively.  Change literal list of\n   non-constants into tuple.\n   Used for right operand of \"in\" and \"not in\" tests and for iterable\n   in \"for\" loop and comprehensions.\n*/\nstatic int\nfold_iter(expr_ty arg, PyArena *arena, _PyASTOptimizeState *state)\n{\n    PyObject *newval;\n    if (arg->kind == List_kind) {\n        /* First change a list into tuple. */\n        asdl_expr_seq *elts = arg->v.List.elts;\n        if (has_starred(elts)) {\n            return 1;\n        }\n        expr_context_ty ctx = arg->v.List.ctx;\n        arg->kind = Tuple_kind;\n        arg->v.Tuple.elts = elts;\n        arg->v.Tuple.ctx = ctx;\n        /* Try to create a constant tuple. */\n        newval = make_const_tuple(elts);\n    }\n    else if (arg->kind == Set_kind) {\n        newval = make_const_tuple(arg->v.Set.elts);\n        if (newval) {\n            Py_SETREF(newval, PyFrozenSet_New(newval));\n        }\n    }\n    else {\n        return 1;\n    }\n    return make_const(arg, newval, arena);\n}\n\nstatic int\nfold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)\n{\n    asdl_int_seq *ops;\n    asdl_expr_seq *args;\n    Py_ssize_t i;\n\n    ops = node->v.Compare.ops;\n    args = node->v.Compare.comparators;\n    /* Change literal list or set in 'in' or 'not in' into\n       tuple or frozenset respectively. */\n    i = asdl_seq_LEN(ops) - 1;\n    int op = asdl_seq_GET(ops, i);\n    if (op == In || op == NotIn) {\n        if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, state)) {\n            return 0;\n        }\n    }\n    return 1;\n}\n\nstatic int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);\nstatic int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);\nstatic int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);\nstatic int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);\nstatic int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);\nstatic int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);\nstatic int astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);\nstatic int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);\nstatic int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);\nstatic int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);\nstatic int astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);\nstatic int astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);\n\n#define CALL(FUNC, TYPE, ARG) \\\n    if (!FUNC((ARG), ctx_, state)) \\\n        return 0;\n\n#define CALL_OPT(FUNC, TYPE, ARG) \\\n    if ((ARG) != NULL && !FUNC((ARG), ctx_, state)) \\\n        return 0;\n\n#define CALL_SEQ(FUNC, TYPE, ARG) { \\\n    int i; \\\n    asdl_ ## TYPE ## _seq *seq = (ARG); /* avoid variable capture */ \\\n    for (i = 0; i < asdl_seq_LEN(seq); i++) { \\\n        TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \\\n        if (elt != NULL && !FUNC(elt, ctx_, state)) \\\n            return 0; \\\n    } \\\n}\n\n\nstatic int\nastfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    int docstring = _PyAST_GetDocString(stmts) != NULL;\n    CALL_SEQ(astfold_stmt, stmt, stmts);\n    if (!docstring && _PyAST_GetDocString(stmts) != NULL) {\n        stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);\n        asdl_expr_seq *values = _Py_asdl_expr_seq_new(1, ctx_);\n        if (!values) {\n            return 0;\n        }\n        asdl_seq_SET(values, 0, st->v.Expr.value);\n        expr_ty expr = _PyAST_JoinedStr(values, st->lineno, st->col_offset,\n                                        st->end_lineno, st->end_col_offset,\n                                        ctx_);\n        if (!expr) {\n            return 0;\n        }\n        st->v.Expr.value = expr;\n    }\n    return 1;\n}\n\nstatic int\nastfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    switch (node_->kind) {\n    case Module_kind:\n        CALL(astfold_body, asdl_seq, node_->v.Module.body);\n        break;\n    case Interactive_kind:\n        CALL_SEQ(astfold_stmt, stmt, node_->v.Interactive.body);\n        break;\n    case Expression_kind:\n        CALL(astfold_expr, expr_ty, node_->v.Expression.body);\n        break;\n    // The following top level nodes don't participate in constant folding\n    case FunctionType_kind:\n        break;\n    // No default case, so the compiler will emit a warning if new top level\n    // compilation nodes are added without being handled here\n    }\n    return 1;\n}\n\nstatic int\nastfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n                        \"maximum recursion depth exceeded during compilation\");\n        return 0;\n    }\n    switch (node_->kind) {\n    case BoolOp_kind:\n        CALL_SEQ(astfold_expr, expr, node_->v.BoolOp.values);\n        break;\n    case BinOp_kind:\n        CALL(astfold_expr, expr_ty, node_->v.BinOp.left);\n        CALL(astfold_expr, expr_ty, node_->v.BinOp.right);\n        CALL(fold_binop, expr_ty, node_);\n        break;\n    case UnaryOp_kind:\n        CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);\n        CALL(fold_unaryop, expr_ty, node_);\n        break;\n    case Lambda_kind:\n        CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);\n        CALL(astfold_expr, expr_ty, node_->v.Lambda.body);\n        break;\n    case IfExp_kind:\n        CALL(astfold_expr, expr_ty, node_->v.IfExp.test);\n        CALL(astfold_expr, expr_ty, node_->v.IfExp.body);\n        CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);\n        break;\n    case Dict_kind:\n        CALL_SEQ(astfold_expr, expr, node_->v.Dict.keys);\n        CALL_SEQ(astfold_expr, expr, node_->v.Dict.values);\n        break;\n    case Set_kind:\n        CALL_SEQ(astfold_expr, expr, node_->v.Set.elts);\n        break;\n    case ListComp_kind:\n        CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);\n        CALL_SEQ(astfold_comprehension, comprehension, node_->v.ListComp.generators);\n        break;\n    case SetComp_kind:\n        CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);\n        CALL_SEQ(astfold_comprehension, comprehension, node_->v.SetComp.generators);\n        break;\n    case DictComp_kind:\n        CALL(astfold_expr, expr_ty, node_->v.DictComp.key);\n        CALL(astfold_expr, expr_ty, node_->v.DictComp.value);\n        CALL_SEQ(astfold_comprehension, comprehension, node_->v.DictComp.generators);\n        break;\n    case GeneratorExp_kind:\n        CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);\n        CALL_SEQ(astfold_comprehension, comprehension, node_->v.GeneratorExp.generators);\n        break;\n    case Await_kind:\n        CALL(astfold_expr, expr_ty, node_->v.Await.value);\n        break;\n    case Yield_kind:\n        CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);\n        break;\n    case YieldFrom_kind:\n        CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);\n        break;\n    case Compare_kind:\n        CALL(astfold_expr, expr_ty, node_->v.Compare.left);\n        CALL_SEQ(astfold_expr, expr, node_->v.Compare.comparators);\n        CALL(fold_compare, expr_ty, node_);\n        break;\n    case Call_kind:\n        CALL(astfold_expr, expr_ty, node_->v.Call.func);\n        CALL_SEQ(astfold_expr, expr, node_->v.Call.args);\n        CALL_SEQ(astfold_keyword, keyword, node_->v.Call.keywords);\n        break;\n    case FormattedValue_kind:\n        CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);\n        CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);\n        break;\n    case JoinedStr_kind:\n        CALL_SEQ(astfold_expr, expr, node_->v.JoinedStr.values);\n        break;\n    case Attribute_kind:\n        CALL(astfold_expr, expr_ty, node_->v.Attribute.value);\n        break;\n    case Subscript_kind:\n        CALL(astfold_expr, expr_ty, node_->v.Subscript.value);\n        CALL(astfold_expr, expr_ty, node_->v.Subscript.slice);\n        CALL(fold_subscr, expr_ty, node_);\n        break;\n    case Starred_kind:\n        CALL(astfold_expr, expr_ty, node_->v.Starred.value);\n        break;\n    case Slice_kind:\n        CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);\n        CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);\n        CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);\n        break;\n    case List_kind:\n        CALL_SEQ(astfold_expr, expr, node_->v.List.elts);\n        break;\n    case Tuple_kind:\n        CALL_SEQ(astfold_expr, expr, node_->v.Tuple.elts);\n        CALL(fold_tuple, expr_ty, node_);\n        break;\n    case Name_kind:\n        if (node_->v.Name.ctx == Load &&\n                _PyUnicode_EqualToASCIIString(node_->v.Name.id, \"__debug__\")) {\n            state->recursion_depth--;\n            return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);\n        }\n        break;\n    case NamedExpr_kind:\n        CALL(astfold_expr, expr_ty, node_->v.NamedExpr.value);\n        break;\n    case Constant_kind:\n        // Already a constant, nothing further to do\n        break;\n    // No default case, so the compiler will emit a warning if new expression\n    // kinds are added without being handled here\n    }\n    state->recursion_depth--;\n    return 1;\n}\n\nstatic int\nastfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    CALL(astfold_expr, expr_ty, node_->value);\n    return 1;\n}\n\nstatic int\nastfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    CALL(astfold_expr, expr_ty, node_->target);\n    CALL(astfold_expr, expr_ty, node_->iter);\n    CALL_SEQ(astfold_expr, expr, node_->ifs);\n\n    CALL(fold_iter, expr_ty, node_->iter);\n    return 1;\n}\n\nstatic int\nastfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    CALL_SEQ(astfold_arg, arg, node_->posonlyargs);\n    CALL_SEQ(astfold_arg, arg, node_->args);\n    CALL_OPT(astfold_arg, arg_ty, node_->vararg);\n    CALL_SEQ(astfold_arg, arg, node_->kwonlyargs);\n    CALL_SEQ(astfold_expr, expr, node_->kw_defaults);\n    CALL_OPT(astfold_arg, arg_ty, node_->kwarg);\n    CALL_SEQ(astfold_expr, expr, node_->defaults);\n    return 1;\n}\n\nstatic int\nastfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {\n        CALL_OPT(astfold_expr, expr_ty, node_->annotation);\n    }\n    return 1;\n}\n\nstatic int\nastfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n                        \"maximum recursion depth exceeded during compilation\");\n        return 0;\n    }\n    switch (node_->kind) {\n    case FunctionDef_kind:\n        CALL_SEQ(astfold_type_param, type_param, node_->v.FunctionDef.type_params);\n        CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);\n        CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);\n        CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list);\n        if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {\n            CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);\n        }\n        break;\n    case AsyncFunctionDef_kind:\n        CALL_SEQ(astfold_type_param, type_param, node_->v.AsyncFunctionDef.type_params);\n        CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);\n        CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);\n        CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list);\n        if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {\n            CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);\n        }\n        break;\n    case ClassDef_kind:\n        CALL_SEQ(astfold_type_param, type_param, node_->v.ClassDef.type_params);\n        CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.bases);\n        CALL_SEQ(astfold_keyword, keyword, node_->v.ClassDef.keywords);\n        CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);\n        CALL_SEQ(astfold_expr, expr, node_->v.ClassDef.decorator_list);\n        break;\n    case Return_kind:\n        CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);\n        break;\n    case Delete_kind:\n        CALL_SEQ(astfold_expr, expr, node_->v.Delete.targets);\n        break;\n    case Assign_kind:\n        CALL_SEQ(astfold_expr, expr, node_->v.Assign.targets);\n        CALL(astfold_expr, expr_ty, node_->v.Assign.value);\n        break;\n    case AugAssign_kind:\n        CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);\n        CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);\n        break;\n    case AnnAssign_kind:\n        CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);\n        if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {\n            CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);\n        }\n        CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);\n        break;\n    case TypeAlias_kind:\n        CALL(astfold_expr, expr_ty, node_->v.TypeAlias.name);\n        CALL_SEQ(astfold_type_param, type_param, node_->v.TypeAlias.type_params);\n        CALL(astfold_expr, expr_ty, node_->v.TypeAlias.value);\n        break;\n    case For_kind:\n        CALL(astfold_expr, expr_ty, node_->v.For.target);\n        CALL(astfold_expr, expr_ty, node_->v.For.iter);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.For.body);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse);\n\n        CALL(fold_iter, expr_ty, node_->v.For.iter);\n        break;\n    case AsyncFor_kind:\n        CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);\n        CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.body);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.orelse);\n        break;\n    case While_kind:\n        CALL(astfold_expr, expr_ty, node_->v.While.test);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.While.body);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.While.orelse);\n        break;\n    case If_kind:\n        CALL(astfold_expr, expr_ty, node_->v.If.test);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.If.body);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.If.orelse);\n        break;\n    case With_kind:\n        CALL_SEQ(astfold_withitem, withitem, node_->v.With.items);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.With.body);\n        break;\n    case AsyncWith_kind:\n        CALL_SEQ(astfold_withitem, withitem, node_->v.AsyncWith.items);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncWith.body);\n        break;\n    case Raise_kind:\n        CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);\n        CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);\n        break;\n    case Try_kind:\n        CALL_SEQ(astfold_stmt, stmt, node_->v.Try.body);\n        CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.Try.handlers);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody);\n        break;\n    case TryStar_kind:\n        CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.body);\n        CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.TryStar.handlers);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.orelse);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.finalbody);\n        break;\n    case Assert_kind:\n        CALL(astfold_expr, expr_ty, node_->v.Assert.test);\n        CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);\n        break;\n    case Expr_kind:\n        CALL(astfold_expr, expr_ty, node_->v.Expr.value);\n        break;\n    case Match_kind:\n        CALL(astfold_expr, expr_ty, node_->v.Match.subject);\n        CALL_SEQ(astfold_match_case, match_case, node_->v.Match.cases);\n        break;\n    // The following statements don't contain any subexpressions to be folded\n    case Import_kind:\n    case ImportFrom_kind:\n    case Global_kind:\n    case Nonlocal_kind:\n    case Pass_kind:\n    case Break_kind:\n    case Continue_kind:\n        break;\n    // No default case, so the compiler will emit a warning if new statement\n    // kinds are added without being handled here\n    }\n    state->recursion_depth--;\n    return 1;\n}\n\nstatic int\nastfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    switch (node_->kind) {\n    case ExceptHandler_kind:\n        CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);\n        CALL_SEQ(astfold_stmt, stmt, node_->v.ExceptHandler.body);\n        break;\n    // No default case, so the compiler will emit a warning if new handler\n    // kinds are added without being handled here\n    }\n    return 1;\n}\n\nstatic int\nastfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    CALL(astfold_expr, expr_ty, node_->context_expr);\n    CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);\n    return 1;\n}\n\nstatic int\nastfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    // Currently, this is really only used to form complex/negative numeric\n    // constants in MatchValue and MatchMapping nodes\n    // We still recurse into all subexpressions and subpatterns anyway\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n                        \"maximum recursion depth exceeded during compilation\");\n        return 0;\n    }\n    switch (node_->kind) {\n        case MatchValue_kind:\n            CALL(astfold_expr, expr_ty, node_->v.MatchValue.value);\n            break;\n        case MatchSingleton_kind:\n            break;\n        case MatchSequence_kind:\n            CALL_SEQ(astfold_pattern, pattern, node_->v.MatchSequence.patterns);\n            break;\n        case MatchMapping_kind:\n            CALL_SEQ(astfold_expr, expr, node_->v.MatchMapping.keys);\n            CALL_SEQ(astfold_pattern, pattern, node_->v.MatchMapping.patterns);\n            break;\n        case MatchClass_kind:\n            CALL(astfold_expr, expr_ty, node_->v.MatchClass.cls);\n            CALL_SEQ(astfold_pattern, pattern, node_->v.MatchClass.patterns);\n            CALL_SEQ(astfold_pattern, pattern, node_->v.MatchClass.kwd_patterns);\n            break;\n        case MatchStar_kind:\n            break;\n        case MatchAs_kind:\n            if (node_->v.MatchAs.pattern) {\n                CALL(astfold_pattern, pattern_ty, node_->v.MatchAs.pattern);\n            }\n            break;\n        case MatchOr_kind:\n            CALL_SEQ(astfold_pattern, pattern, node_->v.MatchOr.patterns);\n            break;\n    // No default case, so the compiler will emit a warning if new pattern\n    // kinds are added without being handled here\n    }\n    state->recursion_depth--;\n    return 1;\n}\n\nstatic int\nastfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    CALL(astfold_pattern, expr_ty, node_->pattern);\n    CALL_OPT(astfold_expr, expr_ty, node_->guard);\n    CALL_SEQ(astfold_stmt, stmt, node_->body);\n    return 1;\n}\n\nstatic int\nastfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)\n{\n    switch (node_->kind) {\n        case TypeVar_kind:\n            CALL_OPT(astfold_expr, expr_ty, node_->v.TypeVar.bound);\n            break;\n        case ParamSpec_kind:\n            break;\n        case TypeVarTuple_kind:\n            break;\n    }\n    return 1;\n}\n\n#undef CALL\n#undef CALL_OPT\n#undef CALL_SEQ\n\n/* See comments in symtable.c. */\n#define COMPILER_STACK_FRAME_SCALE 3\n\nint\n_PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize, int ff_features)\n{\n    PyThreadState *tstate;\n    int starting_recursion_depth;\n\n    _PyASTOptimizeState state;\n    state.optimize = optimize;\n    state.ff_features = ff_features;\n\n    /* Setup recursion depth check counters */\n    tstate = _PyThreadState_GET();\n    if (!tstate) {\n        return 0;\n    }\n    /* Be careful here to prevent overflow. */\n    int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;\n    starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;\n    state.recursion_depth = starting_recursion_depth;\n    state.recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;\n\n    int ret = astfold_mod(mod, arena, &state);\n    assert(ret || PyErr_Occurred());\n\n    /* Check that the recursion depth counting balanced correctly */\n    if (ret && state.recursion_depth != starting_recursion_depth) {\n        PyErr_Format(PyExc_SystemError,\n            \"AST optimizer recursion depth mismatch (before=%d, after=%d)\",\n            starting_recursion_depth, state.recursion_depth);\n        return 0;\n    }\n\n    return ret;\n}\n"
  },
  {
    "path": "Ast_Unparse.c",
    "content": "#include \"Python.h\"\n#include \"pycore_ast.h\"           // expr_ty\n#include \"pycore_pystate.h\"       // _PyInterpreterState_GET()\n#include \"pycore_runtime.h\"       // _Py_ID()\n#include <float.h>                // DBL_MAX_10_EXP\n#include <stdbool.h>\n\n/* This limited unparser is used to convert annotations back to strings\n * during compilation rather than being a full AST unparser.\n * See ast.unparse for a full unparser (written in Python)\n */\n\n_Py_DECLARE_STR(open_br, \"{\");\n_Py_DECLARE_STR(dbl_open_br, \"{{\");\n_Py_DECLARE_STR(close_br, \"}\");\n_Py_DECLARE_STR(dbl_close_br, \"}}\");\n\n/* We would statically initialize this if doing so were simple enough. */\n#define _str_replace_inf(interp) \\\n    _Py_INTERP_CACHED_OBJECT(interp, str_replace_inf)\n\n/* Forward declarations for recursion via helper functions. */\nstatic PyObject *\nexpr_as_unicode(expr_ty e, int level);\nstatic int\nappend_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level);\nstatic int\nappend_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec);\nstatic int\nappend_formattedvalue(_PyUnicodeWriter *writer, expr_ty e);\nstatic int\nappend_ast_slice(_PyUnicodeWriter *writer, expr_ty e);\n\nstatic int\nappend_charp(_PyUnicodeWriter *writer, const char *charp)\n{\n    return _PyUnicodeWriter_WriteASCIIString(writer, charp, -1);\n}\n\n#define APPEND_STR_FINISH(str)  do { \\\n        return append_charp(writer, (str)); \\\n    } while (0)\n\n#define APPEND_STR(str)  do { \\\n        if (-1 == append_charp(writer, (str))) { \\\n            return -1; \\\n        } \\\n    } while (0)\n\n#define APPEND_STR_IF(cond, str)  do { \\\n        if ((cond) && -1 == append_charp(writer, (str))) { \\\n            return -1; \\\n        } \\\n    } while (0)\n\n#define APPEND_STR_IF_NOT_FIRST(str)  do { \\\n        APPEND_STR_IF(!first, (str)); \\\n        first = false; \\\n    } while (0)\n\n#define APPEND_EXPR(expr, pr)  do { \\\n        if (-1 == append_ast_expr(writer, (expr), (pr))) { \\\n            return -1; \\\n        } \\\n    } while (0)\n\n#define APPEND(type, value)  do { \\\n        if (-1 == append_ast_ ## type(writer, (value))) { \\\n            return -1; \\\n        } \\\n    } while (0)\n\nstatic int\nappend_repr(_PyUnicodeWriter *writer, PyObject *obj)\n{\n    PyObject *repr = PyObject_Repr(obj);\n\n    if (!repr) {\n        return -1;\n    }\n\n    if ((PyFloat_CheckExact(obj) && Py_IS_INFINITY(PyFloat_AS_DOUBLE(obj))) ||\n       PyComplex_CheckExact(obj))\n    {\n        PyInterpreterState *interp = _PyInterpreterState_GET();\n        PyObject *new_repr = PyUnicode_Replace(\n            repr,\n            &_Py_ID(inf),\n            _str_replace_inf(interp),\n            -1\n        );\n        Py_DECREF(repr);\n        if (!new_repr) {\n            return -1;\n        }\n        repr = new_repr;\n    }\n    int ret = _PyUnicodeWriter_WriteStr(writer, repr);\n    Py_DECREF(repr);\n    return ret;\n}\n\n/* Priority levels */\n\nenum {\n    PR_TUPLE,\n    PR_TEST,            /* 'if'-'else', 'lambda' */\n    PR_OR,              /* 'or' */\n    PR_AND,             /* 'and' */\n    PR_NOT,             /* 'not' */\n    PR_CMP,             /* '<', '>', '==', '>=', '<=', '!=',\n                           'in', 'not in', 'is', 'is not' */\n    PR_EXPR,\n    PR_BOR = PR_EXPR,   /* '|' */\n    PR_BXOR,            /* '^' */\n    PR_BAND,            /* '&' */\n    PR_SHIFT,           /* '<<', '>>' */\n    PR_ARITH,           /* '+', '-' */\n    PR_TERM,            /* '*', '@', '/', '%', '//' */\n    PR_FACTOR,          /* unary '+', '-', '~' */\n    PR_POWER,           /* '**' */\n    PR_AWAIT,           /* 'await' */\n    PR_ATOM,\n};\n\nstatic int\nappend_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, int level)\n{\n    Py_ssize_t i, value_count;\n    asdl_expr_seq *values;\n    const char *op = (e->v.BoolOp.op == And) ? \" and \" : \" or \";\n    int pr = (e->v.BoolOp.op == And) ? PR_AND : PR_OR;\n\n    APPEND_STR_IF(level > pr, \"(\");\n\n    values = e->v.BoolOp.values;\n    value_count = asdl_seq_LEN(values);\n\n    for (i = 0; i < value_count; ++i) {\n        APPEND_STR_IF(i > 0, op);\n        APPEND_EXPR((expr_ty)asdl_seq_GET(values, i), pr + 1);\n    }\n\n    APPEND_STR_IF(level > pr, \")\");\n    return 0;\n}\n\nstatic int\nappend_ast_binop(_PyUnicodeWriter *writer, expr_ty e, int level)\n{\n    const char *op;\n    int pr;\n    bool rassoc = false;  /* is right-associative? */\n\n    switch (e->v.BinOp.op) {\n    case Add: op = \" + \"; pr = PR_ARITH; break;\n    case Sub: op = \" - \"; pr = PR_ARITH; break;\n    case Mult: op = \" * \"; pr = PR_TERM; break;\n    case MatMult: op = \" @ \"; pr = PR_TERM; break;\n    case Div: op = \" / \"; pr = PR_TERM; break;\n    case Mod: op = \" % \"; pr = PR_TERM; break;\n    case LShift: op = \" << \"; pr = PR_SHIFT; break;\n    case RShift: op = \" >> \"; pr = PR_SHIFT; break;\n    case BitOr: op = \" | \"; pr = PR_BOR; break;\n    case BitXor: op = \" ^ \"; pr = PR_BXOR; break;\n    case BitAnd: op = \" & \"; pr = PR_BAND; break;\n    case FloorDiv: op = \" // \"; pr = PR_TERM; break;\n    case Pow: op = \" ** \"; pr = PR_POWER; rassoc = true; break;\n    default:\n        PyErr_SetString(PyExc_SystemError,\n                        \"unknown binary operator\");\n        return -1;\n    }\n\n    APPEND_STR_IF(level > pr, \"(\");\n    APPEND_EXPR(e->v.BinOp.left, pr + rassoc);\n    APPEND_STR(op);\n    APPEND_EXPR(e->v.BinOp.right, pr + !rassoc);\n    APPEND_STR_IF(level > pr, \")\");\n    return 0;\n}\n\nstatic int\nappend_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, int level)\n{\n    const char *op;\n    int pr;\n\n    switch (e->v.UnaryOp.op) {\n    case Invert: op = \"~\"; pr = PR_FACTOR; break;\n    case Not: op = \"not \"; pr = PR_NOT; break;\n    case UAdd: op = \"+\"; pr = PR_FACTOR; break;\n    case USub: op = \"-\"; pr = PR_FACTOR; break;\n    default:\n        PyErr_SetString(PyExc_SystemError,\n                        \"unknown unary operator\");\n        return -1;\n    }\n\n    APPEND_STR_IF(level > pr, \"(\");\n    APPEND_STR(op);\n    APPEND_EXPR(e->v.UnaryOp.operand, pr);\n    APPEND_STR_IF(level > pr, \")\");\n    return 0;\n}\n\nstatic int\nappend_ast_arg(_PyUnicodeWriter *writer, arg_ty arg)\n{\n    if (-1 == _PyUnicodeWriter_WriteStr(writer, arg->arg)) {\n        return -1;\n    }\n    if (arg->annotation) {\n        APPEND_STR(\": \");\n        APPEND_EXPR(arg->annotation, PR_TEST);\n    }\n    return 0;\n}\n\nstatic int\nappend_ast_args(_PyUnicodeWriter *writer, arguments_ty args)\n{\n    bool first;\n    Py_ssize_t i, di, arg_count, posonlyarg_count, default_count;\n\n    first = true;\n\n    /* positional-only and positional arguments with defaults */\n    posonlyarg_count = asdl_seq_LEN(args->posonlyargs);\n    arg_count = asdl_seq_LEN(args->args);\n    default_count = asdl_seq_LEN(args->defaults);\n    for (i = 0; i < posonlyarg_count + arg_count; i++) {\n        APPEND_STR_IF_NOT_FIRST(\", \");\n        if (i < posonlyarg_count){\n            APPEND(arg, (arg_ty)asdl_seq_GET(args->posonlyargs, i));\n        } else {\n            APPEND(arg, (arg_ty)asdl_seq_GET(args->args, i-posonlyarg_count));\n        }\n\n        di = i - posonlyarg_count - arg_count + default_count;\n        if (di >= 0) {\n            APPEND_STR(\"=\");\n            APPEND_EXPR((expr_ty)asdl_seq_GET(args->defaults, di), PR_TEST);\n        }\n        if (posonlyarg_count && i + 1 == posonlyarg_count) {\n            APPEND_STR(\", /\");\n        }\n    }\n\n    /* vararg, or bare '*' if no varargs but keyword-only arguments present */\n    if (args->vararg || asdl_seq_LEN(args->kwonlyargs)) {\n        APPEND_STR_IF_NOT_FIRST(\", \");\n        APPEND_STR(\"*\");\n        if (args->vararg) {\n            APPEND(arg, args->vararg);\n        }\n    }\n\n    /* keyword-only arguments */\n    arg_count = asdl_seq_LEN(args->kwonlyargs);\n    default_count = asdl_seq_LEN(args->kw_defaults);\n    for (i = 0; i < arg_count; i++) {\n        APPEND_STR_IF_NOT_FIRST(\", \");\n        APPEND(arg, (arg_ty)asdl_seq_GET(args->kwonlyargs, i));\n\n        di = i - arg_count + default_count;\n        if (di >= 0) {\n            expr_ty default_ = (expr_ty)asdl_seq_GET(args->kw_defaults, di);\n            if (default_) {\n                APPEND_STR(\"=\");\n                APPEND_EXPR(default_, PR_TEST);\n            }\n        }\n    }\n\n    /* **kwargs */\n    if (args->kwarg) {\n        APPEND_STR_IF_NOT_FIRST(\", \");\n        APPEND_STR(\"**\");\n        APPEND(arg, args->kwarg);\n    }\n\n    return 0;\n}\n\nstatic int\nappend_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, int level)\n{\n    APPEND_STR_IF(level > PR_TEST, \"(\");\n    Py_ssize_t n_positional = (asdl_seq_LEN(e->v.Lambda.args->args) +\n                               asdl_seq_LEN(e->v.Lambda.args->posonlyargs));\n    APPEND_STR(n_positional ? \"lambda \" : \"lambda\");\n    APPEND(args, e->v.Lambda.args);\n    APPEND_STR(\": \");\n    APPEND_EXPR(e->v.Lambda.body, PR_TEST);\n    APPEND_STR_IF(level > PR_TEST, \")\");\n    return 0;\n}\n\nstatic int\nappend_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, int level)\n{\n    APPEND_STR_IF(level > PR_TEST, \"(\");\n    APPEND_EXPR(e->v.IfExp.body, PR_TEST + 1);\n    APPEND_STR(\" if \");\n    APPEND_EXPR(e->v.IfExp.test, PR_TEST + 1);\n    APPEND_STR(\" else \");\n    APPEND_EXPR(e->v.IfExp.orelse, PR_TEST);\n    APPEND_STR_IF(level > PR_TEST, \")\");\n    return 0;\n}\n\nstatic int\nappend_ast_dict(_PyUnicodeWriter *writer, expr_ty e)\n{\n    Py_ssize_t i, value_count;\n    expr_ty key_node;\n\n    APPEND_STR(\"{\");\n    value_count = asdl_seq_LEN(e->v.Dict.values);\n\n    for (i = 0; i < value_count; i++) {\n        APPEND_STR_IF(i > 0, \", \");\n        key_node = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i);\n        if (key_node != NULL) {\n            APPEND_EXPR(key_node, PR_TEST);\n            APPEND_STR(\": \");\n            APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_TEST);\n        }\n        else {\n            APPEND_STR(\"**\");\n            APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_EXPR);\n        }\n    }\n\n    APPEND_STR_FINISH(\"}\");\n}\n\nstatic int\nappend_ast_set(_PyUnicodeWriter *writer, expr_ty e)\n{\n    Py_ssize_t i, elem_count;\n\n    APPEND_STR(\"{\");\n    elem_count = asdl_seq_LEN(e->v.Set.elts);\n    for (i = 0; i < elem_count; i++) {\n        APPEND_STR_IF(i > 0, \", \");\n        APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Set.elts, i), PR_TEST);\n    }\n\n    APPEND_STR_FINISH(\"}\");\n}\n\nstatic int\nappend_ast_list(_PyUnicodeWriter *writer, expr_ty e)\n{\n    Py_ssize_t i, elem_count;\n\n    APPEND_STR(\"[\");\n    elem_count = asdl_seq_LEN(e->v.List.elts);\n    for (i = 0; i < elem_count; i++) {\n        APPEND_STR_IF(i > 0, \", \");\n        APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.List.elts, i), PR_TEST);\n    }\n\n    APPEND_STR_FINISH(\"]\");\n}\n\nstatic int\nappend_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, int level)\n{\n    Py_ssize_t i, elem_count;\n\n    elem_count = asdl_seq_LEN(e->v.Tuple.elts);\n\n    if (elem_count == 0) {\n        APPEND_STR_FINISH(\"()\");\n    }\n\n    APPEND_STR_IF(level > PR_TUPLE, \"(\");\n\n    for (i = 0; i < elem_count; i++) {\n        APPEND_STR_IF(i > 0, \", \");\n        APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Tuple.elts, i), PR_TEST);\n    }\n\n    APPEND_STR_IF(elem_count == 1, \",\");\n    APPEND_STR_IF(level > PR_TUPLE, \")\");\n    return 0;\n}\n\nstatic int\nappend_ast_comprehension(_PyUnicodeWriter *writer, comprehension_ty gen)\n{\n    Py_ssize_t i, if_count;\n\n    APPEND_STR(gen->is_async ? \" async for \" : \" for \");\n    APPEND_EXPR(gen->target, PR_TUPLE);\n    APPEND_STR(\" in \");\n    APPEND_EXPR(gen->iter, PR_TEST + 1);\n\n    if_count = asdl_seq_LEN(gen->ifs);\n    for (i = 0; i < if_count; i++) {\n        APPEND_STR(\" if \");\n        APPEND_EXPR((expr_ty)asdl_seq_GET(gen->ifs, i), PR_TEST + 1);\n    }\n    return 0;\n}\n\nstatic int\nappend_ast_comprehensions(_PyUnicodeWriter *writer, asdl_comprehension_seq *comprehensions)\n{\n    Py_ssize_t i, gen_count;\n    gen_count = asdl_seq_LEN(comprehensions);\n\n    for (i = 0; i < gen_count; i++) {\n        APPEND(comprehension, (comprehension_ty)asdl_seq_GET(comprehensions, i));\n    }\n\n    return 0;\n}\n\nstatic int\nappend_ast_genexp(_PyUnicodeWriter *writer, expr_ty e)\n{\n    APPEND_STR(\"(\");\n    APPEND_EXPR(e->v.GeneratorExp.elt, PR_TEST);\n    APPEND(comprehensions, e->v.GeneratorExp.generators);\n    APPEND_STR_FINISH(\")\");\n}\n\nstatic int\nappend_ast_listcomp(_PyUnicodeWriter *writer, expr_ty e)\n{\n    APPEND_STR(\"[\");\n    APPEND_EXPR(e->v.ListComp.elt, PR_TEST);\n    APPEND(comprehensions, e->v.ListComp.generators);\n    APPEND_STR_FINISH(\"]\");\n}\n\nstatic int\nappend_ast_setcomp(_PyUnicodeWriter *writer, expr_ty e)\n{\n    APPEND_STR(\"{\");\n    APPEND_EXPR(e->v.SetComp.elt, PR_TEST);\n    APPEND(comprehensions, e->v.SetComp.generators);\n    APPEND_STR_FINISH(\"}\");\n}\n\nstatic int\nappend_ast_dictcomp(_PyUnicodeWriter *writer, expr_ty e)\n{\n    APPEND_STR(\"{\");\n    APPEND_EXPR(e->v.DictComp.key, PR_TEST);\n    APPEND_STR(\": \");\n    APPEND_EXPR(e->v.DictComp.value, PR_TEST);\n    APPEND(comprehensions, e->v.DictComp.generators);\n    APPEND_STR_FINISH(\"}\");\n}\n\nstatic int\nappend_ast_compare(_PyUnicodeWriter *writer, expr_ty e, int level)\n{\n    const char *op;\n    Py_ssize_t i, comparator_count;\n    asdl_expr_seq *comparators;\n    asdl_int_seq *ops;\n\n    APPEND_STR_IF(level > PR_CMP, \"(\");\n\n    comparators = e->v.Compare.comparators;\n    ops = e->v.Compare.ops;\n    comparator_count = asdl_seq_LEN(comparators);\n    assert(comparator_count > 0);\n    assert(comparator_count == asdl_seq_LEN(ops));\n\n    APPEND_EXPR(e->v.Compare.left, PR_CMP + 1);\n\n    for (i = 0; i < comparator_count; i++) {\n        switch ((cmpop_ty)asdl_seq_GET(ops, i)) {\n        case Eq:\n            op = \" == \";\n            break;\n        case NotEq:\n            op = \" != \";\n            break;\n        case Lt:\n            op = \" < \";\n            break;\n        case LtE:\n            op = \" <= \";\n            break;\n        case Gt:\n            op = \" > \";\n            break;\n        case GtE:\n            op = \" >= \";\n            break;\n        case Is:\n            op = \" is \";\n            break;\n        case IsNot:\n            op = \" is not \";\n            break;\n        case In:\n            op = \" in \";\n            break;\n        case NotIn:\n            op = \" not in \";\n            break;\n        default:\n            PyErr_SetString(PyExc_SystemError,\n                            \"unexpected comparison kind\");\n            return -1;\n        }\n\n        APPEND_STR(op);\n        APPEND_EXPR((expr_ty)asdl_seq_GET(comparators, i), PR_CMP + 1);\n    }\n\n    APPEND_STR_IF(level > PR_CMP, \")\");\n    return 0;\n}\n\nstatic int\nappend_ast_keyword(_PyUnicodeWriter *writer, keyword_ty kw)\n{\n    if (kw->arg == NULL) {\n        APPEND_STR(\"**\");\n    }\n    else {\n        if (-1 == _PyUnicodeWriter_WriteStr(writer, kw->arg)) {\n            return -1;\n        }\n\n        APPEND_STR(\"=\");\n    }\n\n    APPEND_EXPR(kw->value, PR_TEST);\n    return 0;\n}\n\nstatic int\nappend_ast_call(_PyUnicodeWriter *writer, expr_ty e)\n{\n    bool first;\n    Py_ssize_t i, arg_count, kw_count;\n    expr_ty expr;\n\n    APPEND_EXPR(e->v.Call.func, PR_ATOM);\n\n    arg_count = asdl_seq_LEN(e->v.Call.args);\n    kw_count = asdl_seq_LEN(e->v.Call.keywords);\n    if (arg_count == 1 && kw_count == 0) {\n        expr = (expr_ty)asdl_seq_GET(e->v.Call.args, 0);\n        if (expr->kind == GeneratorExp_kind) {\n            /* Special case: a single generator expression. */\n            return append_ast_genexp(writer, expr);\n        }\n    }\n\n    APPEND_STR(\"(\");\n\n    first = true;\n    for (i = 0; i < arg_count; i++) {\n        APPEND_STR_IF_NOT_FIRST(\", \");\n        APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Call.args, i), PR_TEST);\n    }\n\n    for (i = 0; i < kw_count; i++) {\n        APPEND_STR_IF_NOT_FIRST(\", \");\n        APPEND(keyword, (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i));\n    }\n\n    APPEND_STR_FINISH(\")\");\n}\n\nstatic PyObject *\nescape_braces(PyObject *orig)\n{\n    PyObject *temp;\n    PyObject *result;\n    temp = PyUnicode_Replace(orig, &_Py_STR(open_br), &_Py_STR(dbl_open_br), -1);\n    if (!temp) {\n        return NULL;\n    }\n    result = PyUnicode_Replace(temp, &_Py_STR(close_br), &_Py_STR(dbl_close_br), -1);\n    Py_DECREF(temp);\n    return result;\n}\n\nstatic int\nappend_fstring_unicode(_PyUnicodeWriter *writer, PyObject *unicode)\n{\n    PyObject *escaped;\n    int result = -1;\n    escaped = escape_braces(unicode);\n    if (escaped) {\n        result = _PyUnicodeWriter_WriteStr(writer, escaped);\n        Py_DECREF(escaped);\n    }\n    return result;\n}\n\nstatic int\nappend_fstring_element(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)\n{\n    switch (e->kind) {\n    case Constant_kind:\n        return append_fstring_unicode(writer, e->v.Constant.value);\n    case JoinedStr_kind:\n        return append_joinedstr(writer, e, is_format_spec);\n    case FormattedValue_kind:\n        return append_formattedvalue(writer, e);\n    default:\n        PyErr_SetString(PyExc_SystemError,\n                        \"unknown expression kind inside f-string\");\n        return -1;\n    }\n}\n\n/* Build body separately to enable wrapping the entire stream of Strs,\n   Constants and FormattedValues in one opening and one closing quote. */\nstatic PyObject *\nbuild_fstring_body(asdl_expr_seq *values, bool is_format_spec)\n{\n    Py_ssize_t i, value_count;\n    _PyUnicodeWriter body_writer;\n    _PyUnicodeWriter_Init(&body_writer);\n    body_writer.min_length = 256;\n    body_writer.overallocate = 1;\n\n    value_count = asdl_seq_LEN(values);\n    for (i = 0; i < value_count; ++i) {\n        if (-1 == append_fstring_element(&body_writer,\n                                         (expr_ty)asdl_seq_GET(values, i),\n                                         is_format_spec\n                                         )) {\n            _PyUnicodeWriter_Dealloc(&body_writer);\n            return NULL;\n        }\n    }\n\n    return _PyUnicodeWriter_Finish(&body_writer);\n}\n\nstatic int\nappend_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)\n{\n    int result = -1;\n    PyObject *body = build_fstring_body(e->v.JoinedStr.values, is_format_spec);\n    if (!body) {\n        return -1;\n    }\n\n    if (!is_format_spec) {\n        if (-1 != append_charp(writer, \"f\") &&\n            -1 != append_repr(writer, body))\n        {\n            result = 0;\n        }\n    }\n    else {\n        result = _PyUnicodeWriter_WriteStr(writer, body);\n    }\n    Py_DECREF(body);\n    return result;\n}\n\nstatic int\nappend_formattedvalue(_PyUnicodeWriter *writer, expr_ty e)\n{\n    const char *conversion;\n    const char *outer_brace = \"{\";\n    /* Grammar allows PR_TUPLE, but use >PR_TEST for adding parenthesis\n       around a lambda with ':' */\n    PyObject *temp_fv_str = expr_as_unicode(e->v.FormattedValue.value, PR_TEST + 1);\n    if (!temp_fv_str) {\n        return -1;\n    }\n    if (PyUnicode_Find(temp_fv_str, &_Py_STR(open_br), 0, 1, 1) == 0) {\n        /* Expression starts with a brace, split it with a space from the outer\n           one. */\n        outer_brace = \"{ \";\n    }\n    if (-1 == append_charp(writer, outer_brace)) {\n        Py_DECREF(temp_fv_str);\n        return -1;\n    }\n    if (-1 == _PyUnicodeWriter_WriteStr(writer, temp_fv_str)) {\n        Py_DECREF(temp_fv_str);\n        return -1;\n    }\n    Py_DECREF(temp_fv_str);\n\n    if (e->v.FormattedValue.conversion > 0) {\n        switch (e->v.FormattedValue.conversion) {\n        case 'a':\n            conversion = \"!a\";\n            break;\n        case 'r':\n            conversion = \"!r\";\n            break;\n        case 's':\n            conversion = \"!s\";\n            break;\n        default:\n            PyErr_SetString(PyExc_SystemError,\n                            \"unknown f-value conversion kind\");\n            return -1;\n        }\n        APPEND_STR(conversion);\n    }\n    if (e->v.FormattedValue.format_spec) {\n        if (-1 == _PyUnicodeWriter_WriteASCIIString(writer, \":\", 1) ||\n            -1 == append_fstring_element(writer,\n                                         e->v.FormattedValue.format_spec,\n                                         true\n                                        ))\n        {\n            return -1;\n        }\n    }\n\n    APPEND_STR_FINISH(\"}\");\n}\n\nstatic int\nappend_ast_constant(_PyUnicodeWriter *writer, PyObject *constant)\n{\n    if (PyTuple_CheckExact(constant)) {\n        Py_ssize_t i, elem_count;\n\n        elem_count = PyTuple_GET_SIZE(constant);\n        APPEND_STR(\"(\");\n        for (i = 0; i < elem_count; i++) {\n            APPEND_STR_IF(i > 0, \", \");\n            if (append_ast_constant(writer, PyTuple_GET_ITEM(constant, i)) < 0) {\n                return -1;\n            }\n        }\n\n        APPEND_STR_IF(elem_count == 1, \",\");\n        APPEND_STR(\")\");\n        return 0;\n    }\n    return append_repr(writer, constant);\n}\n\nstatic int\nappend_ast_attribute(_PyUnicodeWriter *writer, expr_ty e)\n{\n    const char *period;\n    expr_ty v = e->v.Attribute.value;\n    APPEND_EXPR(v, PR_ATOM);\n\n    /* Special case: integers require a space for attribute access to be\n       unambiguous. */\n    if (v->kind == Constant_kind && PyLong_CheckExact(v->v.Constant.value)) {\n        period = \" .\";\n    }\n    else {\n        period = \".\";\n    }\n    APPEND_STR(period);\n\n    return _PyUnicodeWriter_WriteStr(writer, e->v.Attribute.attr);\n}\n\nstatic int\nappend_ast_slice(_PyUnicodeWriter *writer, expr_ty e)\n{\n    if (e->v.Slice.lower) {\n        APPEND_EXPR(e->v.Slice.lower, PR_TEST);\n    }\n\n    APPEND_STR(\":\");\n\n    if (e->v.Slice.upper) {\n        APPEND_EXPR(e->v.Slice.upper, PR_TEST);\n    }\n\n    if (e->v.Slice.step) {\n        APPEND_STR(\":\");\n        APPEND_EXPR(e->v.Slice.step, PR_TEST);\n    }\n    return 0;\n}\n\nstatic int\nappend_ast_subscript(_PyUnicodeWriter *writer, expr_ty e)\n{\n    APPEND_EXPR(e->v.Subscript.value, PR_ATOM);\n    APPEND_STR(\"[\");\n    APPEND_EXPR(e->v.Subscript.slice, PR_TUPLE);\n    APPEND_STR_FINISH(\"]\");\n}\n\nstatic int\nappend_ast_starred(_PyUnicodeWriter *writer, expr_ty e)\n{\n    APPEND_STR(\"*\");\n    APPEND_EXPR(e->v.Starred.value, PR_EXPR);\n    return 0;\n}\n\nstatic int\nappend_ast_yield(_PyUnicodeWriter *writer, expr_ty e)\n{\n    if (!e->v.Yield.value) {\n        APPEND_STR_FINISH(\"(yield)\");\n    }\n\n    APPEND_STR(\"(yield \");\n    APPEND_EXPR(e->v.Yield.value, PR_TEST);\n    APPEND_STR_FINISH(\")\");\n}\n\nstatic int\nappend_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e)\n{\n    APPEND_STR(\"(yield from \");\n    APPEND_EXPR(e->v.YieldFrom.value, PR_TEST);\n    APPEND_STR_FINISH(\")\");\n}\n\nstatic int\nappend_ast_await(_PyUnicodeWriter *writer, expr_ty e, int level)\n{\n    APPEND_STR_IF(level > PR_AWAIT, \"(\");\n    APPEND_STR(\"await \");\n    APPEND_EXPR(e->v.Await.value, PR_ATOM);\n    APPEND_STR_IF(level > PR_AWAIT, \")\");\n    return 0;\n}\n\nstatic int\nappend_named_expr(_PyUnicodeWriter *writer, expr_ty e, int level)\n{\n    APPEND_STR_IF(level > PR_TUPLE, \"(\");\n    APPEND_EXPR(e->v.NamedExpr.target, PR_ATOM);\n    APPEND_STR(\" := \");\n    APPEND_EXPR(e->v.NamedExpr.value, PR_ATOM);\n    APPEND_STR_IF(level > PR_TUPLE, \")\");\n    return 0;\n}\n\nstatic int\nappend_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level)\n{\n    switch (e->kind) {\n    case BoolOp_kind:\n        return append_ast_boolop(writer, e, level);\n    case BinOp_kind:\n        return append_ast_binop(writer, e, level);\n    case UnaryOp_kind:\n        return append_ast_unaryop(writer, e, level);\n    case Lambda_kind:\n        return append_ast_lambda(writer, e, level);\n    case IfExp_kind:\n        return append_ast_ifexp(writer, e, level);\n    case Dict_kind:\n        return append_ast_dict(writer, e);\n    case Set_kind:\n        return append_ast_set(writer, e);\n    case GeneratorExp_kind:\n        return append_ast_genexp(writer, e);\n    case ListComp_kind:\n        return append_ast_listcomp(writer, e);\n    case SetComp_kind:\n        return append_ast_setcomp(writer, e);\n    case DictComp_kind:\n        return append_ast_dictcomp(writer, e);\n    case Yield_kind:\n        return append_ast_yield(writer, e);\n    case YieldFrom_kind:\n        return append_ast_yield_from(writer, e);\n    case Await_kind:\n        return append_ast_await(writer, e, level);\n    case Compare_kind:\n        return append_ast_compare(writer, e, level);\n    case Call_kind:\n        return append_ast_call(writer, e);\n    case Constant_kind:\n        if (e->v.Constant.value == Py_Ellipsis) {\n            APPEND_STR_FINISH(\"...\");\n        }\n        if (e->v.Constant.kind != NULL\n            && -1 == _PyUnicodeWriter_WriteStr(writer, e->v.Constant.kind)) {\n            return -1;\n        }\n        return append_ast_constant(writer, e->v.Constant.value);\n    case JoinedStr_kind:\n        return append_joinedstr(writer, e, false);\n    case FormattedValue_kind:\n        return append_formattedvalue(writer, e);\n    /* The following exprs can be assignment targets. */\n    case Attribute_kind:\n        return append_ast_attribute(writer, e);\n    case Subscript_kind:\n        return append_ast_subscript(writer, e);\n    case Starred_kind:\n        return append_ast_starred(writer, e);\n    case Slice_kind:\n        return append_ast_slice(writer, e);\n    case Name_kind:\n        return _PyUnicodeWriter_WriteStr(writer, e->v.Name.id);\n    case List_kind:\n        return append_ast_list(writer, e);\n    case Tuple_kind:\n        return append_ast_tuple(writer, e, level);\n    case NamedExpr_kind:\n        return append_named_expr(writer, e, level);\n    // No default so compiler emits a warning for unhandled cases\n    }\n    PyErr_SetString(PyExc_SystemError,\n                    \"unknown expression kind\");\n    return -1;\n}\n\nstatic int\nmaybe_init_static_strings(void)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (_str_replace_inf(interp) == NULL) {\n        PyObject *tmp = PyUnicode_FromFormat(\"1e%d\", 1 + DBL_MAX_10_EXP);\n        if (tmp == NULL) {\n            return -1;\n        }\n        _str_replace_inf(interp) = tmp;\n    }\n    return 0;\n}\n\nstatic PyObject *\nexpr_as_unicode(expr_ty e, int level)\n{\n    _PyUnicodeWriter writer;\n    _PyUnicodeWriter_Init(&writer);\n    writer.min_length = 256;\n    writer.overallocate = 1;\n    if (-1 == maybe_init_static_strings() ||\n        -1 == append_ast_expr(&writer, e, level))\n    {\n        _PyUnicodeWriter_Dealloc(&writer);\n        return NULL;\n    }\n    return _PyUnicodeWriter_Finish(&writer);\n}\n\nPyObject *\n_PyAST_ExprAsUnicode(expr_ty e)\n{\n    return expr_as_unicode(e, PR_TEST);\n}\n"
  },
  {
    "path": "BltinModule.c",
    "content": "/* Built-in functions */\n\n#include \"Python.h\"\n#include <ctype.h>\n#include \"pycore_ast.h\"           // _PyAST_Validate()\n#include \"pycore_call.h\"          // _PyObject_CallNoArgs()\n#include \"pycore_compile.h\"       // _PyAST_Compile()\n#include \"pycore_long.h\"          // _PyLong_CompactValue\n#include \"pycore_object.h\"        // _Py_AddToAllObjects()\n#include \"pycore_pyerrors.h\"      // _PyErr_NoMemory()\n#include \"pycore_pystate.h\"       // _PyThreadState_GET()\n#include \"pycore_tuple.h\"         // _PyTuple_FromArray()\n#include \"pycore_ceval.h\"         // _PyEval_Vector()\n\n#include \"clinic/bltinmodule.c.h\"\n\nstatic PyObject*\nupdate_bases(PyObject *bases, PyObject *const *args, Py_ssize_t nargs)\n{\n    Py_ssize_t i, j;\n    PyObject *base, *meth, *new_base, *result, *new_bases = NULL;\n    assert(PyTuple_Check(bases));\n\n    for (i = 0; i < nargs; i++) {\n        base  = args[i];\n        if (PyType_Check(base)) {\n            if (new_bases) {\n                /* If we already have made a replacement, then we append every normal base,\n                   otherwise just skip it. */\n                if (PyList_Append(new_bases, base) < 0) {\n                    goto error;\n                }\n            }\n            continue;\n        }\n        if (_PyObject_LookupAttr(base, &_Py_ID(__mro_entries__), &meth) < 0) {\n            goto error;\n        }\n        if (!meth) {\n            if (new_bases) {\n                if (PyList_Append(new_bases, base) < 0) {\n                    goto error;\n                }\n            }\n            continue;\n        }\n        new_base = PyObject_CallOneArg(meth, bases);\n        Py_DECREF(meth);\n        if (!new_base) {\n            goto error;\n        }\n        if (!PyTuple_Check(new_base)) {\n            PyErr_SetString(PyExc_TypeError,\n                            \"__mro_entries__ must return a tuple\");\n            Py_DECREF(new_base);\n            goto error;\n        }\n        if (!new_bases) {\n            /* If this is a first successful replacement, create new_bases list and\n               copy previously encountered bases. */\n            if (!(new_bases = PyList_New(i))) {\n                Py_DECREF(new_base);\n                goto error;\n            }\n            for (j = 0; j < i; j++) {\n                base = args[j];\n                PyList_SET_ITEM(new_bases, j, Py_NewRef(base));\n            }\n        }\n        j = PyList_GET_SIZE(new_bases);\n        if (PyList_SetSlice(new_bases, j, j, new_base) < 0) {\n            Py_DECREF(new_base);\n            goto error;\n        }\n        Py_DECREF(new_base);\n    }\n    if (!new_bases) {\n        return bases;\n    }\n    result = PyList_AsTuple(new_bases);\n    Py_DECREF(new_bases);\n    return result;\n\nerror:\n    Py_XDECREF(new_bases);\n    return NULL;\n}\n\n/* AC: cannot convert yet, waiting for *args support */\nstatic PyObject *\nbuiltin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs,\n                        PyObject *kwnames)\n{\n    PyObject *func, *name, *winner, *prep;\n    PyObject *cls = NULL, *cell = NULL, *ns = NULL, *meta = NULL, *orig_bases = NULL;\n    PyObject *mkw = NULL, *bases = NULL;\n    int isclass = 0;   /* initialize to prevent gcc warning */\n\n    if (nargs < 2) {\n        PyErr_SetString(PyExc_TypeError,\n                        \"__build_class__: not enough arguments\");\n        return NULL;\n    }\n    func = args[0];   /* Better be callable */\n    if (!PyFunction_Check(func)) {\n        PyErr_SetString(PyExc_TypeError,\n                        \"__build_class__: func must be a function\");\n        return NULL;\n    }\n    name = args[1];\n    if (!PyUnicode_Check(name)) {\n        PyErr_SetString(PyExc_TypeError,\n                        \"__build_class__: name is not a string\");\n        return NULL;\n    }\n    orig_bases = _PyTuple_FromArray(args + 2, nargs - 2);\n    if (orig_bases == NULL)\n        return NULL;\n\n    bases = update_bases(orig_bases, args + 2, nargs - 2);\n    if (bases == NULL) {\n        Py_DECREF(orig_bases);\n        return NULL;\n    }\n\n    if (kwnames == NULL) {\n        meta = NULL;\n        mkw = NULL;\n    }\n    else {\n        mkw = _PyStack_AsDict(args + nargs, kwnames);\n        if (mkw == NULL) {\n            goto error;\n        }\n\n        meta = _PyDict_GetItemWithError(mkw, &_Py_ID(metaclass));\n        if (meta != NULL) {\n            Py_INCREF(meta);\n            if (PyDict_DelItem(mkw, &_Py_ID(metaclass)) < 0) {\n                goto error;\n            }\n            /* metaclass is explicitly given, check if it's indeed a class */\n            isclass = PyType_Check(meta);\n        }\n        else if (PyErr_Occurred()) {\n            goto error;\n        }\n    }\n    if (meta == NULL) {\n        /* if there are no bases, use type: */\n        if (PyTuple_GET_SIZE(bases) == 0) {\n            meta = (PyObject *) (&PyType_Type);\n        }\n        /* else get the type of the first base */\n        else {\n            PyObject *base0 = PyTuple_GET_ITEM(bases, 0);\n            meta = (PyObject *)Py_TYPE(base0);\n        }\n        Py_INCREF(meta);\n        isclass = 1;  /* meta is really a class */\n    }\n\n    if (isclass) {\n        /* meta is really a class, so check for a more derived\n           metaclass, or possible metaclass conflicts: */\n        winner = (PyObject *)_PyType_CalculateMetaclass((PyTypeObject *)meta,\n                                                        bases);\n        if (winner == NULL) {\n            goto error;\n        }\n        if (winner != meta) {\n            Py_SETREF(meta, Py_NewRef(winner));\n        }\n    }\n    /* else: meta is not a class, so we cannot do the metaclass\n       calculation, so we will use the explicitly given object as it is */\n    if (_PyObject_LookupAttr(meta, &_Py_ID(__prepare__), &prep) < 0) {\n        ns = NULL;\n    }\n    else if (prep == NULL) {\n        ns = PyDict_New();\n    }\n    else {\n        PyObject *pargs[2] = {name, bases};\n        ns = PyObject_VectorcallDict(prep, pargs, 2, mkw);\n        Py_DECREF(prep);\n    }\n    if (ns == NULL) {\n        goto error;\n    }\n    if (!PyMapping_Check(ns)) {\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s.__prepare__() must return a mapping, not %.200s\",\n                     isclass ? ((PyTypeObject *)meta)->tp_name : \"<metaclass>\",\n                     Py_TYPE(ns)->tp_name);\n        goto error;\n    }\n    PyThreadState *tstate = _PyThreadState_GET();\n    EVAL_CALL_STAT_INC(EVAL_CALL_BUILD_CLASS);\n    cell = _PyEval_Vector(tstate, (PyFunctionObject *)func, ns, NULL, 0, NULL);\n    if (cell != NULL) {\n        if (bases != orig_bases) {\n            if (PyMapping_SetItemString(ns, \"__orig_bases__\", orig_bases) < 0) {\n                goto error;\n            }\n        }\n        PyObject *margs[3] = {name, bases, ns};\n        cls = PyObject_VectorcallDict(meta, margs, 3, mkw);\n        if (cls != NULL && PyType_Check(cls) && PyCell_Check(cell)) {\n            PyObject *cell_cls = PyCell_GET(cell);\n            if (cell_cls != cls) {\n                if (cell_cls == NULL) {\n                    const char *msg =\n                        \"__class__ not set defining %.200R as %.200R. \"\n                        \"Was __classcell__ propagated to type.__new__?\";\n                    PyErr_Format(PyExc_RuntimeError, msg, name, cls);\n                } else {\n                    const char *msg =\n                        \"__class__ set to %.200R defining %.200R as %.200R\";\n                    PyErr_Format(PyExc_TypeError, msg, cell_cls, name, cls);\n                }\n                Py_SETREF(cls, NULL);\n                goto error;\n            }\n        }\n    }\nerror:\n    Py_XDECREF(cell);\n    Py_XDECREF(ns);\n    Py_XDECREF(meta);\n    Py_XDECREF(mkw);\n    if (bases != orig_bases) {\n        Py_DECREF(orig_bases);\n    }\n    Py_DECREF(bases);\n    return cls;\n}\n\nPyDoc_STRVAR(build_class_doc,\n\"__build_class__(func, name, /, *bases, [metaclass], **kwds) -> class\\n\\\n\\n\\\nInternal helper function used by the class statement.\");\n\n/*[clinic input]\n__import__ as builtin___import__\n\n    name: object\n    globals: object(c_default=\"NULL\") = None\n    locals: object(c_default=\"NULL\") = None\n    fromlist: object(c_default=\"NULL\") = ()\n    level: int = 0\n\nImport a module.\n\nBecause this function is meant for use by the Python\ninterpreter and not for general use, it is better to use\nimportlib.import_module() to programmatically import a module.\n\nThe globals argument is only used to determine the context;\nthey are not modified.  The locals argument is unused.  The fromlist\nshould be a list of names to emulate ``from name import ...``, or an\nempty list to emulate ``import name``.\nWhen importing a module from a package, note that __import__('A.B', ...)\nreturns package A when fromlist is empty, but its submodule B when\nfromlist is not empty.  The level argument is used to determine whether to\nperform absolute or relative imports: 0 is absolute, while a positive number\nis the number of parent directories to search relative to the current module.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin___import___impl(PyObject *module, PyObject *name, PyObject *globals,\n                        PyObject *locals, PyObject *fromlist, int level)\n/*[clinic end generated code: output=4febeda88a0cd245 input=73f4b960ea5b9dd6]*/\n{\n    return PyImport_ImportModuleLevelObject(name, globals, locals,\n                                            fromlist, level);\n}\n\n\n/*[clinic input]\nabs as builtin_abs\n\n    x: object\n    /\n\nReturn the absolute value of the argument.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_abs(PyObject *module, PyObject *x)\n/*[clinic end generated code: output=b1b433b9e51356f5 input=bed4ca14e29c20d1]*/\n{\n    return PyNumber_Absolute(x);\n}\n\n/*[clinic input]\nall as builtin_all\n\n    iterable: object\n    /\n\nReturn True if bool(x) is True for all values x in the iterable.\n\nIf the iterable is empty, return True.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_all(PyObject *module, PyObject *iterable)\n/*[clinic end generated code: output=ca2a7127276f79b3 input=1a7c5d1bc3438a21]*/\n{\n    PyObject *it, *item;\n    PyObject *(*iternext)(PyObject *);\n    int cmp;\n\n    it = PyObject_GetIter(iterable);\n    if (it == NULL)\n        return NULL;\n    iternext = *Py_TYPE(it)->tp_iternext;\n\n    for (;;) {\n        item = iternext(it);\n        if (item == NULL)\n            break;\n        cmp = PyObject_IsTrue(item);\n        Py_DECREF(item);\n        if (cmp < 0) {\n            Py_DECREF(it);\n            return NULL;\n        }\n        if (cmp == 0) {\n            Py_DECREF(it);\n            Py_RETURN_FALSE;\n        }\n    }\n    Py_DECREF(it);\n    if (PyErr_Occurred()) {\n        if (PyErr_ExceptionMatches(PyExc_StopIteration))\n            PyErr_Clear();\n        else\n            return NULL;\n    }\n    Py_RETURN_TRUE;\n}\n\n/*[clinic input]\nany as builtin_any\n\n    iterable: object\n    /\n\nReturn True if bool(x) is True for any x in the iterable.\n\nIf the iterable is empty, return False.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_any(PyObject *module, PyObject *iterable)\n/*[clinic end generated code: output=fa65684748caa60e input=41d7451c23384f24]*/\n{\n    PyObject *it, *item;\n    PyObject *(*iternext)(PyObject *);\n    int cmp;\n\n    it = PyObject_GetIter(iterable);\n    if (it == NULL)\n        return NULL;\n    iternext = *Py_TYPE(it)->tp_iternext;\n\n    for (;;) {\n        item = iternext(it);\n        if (item == NULL)\n            break;\n        cmp = PyObject_IsTrue(item);\n        Py_DECREF(item);\n        if (cmp < 0) {\n            Py_DECREF(it);\n            return NULL;\n        }\n        if (cmp > 0) {\n            Py_DECREF(it);\n            Py_RETURN_TRUE;\n        }\n    }\n    Py_DECREF(it);\n    if (PyErr_Occurred()) {\n        if (PyErr_ExceptionMatches(PyExc_StopIteration))\n            PyErr_Clear();\n        else\n            return NULL;\n    }\n    Py_RETURN_FALSE;\n}\n\n/*[clinic input]\nascii as builtin_ascii\n\n    obj: object\n    /\n\nReturn an ASCII-only representation of an object.\n\nAs repr(), return a string containing a printable representation of an\nobject, but escape the non-ASCII characters in the string returned by\nrepr() using \\\\x, \\\\u or \\\\U escapes. This generates a string similar\nto that returned by repr() in Python 2.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_ascii(PyObject *module, PyObject *obj)\n/*[clinic end generated code: output=6d37b3f0984c7eb9 input=4c62732e1b3a3cc9]*/\n{\n    return PyObject_ASCII(obj);\n}\n\n\n/*[clinic input]\nbin as builtin_bin\n\n    number: object\n    /\n\nReturn the binary representation of an integer.\n\n   >>> bin(2796202)\n   '0b1010101010101010101010'\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_bin(PyObject *module, PyObject *number)\n/*[clinic end generated code: output=b6fc4ad5e649f4f7 input=53f8a0264bacaf90]*/\n{\n    return PyNumber_ToBase(number, 2);\n}\n\n\n/*[clinic input]\ncallable as builtin_callable\n\n    obj: object\n    /\n\nReturn whether the object is callable (i.e., some kind of function).\n\nNote that classes are callable, as are instances of classes with a\n__call__() method.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_callable(PyObject *module, PyObject *obj)\n/*[clinic end generated code: output=2b095d59d934cb7e input=1423bab99cc41f58]*/\n{\n    return PyBool_FromLong((long)PyCallable_Check(obj));\n}\n\nstatic PyObject *\nbuiltin_breakpoint(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords)\n{\n    PyObject *hook = PySys_GetObject(\"breakpointhook\");\n\n    if (hook == NULL) {\n        PyErr_SetString(PyExc_RuntimeError, \"lost sys.breakpointhook\");\n        return NULL;\n    }\n\n    if (PySys_Audit(\"builtins.breakpoint\", \"O\", hook) < 0) {\n        return NULL;\n    }\n\n    Py_INCREF(hook);\n    PyObject *retval = PyObject_Vectorcall(hook, args, nargs, keywords);\n    Py_DECREF(hook);\n    return retval;\n}\n\nPyDoc_STRVAR(breakpoint_doc,\n\"breakpoint(*args, **kws)\\n\\\n\\n\\\nCall sys.breakpointhook(*args, **kws).  sys.breakpointhook() must accept\\n\\\nwhatever arguments are passed.\\n\\\n\\n\\\nBy default, this drops you into the pdb debugger.\");\n\ntypedef struct {\n    PyObject_HEAD\n    PyObject *func;\n    PyObject *it;\n} filterobject;\n\nstatic PyObject *\nfilter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n{\n    PyObject *func, *seq;\n    PyObject *it;\n    filterobject *lz;\n\n    if ((type == &PyFilter_Type || type->tp_init == PyFilter_Type.tp_init) &&\n        !_PyArg_NoKeywords(\"filter\", kwds))\n        return NULL;\n\n    if (!PyArg_UnpackTuple(args, \"filter\", 2, 2, &func, &seq))\n        return NULL;\n\n    /* Get iterator. */\n    it = PyObject_GetIter(seq);\n    if (it == NULL)\n        return NULL;\n\n    /* create filterobject structure */\n    lz = (filterobject *)type->tp_alloc(type, 0);\n    if (lz == NULL) {\n        Py_DECREF(it);\n        return NULL;\n    }\n\n    lz->func = Py_NewRef(func);\n    lz->it = it;\n\n    return (PyObject *)lz;\n}\n\nstatic PyObject *\nfilter_vectorcall(PyObject *type, PyObject * const*args,\n                size_t nargsf, PyObject *kwnames)\n{\n    PyTypeObject *tp = _PyType_CAST(type);\n    if (tp == &PyFilter_Type && !_PyArg_NoKwnames(\"filter\", kwnames)) {\n        return NULL;\n    }\n\n    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);\n    if (!_PyArg_CheckPositional(\"filter\", nargs, 2, 2)) {\n        return NULL;\n    }\n\n    PyObject *it = PyObject_GetIter(args[1]);\n    if (it == NULL) {\n        return NULL;\n    }\n\n    filterobject *lz = (filterobject *)tp->tp_alloc(tp, 0);\n\n    if (lz == NULL) {\n        Py_DECREF(it);\n        return NULL;\n    }\n\n    lz->func = Py_NewRef(args[0]);\n    lz->it = it;\n\n    return (PyObject *)lz;\n}\n\nstatic void\nfilter_dealloc(filterobject *lz)\n{\n    PyObject_GC_UnTrack(lz);\n    Py_TRASHCAN_BEGIN(lz, filter_dealloc)\n    Py_XDECREF(lz->func);\n    Py_XDECREF(lz->it);\n    Py_TYPE(lz)->tp_free(lz);\n    Py_TRASHCAN_END\n}\n\nstatic int\nfilter_traverse(filterobject *lz, visitproc visit, void *arg)\n{\n    Py_VISIT(lz->it);\n    Py_VISIT(lz->func);\n    return 0;\n}\n\nstatic PyObject *\nfilter_next(filterobject *lz)\n{\n    PyObject *item;\n    PyObject *it = lz->it;\n    long ok;\n    PyObject *(*iternext)(PyObject *);\n    int checktrue = lz->func == Py_None || lz->func == (PyObject *)&PyBool_Type;\n\n    iternext = *Py_TYPE(it)->tp_iternext;\n    for (;;) {\n        item = iternext(it);\n        if (item == NULL)\n            return NULL;\n\n        if (checktrue) {\n            ok = PyObject_IsTrue(item);\n        } else {\n            PyObject *good;\n            good = PyObject_CallOneArg(lz->func, item);\n            if (good == NULL) {\n                Py_DECREF(item);\n                return NULL;\n            }\n            ok = PyObject_IsTrue(good);\n            Py_DECREF(good);\n        }\n        if (ok > 0)\n            return item;\n        Py_DECREF(item);\n        if (ok < 0)\n            return NULL;\n    }\n}\n\nstatic PyObject *\nfilter_reduce(filterobject *lz, PyObject *Py_UNUSED(ignored))\n{\n    return Py_BuildValue(\"O(OO)\", Py_TYPE(lz), lz->func, lz->it);\n}\n\nPyDoc_STRVAR(reduce_doc, \"Return state information for pickling.\");\n\nstatic PyMethodDef filter_methods[] = {\n    {\"__reduce__\", _PyCFunction_CAST(filter_reduce), METH_NOARGS, reduce_doc},\n    {NULL,           NULL}           /* sentinel */\n};\n\nPyDoc_STRVAR(filter_doc,\n\"filter(function or None, iterable) --> filter object\\n\\\n\\n\\\nReturn an iterator yielding those items of iterable for which function(item)\\n\\\nis true. If function is None, return the items that are true.\");\n\nPyTypeObject PyFilter_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"filter\",                           /* tp_name */\n    sizeof(filterobject),               /* tp_basicsize */\n    0,                                  /* tp_itemsize */\n    /* methods */\n    (destructor)filter_dealloc,         /* tp_dealloc */\n    0,                                  /* tp_vectorcall_offset */\n    0,                                  /* tp_getattr */\n    0,                                  /* tp_setattr */\n    0,                                  /* tp_as_async */\n    0,                                  /* tp_repr */\n    0,                                  /* tp_as_number */\n    0,                                  /* tp_as_sequence */\n    0,                                  /* tp_as_mapping */\n    0,                                  /* tp_hash */\n    0,                                  /* tp_call */\n    0,                                  /* tp_str */\n    PyObject_GenericGetAttr,            /* tp_getattro */\n    0,                                  /* tp_setattro */\n    0,                                  /* tp_as_buffer */\n    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\n        Py_TPFLAGS_BASETYPE,            /* tp_flags */\n    filter_doc,                         /* tp_doc */\n    (traverseproc)filter_traverse,      /* tp_traverse */\n    0,                                  /* tp_clear */\n    0,                                  /* tp_richcompare */\n    0,                                  /* tp_weaklistoffset */\n    PyObject_SelfIter,                  /* tp_iter */\n    (iternextfunc)filter_next,          /* tp_iternext */\n    filter_methods,                     /* tp_methods */\n    0,                                  /* tp_members */\n    0,                                  /* tp_getset */\n    0,                                  /* tp_base */\n    0,                                  /* tp_dict */\n    0,                                  /* tp_descr_get */\n    0,                                  /* tp_descr_set */\n    0,                                  /* tp_dictoffset */\n    0,                                  /* tp_init */\n    PyType_GenericAlloc,                /* tp_alloc */\n    filter_new,                         /* tp_new */\n    PyObject_GC_Del,                    /* tp_free */\n    .tp_vectorcall = (vectorcallfunc)filter_vectorcall\n};\n\n\n/*[clinic input]\nformat as builtin_format\n\n    value: object\n    format_spec: unicode(c_default=\"NULL\") = ''\n    /\n\nReturn type(value).__format__(value, format_spec)\n\nMany built-in types implement format_spec according to the\nFormat Specification Mini-language. See help('FORMATTING').\n\nIf type(value) does not supply a method named __format__\nand format_spec is empty, then str(value) is returned.\nSee also help('SPECIALMETHODS').\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_format_impl(PyObject *module, PyObject *value, PyObject *format_spec)\n/*[clinic end generated code: output=2f40bdfa4954b077 input=45ef3934b86d5624]*/\n{\n    return PyObject_Format(value, format_spec);\n}\n\n/*[clinic input]\nchr as builtin_chr\n\n    i: int\n    /\n\nReturn a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_chr_impl(PyObject *module, int i)\n/*[clinic end generated code: output=c733afcd200afcb7 input=3f604ef45a70750d]*/\n{\n    return PyUnicode_FromOrdinal(i);\n}\n\n\n/*[clinic input]\ncompile as builtin_compile\n\n    source: object\n    filename: object(converter=\"PyUnicode_FSDecoder\")\n    mode: str\n    flags: int = 0\n    dont_inherit: bool = False\n    optimize: int = -1\n    *\n    _feature_version as feature_version: int = -1\n\nCompile source into a code object that can be executed by exec() or eval().\n\nThe source code may represent a Python module, statement or expression.\nThe filename will be used for run-time error messages.\nThe mode must be 'exec' to compile a module, 'single' to compile a\nsingle (interactive) statement, or 'eval' to compile an expression.\nThe flags argument, if present, controls which future statements influence\nthe compilation of the code.\nThe dont_inherit argument, if true, stops the compilation inheriting\nthe effects of any future statements in effect in the code calling\ncompile; if absent or false these statements do influence the compilation,\nin addition to any features explicitly specified.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_compile_impl(PyObject *module, PyObject *source, PyObject *filename,\n                     const char *mode, int flags, int dont_inherit,\n                     int optimize, int feature_version)\n/*[clinic end generated code: output=b0c09c84f116d3d7 input=cc78e20e7c7682ba]*/\n{\n    PyObject *source_copy;\n    const char *str;\n    int compile_mode = -1;\n    int is_ast;\n    int start[] = {Py_file_input, Py_eval_input, Py_single_input, Py_func_type_input};\n    PyObject *result;\n\n    PyCompilerFlags cf = _PyCompilerFlags_INIT;\n    cf.cf_flags = flags | PyCF_SOURCE_IS_UTF8;\n    if (feature_version >= 0 && (flags & PyCF_ONLY_AST)) {\n        cf.cf_feature_version = feature_version;\n    }\n\n    if (flags &\n        ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_COMPILE_MASK))\n    {\n        PyErr_SetString(PyExc_ValueError,\n                        \"compile(): unrecognised flags\");\n        goto error;\n    }\n    /* XXX Warn if (supplied_flags & PyCF_MASK_OBSOLETE) != 0? */\n\n    if (optimize < -1 || optimize > 2) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"compile(): invalid optimize value\");\n        goto error;\n    }\n\n    if (!dont_inherit) {\n        PyEval_MergeCompilerFlags(&cf);\n    }\n\n    if (strcmp(mode, \"exec\") == 0)\n        compile_mode = 0;\n    else if (strcmp(mode, \"eval\") == 0)\n        compile_mode = 1;\n    else if (strcmp(mode, \"single\") == 0)\n        compile_mode = 2;\n    else if (strcmp(mode, \"func_type\") == 0) {\n        if (!(flags & PyCF_ONLY_AST)) {\n            PyErr_SetString(PyExc_ValueError,\n                            \"compile() mode 'func_type' requires flag PyCF_ONLY_AST\");\n            goto error;\n        }\n        compile_mode = 3;\n    }\n    else {\n        const char *msg;\n        if (flags & PyCF_ONLY_AST)\n            msg = \"compile() mode must be 'exec', 'eval', 'single' or 'func_type'\";\n        else\n            msg = \"compile() mode must be 'exec', 'eval' or 'single'\";\n        PyErr_SetString(PyExc_ValueError, msg);\n        goto error;\n    }\n\n    is_ast = PyAST_Check(source);\n    if (is_ast == -1)\n        goto error;\n    if (is_ast) {\n        if (flags & PyCF_ONLY_AST) {\n            result = Py_NewRef(source);\n        }\n        else {\n            PyArena *arena;\n            mod_ty mod;\n\n            arena = _PyArena_New();\n            if (arena == NULL)\n                goto error;\n            mod = PyAST_obj2mod(source, arena, compile_mode);\n            if (mod == NULL || !_PyAST_Validate(mod)) {\n                _PyArena_Free(arena);\n                goto error;\n            }\n            result = (PyObject*)_PyAST_Compile(mod, filename,\n                                               &cf, optimize, arena);\n            _PyArena_Free(arena);\n        }\n        goto finally;\n    }\n\n    str = _Py_SourceAsString(source, \"compile\", \"string, bytes or AST\", &cf, &source_copy);\n    if (str == NULL)\n        goto error;\n\n    result = Py_CompileStringObject(str, filename, start[compile_mode], &cf, optimize);\n\n    Py_XDECREF(source_copy);\n    goto finally;\n\nerror:\n    result = NULL;\nfinally:\n    Py_DECREF(filename);\n    return result;\n}\n\n/*[clinic input]\ndir as builtin_dir\n\n    arg: object = NULL\n    /\n\nShow attributes of an object.\n\nIf called without an argument, return the names in the current scope.\nElse, return an alphabetized list of names comprising (some of) the attributes\nof the given object, and of attributes reachable from it.\nIf the object supplies a method named __dir__, it will be used; otherwise\nthe default dir() logic is used and returns:\n  for a module object: the module's attributes.\n  for a class object:  its attributes, and recursively the attributes\n    of its bases.\n  for any other object: its attributes, its class's attributes, and\n    recursively the attributes of its class's base classes.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_dir_impl(PyObject *module, PyObject *arg)\n/*[clinic end generated code: output=24f2c7a52c1e3b08 input=ed6d6ccb13d52251]*/\n{\n    return PyObject_Dir(arg);\n}\n\n/*[clinic input]\ndivmod as builtin_divmod\n\n    x: object\n    y: object\n    /\n\nReturn the tuple (x//y, x%y).  Invariant: div*y + mod == x.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_divmod_impl(PyObject *module, PyObject *x, PyObject *y)\n/*[clinic end generated code: output=b06d8a5f6e0c745e input=175ad9c84ff41a85]*/\n{\n    return PyNumber_Divmod(x, y);\n}\n\n\n/*[clinic input]\neval as builtin_eval\n\n    source: object\n    globals: object = None\n    locals: object = None\n    /\n\nEvaluate the given source in the context of globals and locals.\n\nThe source may be a string representing a Python expression\nor a code object as returned by compile().\nThe globals must be a dictionary and locals can be any mapping,\ndefaulting to the current globals and locals.\nIf only globals is given, locals defaults to it.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,\n                  PyObject *locals)\n/*[clinic end generated code: output=0a0824aa70093116 input=11ee718a8640e527]*/\n{\n    PyObject *result, *source_copy;\n    const char *str;\n\n    if (locals != Py_None && !PyMapping_Check(locals)) {\n        PyErr_SetString(PyExc_TypeError, \"locals must be a mapping\");\n        return NULL;\n    }\n    if (globals != Py_None && !PyDict_Check(globals)) {\n        PyErr_SetString(PyExc_TypeError, PyMapping_Check(globals) ?\n            \"globals must be a real dict; try eval(expr, {}, mapping)\"\n            : \"globals must be a dict\");\n        return NULL;\n    }\n    if (globals == Py_None) {\n        globals = PyEval_GetGlobals();\n        if (locals == Py_None) {\n            locals = PyEval_GetLocals();\n            if (locals == NULL)\n                return NULL;\n        }\n    }\n    else if (locals == Py_None)\n        locals = globals;\n\n    if (globals == NULL || locals == NULL) {\n        PyErr_SetString(PyExc_TypeError,\n            \"eval must be given globals and locals \"\n            \"when called without a frame\");\n        return NULL;\n    }\n\n    int r = PyDict_Contains(globals, &_Py_ID(__builtins__));\n    if (r == 0) {\n        r = PyDict_SetItem(globals, &_Py_ID(__builtins__), PyEval_GetBuiltins());\n    }\n    if (r < 0) {\n        return NULL;\n    }\n\n    if (PyCode_Check(source)) {\n        if (PySys_Audit(\"exec\", \"O\", source) < 0) {\n            return NULL;\n        }\n\n        if (PyCode_GetNumFree((PyCodeObject *)source) > 0) {\n            PyErr_SetString(PyExc_TypeError,\n                \"code object passed to eval() may not contain free variables\");\n            return NULL;\n        }\n        return PyEval_EvalCode(source, globals, locals);\n    }\n\n    PyCompilerFlags cf = _PyCompilerFlags_INIT;\n    cf.cf_flags = PyCF_SOURCE_IS_UTF8;\n    str = _Py_SourceAsString(source, \"eval\", \"string, bytes or code\", &cf, &source_copy);\n    if (str == NULL)\n        return NULL;\n\n    while (*str == ' ' || *str == '\\t')\n        str++;\n\n    (void)PyEval_MergeCompilerFlags(&cf);\n    result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf);\n    Py_XDECREF(source_copy);\n    return result;\n}\n\n/*[clinic input]\nexec as builtin_exec\n\n    source: object\n    globals: object = None\n    locals: object = None\n    /\n    *\n    closure: object(c_default=\"NULL\") = None\n\nExecute the given source in the context of globals and locals.\n\nThe source may be a string representing one or more Python statements\nor a code object as returned by compile().\nThe globals must be a dictionary and locals can be any mapping,\ndefaulting to the current globals and locals.\nIf only globals is given, locals defaults to it.\nThe closure must be a tuple of cellvars, and can only be used\nwhen source is a code object requiring exactly that many cellvars.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,\n                  PyObject *locals, PyObject *closure)\n/*[clinic end generated code: output=7579eb4e7646743d input=f13a7e2b503d1d9a]*/\n{\n    PyObject *v;\n\n    if (globals == Py_None) {\n        globals = PyEval_GetGlobals();\n        if (locals == Py_None) {\n            locals = PyEval_GetLocals();\n            if (locals == NULL)\n                return NULL;\n        }\n        if (!globals || !locals) {\n            PyErr_SetString(PyExc_SystemError,\n                            \"globals and locals cannot be NULL\");\n            return NULL;\n        }\n    }\n    else if (locals == Py_None)\n        locals = globals;\n\n    if (!PyDict_Check(globals)) {\n        PyErr_Format(PyExc_TypeError, \"exec() globals must be a dict, not %.100s\",\n                     Py_TYPE(globals)->tp_name);\n        return NULL;\n    }\n    if (!PyMapping_Check(locals)) {\n        PyErr_Format(PyExc_TypeError,\n            \"locals must be a mapping or None, not %.100s\",\n            Py_TYPE(locals)->tp_name);\n        return NULL;\n    }\n    int r = PyDict_Contains(globals, &_Py_ID(__builtins__));\n    if (r == 0) {\n        r = PyDict_SetItem(globals, &_Py_ID(__builtins__), PyEval_GetBuiltins());\n    }\n    if (r < 0) {\n        return NULL;\n    }\n\n    if (closure == Py_None) {\n        closure = NULL;\n    }\n\n    if (PyCode_Check(source)) {\n        Py_ssize_t num_free = PyCode_GetNumFree((PyCodeObject *)source);\n        if (num_free == 0) {\n            if (closure) {\n                PyErr_SetString(PyExc_TypeError,\n                    \"cannot use a closure with this code object\");\n                return NULL;\n            }\n        } else {\n            int closure_is_ok =\n                closure\n                && PyTuple_CheckExact(closure)\n                && (PyTuple_GET_SIZE(closure) == num_free);\n            if (closure_is_ok) {\n                for (Py_ssize_t i = 0; i < num_free; i++) {\n                    PyObject *cell = PyTuple_GET_ITEM(closure, i);\n                    if (!PyCell_Check(cell)) {\n                        closure_is_ok = 0;\n                        break;\n                    }\n                }\n            }\n            if (!closure_is_ok) {\n                PyErr_Format(PyExc_TypeError,\n                    \"code object requires a closure of exactly length %zd\",\n                    num_free);\n                return NULL;\n            }\n        }\n\n        if (PySys_Audit(\"exec\", \"O\", source) < 0) {\n            return NULL;\n        }\n\n        if (!closure) {\n            v = PyEval_EvalCode(source, globals, locals);\n        } else {\n            v = PyEval_EvalCodeEx(source, globals, locals,\n                NULL, 0,\n                NULL, 0,\n                NULL, 0,\n                NULL,\n                closure);\n        }\n    }\n    else {\n        if (closure != NULL) {\n            PyErr_SetString(PyExc_TypeError,\n                \"closure can only be used when source is a code object\");\n        }\n        PyObject *source_copy;\n        const char *str;\n        PyCompilerFlags cf = _PyCompilerFlags_INIT;\n        cf.cf_flags = PyCF_SOURCE_IS_UTF8;\n        str = _Py_SourceAsString(source, \"exec\",\n                                       \"string, bytes or code\", &cf,\n                                       &source_copy);\n        if (str == NULL)\n            return NULL;\n        if (PyEval_MergeCompilerFlags(&cf))\n            v = PyRun_StringFlags(str, Py_file_input, globals,\n                                  locals, &cf);\n        else\n            v = PyRun_String(str, Py_file_input, globals, locals);\n        Py_XDECREF(source_copy);\n    }\n    if (v == NULL)\n        return NULL;\n    Py_DECREF(v);\n    Py_RETURN_NONE;\n}\n\n\n/*[clinic input]\ngetattr as builtin_getattr\n\n    object: object\n    name: object\n    default: object = NULL\n    /\n\nGet a named attribute from an object.\n\ngetattr(x, 'y') is equivalent to x.y\nWhen a default argument is given, it is returned when the attribute doesn't\nexist; without it, an exception is raised in that case.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_getattr_impl(PyObject *module, PyObject *object, PyObject *name,\n                     PyObject *default_value)\n/*[clinic end generated code: output=74ad0e225e3f701c input=d7562cd4c3556171]*/\n{\n    PyObject *result;\n\n    if (default_value != NULL) {\n        if (_PyObject_LookupAttr(object, name, &result) == 0) {\n            return Py_NewRef(default_value);\n        }\n    }\n    else {\n        result = PyObject_GetAttr(object, name);\n    }\n    return result;\n}\n\n\n/*[clinic input]\nglobals as builtin_globals\n\nReturn the dictionary containing the current scope's global variables.\n\nNOTE: Updates to this dictionary *will* affect name lookups in the current\nglobal scope and vice-versa.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_globals_impl(PyObject *module)\n/*[clinic end generated code: output=e5dd1527067b94d2 input=9327576f92bb48ba]*/\n{\n    PyObject *d;\n\n    d = PyEval_GetGlobals();\n    return Py_XNewRef(d);\n}\n\n\n/*[clinic input]\nhasattr as builtin_hasattr\n\n    obj: object\n    name: object\n    /\n\nReturn whether the object has an attribute with the given name.\n\nThis is done by calling getattr(obj, name) and catching AttributeError.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_hasattr_impl(PyObject *module, PyObject *obj, PyObject *name)\n/*[clinic end generated code: output=a7aff2090a4151e5 input=0faec9787d979542]*/\n{\n    PyObject *v;\n\n    if (_PyObject_LookupAttr(obj, name, &v) < 0) {\n        return NULL;\n    }\n    if (v == NULL) {\n        Py_RETURN_FALSE;\n    }\n    Py_DECREF(v);\n    Py_RETURN_TRUE;\n}\n\n\n/* AC: gdb's integration with CPython relies on builtin_id having\n * the *exact* parameter names of \"self\" and \"v\", so we ensure we\n * preserve those name rather than using the AC defaults.\n */\n/*[clinic input]\nid as builtin_id\n\n    self: self(type=\"PyModuleDef *\")\n    obj as v: object\n    /\n\nReturn the identity of an object.\n\nThis is guaranteed to be unique among simultaneously existing objects.\n(CPython uses the object's memory address.)\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_id(PyModuleDef *self, PyObject *v)\n/*[clinic end generated code: output=0aa640785f697f65 input=5a534136419631f4]*/\n{\n    PyObject *id = PyLong_FromVoidPtr(v);\n\n    if (id && PySys_Audit(\"builtins.id\", \"O\", id) < 0) {\n        Py_DECREF(id);\n        return NULL;\n    }\n\n    return id;\n}\n\n\n/* map object ************************************************************/\n\ntypedef struct {\n    PyObject_HEAD\n    PyObject *iters;\n    PyObject *func;\n} mapobject;\n\nstatic PyObject *\nmap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n{\n    PyObject *it, *iters, *func;\n    mapobject *lz;\n    Py_ssize_t numargs, i;\n\n    if ((type == &PyMap_Type || type->tp_init == PyMap_Type.tp_init) &&\n        !_PyArg_NoKeywords(\"map\", kwds))\n        return NULL;\n\n    numargs = PyTuple_Size(args);\n    if (numargs < 2) {\n        PyErr_SetString(PyExc_TypeError,\n           \"map() must have at least two arguments.\");\n        return NULL;\n    }\n\n    iters = PyTuple_New(numargs-1);\n    if (iters == NULL)\n        return NULL;\n\n    for (i=1 ; i<numargs ; i++) {\n        /* Get iterator. */\n        it = PyObject_GetIter(PyTuple_GET_ITEM(args, i));\n        if (it == NULL) {\n            Py_DECREF(iters);\n            return NULL;\n        }\n        PyTuple_SET_ITEM(iters, i-1, it);\n    }\n\n    /* create mapobject structure */\n    lz = (mapobject *)type->tp_alloc(type, 0);\n    if (lz == NULL) {\n        Py_DECREF(iters);\n        return NULL;\n    }\n    lz->iters = iters;\n    func = PyTuple_GET_ITEM(args, 0);\n    lz->func = Py_NewRef(func);\n\n    return (PyObject *)lz;\n}\n\nstatic PyObject *\nmap_vectorcall(PyObject *type, PyObject * const*args,\n                size_t nargsf, PyObject *kwnames)\n{\n    PyTypeObject *tp = _PyType_CAST(type);\n    if (tp == &PyMap_Type && !_PyArg_NoKwnames(\"map\", kwnames)) {\n        return NULL;\n    }\n\n    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);\n    if (nargs < 2) {\n        PyErr_SetString(PyExc_TypeError,\n           \"map() must have at least two arguments.\");\n        return NULL;\n    }\n\n    PyObject *iters = PyTuple_New(nargs-1);\n    if (iters == NULL) {\n        return NULL;\n    }\n\n    for (int i=1; i<nargs; i++) {\n        PyObject *it = PyObject_GetIter(args[i]);\n        if (it == NULL) {\n            Py_DECREF(iters);\n            return NULL;\n        }\n        PyTuple_SET_ITEM(iters, i-1, it);\n    }\n\n    mapobject *lz = (mapobject *)tp->tp_alloc(tp, 0);\n    if (lz == NULL) {\n        Py_DECREF(iters);\n        return NULL;\n    }\n    lz->iters = iters;\n    lz->func = Py_NewRef(args[0]);\n\n    return (PyObject *)lz;\n}\n\nstatic void\nmap_dealloc(mapobject *lz)\n{\n    PyObject_GC_UnTrack(lz);\n    Py_XDECREF(lz->iters);\n    Py_XDECREF(lz->func);\n    Py_TYPE(lz)->tp_free(lz);\n}\n\nstatic int\nmap_traverse(mapobject *lz, visitproc visit, void *arg)\n{\n    Py_VISIT(lz->iters);\n    Py_VISIT(lz->func);\n    return 0;\n}\n\nstatic PyObject *\nmap_next(mapobject *lz)\n{\n    PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];\n    PyObject **stack;\n    PyObject *result = NULL;\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    const Py_ssize_t niters = PyTuple_GET_SIZE(lz->iters);\n    if (niters <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {\n        stack = small_stack;\n    }\n    else {\n        stack = PyMem_Malloc(niters * sizeof(stack[0]));\n        if (stack == NULL) {\n            _PyErr_NoMemory(tstate);\n            return NULL;\n        }\n    }\n\n    Py_ssize_t nargs = 0;\n    for (Py_ssize_t i=0; i < niters; i++) {\n        PyObject *it = PyTuple_GET_ITEM(lz->iters, i);\n        PyObject *val = Py_TYPE(it)->tp_iternext(it);\n        if (val == NULL) {\n            goto exit;\n        }\n        stack[i] = val;\n        nargs++;\n    }\n\n    result = _PyObject_VectorcallTstate(tstate, lz->func, stack, nargs, NULL);\n\nexit:\n    for (Py_ssize_t i=0; i < nargs; i++) {\n        Py_DECREF(stack[i]);\n    }\n    if (stack != small_stack) {\n        PyMem_Free(stack);\n    }\n    return result;\n}\n\nstatic PyObject *\nmap_reduce(mapobject *lz, PyObject *Py_UNUSED(ignored))\n{\n    Py_ssize_t numargs = PyTuple_GET_SIZE(lz->iters);\n    PyObject *args = PyTuple_New(numargs+1);\n    Py_ssize_t i;\n    if (args == NULL)\n        return NULL;\n    PyTuple_SET_ITEM(args, 0, Py_NewRef(lz->func));\n    for (i = 0; i<numargs; i++){\n        PyObject *it = PyTuple_GET_ITEM(lz->iters, i);\n        PyTuple_SET_ITEM(args, i+1, Py_NewRef(it));\n    }\n\n    return Py_BuildValue(\"ON\", Py_TYPE(lz), args);\n}\n\nstatic PyMethodDef map_methods[] = {\n    {\"__reduce__\", _PyCFunction_CAST(map_reduce), METH_NOARGS, reduce_doc},\n    {NULL,           NULL}           /* sentinel */\n};\n\n\nPyDoc_STRVAR(map_doc,\n\"map(func, *iterables) --> map object\\n\\\n\\n\\\nMake an iterator that computes the function using arguments from\\n\\\neach of the iterables.  Stops when the shortest iterable is exhausted.\");\n\nPyTypeObject PyMap_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"map\",                              /* tp_name */\n    sizeof(mapobject),                  /* tp_basicsize */\n    0,                                  /* tp_itemsize */\n    /* methods */\n    (destructor)map_dealloc,            /* tp_dealloc */\n    0,                                  /* tp_vectorcall_offset */\n    0,                                  /* tp_getattr */\n    0,                                  /* tp_setattr */\n    0,                                  /* tp_as_async */\n    0,                                  /* tp_repr */\n    0,                                  /* tp_as_number */\n    0,                                  /* tp_as_sequence */\n    0,                                  /* tp_as_mapping */\n    0,                                  /* tp_hash */\n    0,                                  /* tp_call */\n    0,                                  /* tp_str */\n    PyObject_GenericGetAttr,            /* tp_getattro */\n    0,                                  /* tp_setattro */\n    0,                                  /* tp_as_buffer */\n    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\n        Py_TPFLAGS_BASETYPE,            /* tp_flags */\n    map_doc,                            /* tp_doc */\n    (traverseproc)map_traverse,         /* tp_traverse */\n    0,                                  /* tp_clear */\n    0,                                  /* tp_richcompare */\n    0,                                  /* tp_weaklistoffset */\n    PyObject_SelfIter,                  /* tp_iter */\n    (iternextfunc)map_next,     /* tp_iternext */\n    map_methods,                        /* tp_methods */\n    0,                                  /* tp_members */\n    0,                                  /* tp_getset */\n    0,                                  /* tp_base */\n    0,                                  /* tp_dict */\n    0,                                  /* tp_descr_get */\n    0,                                  /* tp_descr_set */\n    0,                                  /* tp_dictoffset */\n    0,                                  /* tp_init */\n    PyType_GenericAlloc,                /* tp_alloc */\n    map_new,                            /* tp_new */\n    PyObject_GC_Del,                    /* tp_free */\n    .tp_vectorcall = (vectorcallfunc)map_vectorcall\n};\n\n\n/*[clinic input]\nnext as builtin_next\n\n    iterator: object\n    default: object = NULL\n    /\n\nReturn the next item from the iterator.\n\nIf default is given and the iterator is exhausted,\nit is returned instead of raising StopIteration.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_next_impl(PyObject *module, PyObject *iterator,\n                  PyObject *default_value)\n/*[clinic end generated code: output=a38a94eeb447fef9 input=180f9984f182020f]*/\n{\n    PyObject *res;\n\n    if (!PyIter_Check(iterator)) {\n        PyErr_Format(PyExc_TypeError,\n            \"'%.200s' object is not an iterator\",\n            Py_TYPE(iterator)->tp_name);\n        return NULL;\n    }\n\n    res = (*Py_TYPE(iterator)->tp_iternext)(iterator);\n    if (res != NULL) {\n        return res;\n    } else if (default_value != NULL) {\n        if (PyErr_Occurred()) {\n            if(!PyErr_ExceptionMatches(PyExc_StopIteration))\n                return NULL;\n            PyErr_Clear();\n        }\n        return Py_NewRef(default_value);\n    } else if (PyErr_Occurred()) {\n        return NULL;\n    } else {\n        PyErr_SetNone(PyExc_StopIteration);\n        return NULL;\n    }\n}\n\n\n/*[clinic input]\nsetattr as builtin_setattr\n\n    obj: object\n    name: object\n    value: object\n    /\n\nSets the named attribute on the given object to the specified value.\n\nsetattr(x, 'y', v) is equivalent to ``x.y = v``\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_setattr_impl(PyObject *module, PyObject *obj, PyObject *name,\n                     PyObject *value)\n/*[clinic end generated code: output=dc2ce1d1add9acb4 input=5e26417f2e8598d4]*/\n{\n    if (PyObject_SetAttr(obj, name, value) != 0)\n        return NULL;\n    Py_RETURN_NONE;\n}\n\n\n/*[clinic input]\ndelattr as builtin_delattr\n\n    obj: object\n    name: object\n    /\n\nDeletes the named attribute from the given object.\n\ndelattr(x, 'y') is equivalent to ``del x.y``\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_delattr_impl(PyObject *module, PyObject *obj, PyObject *name)\n/*[clinic end generated code: output=85134bc58dff79fa input=164865623abe7216]*/\n{\n    if (PyObject_SetAttr(obj, name, (PyObject *)NULL) != 0)\n        return NULL;\n    Py_RETURN_NONE;\n}\n\n\n/*[clinic input]\nhash as builtin_hash\n\n    obj: object\n    /\n\nReturn the hash value for the given object.\n\nTwo objects that compare equal must also have the same hash value, but the\nreverse is not necessarily true.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_hash(PyObject *module, PyObject *obj)\n/*[clinic end generated code: output=237668e9d7688db7 input=58c48be822bf9c54]*/\n{\n    Py_hash_t x;\n\n    x = PyObject_Hash(obj);\n    if (x == -1)\n        return NULL;\n    return PyLong_FromSsize_t(x);\n}\n\n\n/*[clinic input]\nhex as builtin_hex\n\n    number: object\n    /\n\nReturn the hexadecimal representation of an integer.\n\n   >>> hex(12648430)\n   '0xc0ffee'\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_hex(PyObject *module, PyObject *number)\n/*[clinic end generated code: output=e46b612169099408 input=e645aff5fc7d540e]*/\n{\n    return PyNumber_ToBase(number, 16);\n}\n\n\n/*[clinic input]\niter as builtin_iter\n\n    object: object\n    sentinel: object = NULL\n    /\n\nGet an iterator from an object.\n\nIn the first form, the argument must supply its own iterator, or be a sequence.\nIn the second form, the callable is called until it returns the sentinel.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_iter_impl(PyObject *module, PyObject *object, PyObject *sentinel)\n/*[clinic end generated code: output=12cf64203c195a94 input=a5d64d9d81880ba6]*/\n{\n    if (sentinel == NULL)\n        return PyObject_GetIter(object);\n    if (!PyCallable_Check(object)) {\n        PyErr_SetString(PyExc_TypeError,\n                        \"iter(object, sentinel): object must be callable\");\n        return NULL;\n    }\n    return PyCallIter_New(object, sentinel);\n}\n\n\n/*[clinic input]\naiter as builtin_aiter\n\n    async_iterable: object\n    /\n\nReturn an AsyncIterator for an AsyncIterable object.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_aiter(PyObject *module, PyObject *async_iterable)\n/*[clinic end generated code: output=1bae108d86f7960e input=473993d0cacc7d23]*/\n{\n    return PyObject_GetAIter(async_iterable);\n}\n\nPyObject *PyAnextAwaitable_New(PyObject *, PyObject *);\n\n/*[clinic input]\nanext as builtin_anext\n\n    aiterator: object\n    default: object = NULL\n    /\n\nasync anext(aiterator[, default])\n\nReturn the next item from the async iterator.  If default is given and the async\niterator is exhausted, it is returned instead of raising StopAsyncIteration.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_anext_impl(PyObject *module, PyObject *aiterator,\n                   PyObject *default_value)\n/*[clinic end generated code: output=f02c060c163a81fa input=8f63f4f78590bb4c]*/\n{\n    PyTypeObject *t;\n    PyObject *awaitable;\n\n    t = Py_TYPE(aiterator);\n    if (t->tp_as_async == NULL || t->tp_as_async->am_anext == NULL) {\n        PyErr_Format(PyExc_TypeError,\n            \"'%.200s' object is not an async iterator\",\n            t->tp_name);\n        return NULL;\n    }\n\n    awaitable = (*t->tp_as_async->am_anext)(aiterator);\n    if (default_value == NULL) {\n        return awaitable;\n    }\n\n    PyObject* new_awaitable = PyAnextAwaitable_New(\n            awaitable, default_value);\n    Py_DECREF(awaitable);\n    return new_awaitable;\n}\n\n\n/*[clinic input]\nlen as builtin_len\n\n    obj: object\n    /\n\nReturn the number of items in a container.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_len(PyObject *module, PyObject *obj)\n/*[clinic end generated code: output=fa7a270d314dfb6c input=bc55598da9e9c9b5]*/\n{\n    Py_ssize_t res;\n\n    res = PyObject_Size(obj);\n    if (res < 0) {\n        assert(PyErr_Occurred());\n        return NULL;\n    }\n    return PyLong_FromSsize_t(res);\n}\n\n\n/*[clinic input]\nlocals as builtin_locals\n\nReturn a dictionary containing the current scope's local variables.\n\nNOTE: Whether or not updates to this dictionary will affect name lookups in\nthe local scope and vice-versa is *implementation dependent* and not\ncovered by any backwards compatibility guarantees.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_locals_impl(PyObject *module)\n/*[clinic end generated code: output=b46c94015ce11448 input=7874018d478d5c4b]*/\n{\n    PyObject *d;\n\n    d = PyEval_GetLocals();\n    return Py_XNewRef(d);\n}\n\n\nstatic PyObject *\nmin_max(PyObject *args, PyObject *kwds, int op)\n{\n    PyObject *v, *it, *item, *val, *maxitem, *maxval, *keyfunc=NULL;\n    PyObject *emptytuple, *defaultval = NULL;\n    static char *kwlist[] = {\"key\", \"default\", NULL};\n    const char *name = op == Py_LT ? \"min\" : \"max\";\n    const int positional = PyTuple_Size(args) > 1;\n    int ret;\n\n    if (positional) {\n        v = args;\n    }\n    else if (!PyArg_UnpackTuple(args, name, 1, 1, &v)) {\n        if (PyExceptionClass_Check(PyExc_TypeError)) {\n            PyErr_Format(PyExc_TypeError, \"%s expected at least 1 argument, got 0\", name);\n        }\n        return NULL;\n    }\n\n    emptytuple = PyTuple_New(0);\n    if (emptytuple == NULL)\n        return NULL;\n    ret = PyArg_ParseTupleAndKeywords(emptytuple, kwds,\n                                      (op == Py_LT) ? \"|$OO:min\" : \"|$OO:max\",\n                                      kwlist, &keyfunc, &defaultval);\n    Py_DECREF(emptytuple);\n    if (!ret)\n        return NULL;\n\n    if (positional && defaultval != NULL) {\n        PyErr_Format(PyExc_TypeError,\n                        \"Cannot specify a default for %s() with multiple \"\n                        \"positional arguments\", name);\n        return NULL;\n    }\n\n    it = PyObject_GetIter(v);\n    if (it == NULL) {\n        return NULL;\n    }\n\n    if (keyfunc == Py_None) {\n        keyfunc = NULL;\n    }\n\n    maxitem = NULL; /* the result */\n    maxval = NULL;  /* the value associated with the result */\n    while (( item = PyIter_Next(it) )) {\n        /* get the value from the key function */\n        if (keyfunc != NULL) {\n            val = PyObject_CallOneArg(keyfunc, item);\n            if (val == NULL)\n                goto Fail_it_item;\n        }\n        /* no key function; the value is the item */\n        else {\n            val = Py_NewRef(item);\n        }\n\n        /* maximum value and item are unset; set them */\n        if (maxval == NULL) {\n            maxitem = item;\n            maxval = val;\n        }\n        /* maximum value and item are set; update them as necessary */\n        else {\n            int cmp = PyObject_RichCompareBool(val, maxval, op);\n            if (cmp < 0)\n                goto Fail_it_item_and_val;\n            else if (cmp > 0) {\n                Py_DECREF(maxval);\n                Py_DECREF(maxitem);\n                maxval = val;\n                maxitem = item;\n            }\n            else {\n                Py_DECREF(item);\n                Py_DECREF(val);\n            }\n        }\n    }\n    if (PyErr_Occurred())\n        goto Fail_it;\n    if (maxval == NULL) {\n        assert(maxitem == NULL);\n        if (defaultval != NULL) {\n            maxitem = Py_NewRef(defaultval);\n        } else {\n            PyErr_Format(PyExc_ValueError,\n                         \"%s() iterable argument is empty\", name);\n        }\n    }\n    else\n        Py_DECREF(maxval);\n    Py_DECREF(it);\n    return maxitem;\n\nFail_it_item_and_val:\n    Py_DECREF(val);\nFail_it_item:\n    Py_DECREF(item);\nFail_it:\n    Py_XDECREF(maxval);\n    Py_XDECREF(maxitem);\n    Py_DECREF(it);\n    return NULL;\n}\n\n/* AC: cannot convert yet, waiting for *args support */\nstatic PyObject *\nbuiltin_min(PyObject *self, PyObject *args, PyObject *kwds)\n{\n    return min_max(args, kwds, Py_LT);\n}\n\nPyDoc_STRVAR(min_doc,\n\"min(iterable, *[, default=obj, key=func]) -> value\\n\\\nmin(arg1, arg2, *args, *[, key=func]) -> value\\n\\\n\\n\\\nWith a single iterable argument, return its smallest item. The\\n\\\ndefault keyword-only argument specifies an object to return if\\n\\\nthe provided iterable is empty.\\n\\\nWith two or more arguments, return the smallest argument.\");\n\n\n/* AC: cannot convert yet, waiting for *args support */\nstatic PyObject *\nbuiltin_max(PyObject *self, PyObject *args, PyObject *kwds)\n{\n    return min_max(args, kwds, Py_GT);\n}\n\nPyDoc_STRVAR(max_doc,\n\"max(iterable, *[, default=obj, key=func]) -> value\\n\\\nmax(arg1, arg2, *args, *[, key=func]) -> value\\n\\\n\\n\\\nWith a single iterable argument, return its biggest item. The\\n\\\ndefault keyword-only argument specifies an object to return if\\n\\\nthe provided iterable is empty.\\n\\\nWith two or more arguments, return the largest argument.\");\n\n\n/*[clinic input]\noct as builtin_oct\n\n    number: object\n    /\n\nReturn the octal representation of an integer.\n\n   >>> oct(342391)\n   '0o1234567'\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_oct(PyObject *module, PyObject *number)\n/*[clinic end generated code: output=40a34656b6875352 input=ad6b274af4016c72]*/\n{\n    return PyNumber_ToBase(number, 8);\n}\n\n\n/*[clinic input]\nord as builtin_ord\n\n    c: object\n    /\n\nReturn the Unicode code point for a one-character string.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_ord(PyObject *module, PyObject *c)\n/*[clinic end generated code: output=4fa5e87a323bae71 input=3064e5d6203ad012]*/\n{\n    long ord;\n    Py_ssize_t size;\n\n    if (PyBytes_Check(c)) {\n        size = PyBytes_GET_SIZE(c);\n        if (size == 1) {\n            ord = (long)((unsigned char)*PyBytes_AS_STRING(c));\n            return PyLong_FromLong(ord);\n        }\n    }\n    else if (PyUnicode_Check(c)) {\n        size = PyUnicode_GET_LENGTH(c);\n        if (size == 1) {\n            ord = (long)PyUnicode_READ_CHAR(c, 0);\n            return PyLong_FromLong(ord);\n        }\n    }\n    else if (PyByteArray_Check(c)) {\n        /* XXX Hopefully this is temporary */\n        size = PyByteArray_GET_SIZE(c);\n        if (size == 1) {\n            ord = (long)((unsigned char)*PyByteArray_AS_STRING(c));\n            return PyLong_FromLong(ord);\n        }\n    }\n    else {\n        PyErr_Format(PyExc_TypeError,\n                     \"ord() expected string of length 1, but \" \\\n                     \"%.200s found\", Py_TYPE(c)->tp_name);\n        return NULL;\n    }\n\n    PyErr_Format(PyExc_TypeError,\n                 \"ord() expected a character, \"\n                 \"but string of length %zd found\",\n                 size);\n    return NULL;\n}\n\n\n/*[clinic input]\npow as builtin_pow\n\n    base: object\n    exp: object\n    mod: object = None\n\nEquivalent to base**exp with 2 arguments or base**exp % mod with 3 arguments\n\nSome types, such as ints, are able to use a more efficient algorithm when\ninvoked using the three argument form.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_pow_impl(PyObject *module, PyObject *base, PyObject *exp,\n                 PyObject *mod)\n/*[clinic end generated code: output=3ca1538221bbf15f input=435dbd48a12efb23]*/\n{\n    return PyNumber_Power(base, exp, mod);\n}\n\n/*[clinic input]\nprint as builtin_print\n\n    *args: object\n    sep: object(c_default=\"Py_None\") = ' '\n        string inserted between values, default a space.\n    end: object(c_default=\"Py_None\") = '\\n'\n        string appended after the last value, default a newline.\n    file: object = None\n        a file-like object (stream); defaults to the current sys.stdout.\n    flush: bool = False\n        whether to forcibly flush the stream.\n\nPrints the values to a stream, or to sys.stdout by default.\n\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_print_impl(PyObject *module, PyObject *args, PyObject *sep,\n                   PyObject *end, PyObject *file, int flush)\n/*[clinic end generated code: output=3cfc0940f5bc237b input=c143c575d24fe665]*/\n{\n    int i, err;\n\n    if (file == Py_None) {\n        PyThreadState *tstate = _PyThreadState_GET();\n        file = _PySys_GetAttr(tstate, &_Py_ID(stdout));\n        if (file == NULL) {\n            PyErr_SetString(PyExc_RuntimeError, \"lost sys.stdout\");\n            return NULL;\n        }\n\n        /* sys.stdout may be None when FILE* stdout isn't connected */\n        if (file == Py_None) {\n            Py_RETURN_NONE;\n        }\n    }\n\n    if (sep == Py_None) {\n        sep = NULL;\n    }\n    else if (sep && !PyUnicode_Check(sep)) {\n        PyErr_Format(PyExc_TypeError,\n                     \"sep must be None or a string, not %.200s\",\n                     Py_TYPE(sep)->tp_name);\n        return NULL;\n    }\n    if (end == Py_None) {\n        end = NULL;\n    }\n    else if (end && !PyUnicode_Check(end)) {\n        PyErr_Format(PyExc_TypeError,\n                     \"end must be None or a string, not %.200s\",\n                     Py_TYPE(end)->tp_name);\n        return NULL;\n    }\n\n    for (i = 0; i < PyTuple_GET_SIZE(args); i++) {\n        if (i > 0) {\n            if (sep == NULL) {\n                err = PyFile_WriteString(\" \", file);\n            }\n            else {\n                err = PyFile_WriteObject(sep, file, Py_PRINT_RAW);\n            }\n            if (err) {\n                return NULL;\n            }\n        }\n        err = PyFile_WriteObject(PyTuple_GET_ITEM(args, i), file, Py_PRINT_RAW);\n        if (err) {\n            return NULL;\n        }\n    }\n\n    if (end == NULL) {\n        err = PyFile_WriteString(\"\\n\", file);\n    }\n    else {\n        err = PyFile_WriteObject(end, file, Py_PRINT_RAW);\n    }\n    if (err) {\n        return NULL;\n    }\n\n    if (flush) {\n        PyObject *tmp = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));\n        if (tmp == NULL) {\n            return NULL;\n        }\n        Py_DECREF(tmp);\n    }\n\n    Py_RETURN_NONE;\n}\n\n\n/*[clinic input]\ninput as builtin_input\n\n    prompt: object(c_default=\"NULL\") = \"\"\n    /\n\nRead a string from standard input.  The trailing newline is stripped.\n\nThe prompt string, if given, is printed to standard output without a\ntrailing newline before reading input.\n\nIf the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.\nOn *nix systems, readline is used if available.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_input_impl(PyObject *module, PyObject *prompt)\n/*[clinic end generated code: output=83db5a191e7a0d60 input=159c46d4ae40977e]*/\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *fin = _PySys_GetAttr(\n        tstate, &_Py_ID(stdin));\n    PyObject *fout = _PySys_GetAttr(\n        tstate, &_Py_ID(stdout));\n    PyObject *ferr = _PySys_GetAttr(\n        tstate, &_Py_ID(stderr));\n    PyObject *tmp;\n    long fd;\n    int tty;\n\n    /* Check that stdin/out/err are intact */\n    if (fin == NULL || fin == Py_None) {\n        PyErr_SetString(PyExc_RuntimeError,\n                        \"input(): lost sys.stdin\");\n        return NULL;\n    }\n    if (fout == NULL || fout == Py_None) {\n        PyErr_SetString(PyExc_RuntimeError,\n                        \"input(): lost sys.stdout\");\n        return NULL;\n    }\n    if (ferr == NULL || ferr == Py_None) {\n        PyErr_SetString(PyExc_RuntimeError,\n                        \"input(): lost sys.stderr\");\n        return NULL;\n    }\n\n    if (PySys_Audit(\"builtins.input\", \"O\", prompt ? prompt : Py_None) < 0) {\n        return NULL;\n    }\n\n    /* First of all, flush stderr */\n    tmp = PyObject_CallMethodNoArgs(ferr, &_Py_ID(flush));\n    if (tmp == NULL)\n        PyErr_Clear();\n    else\n        Py_DECREF(tmp);\n\n    /* We should only use (GNU) readline if Python's sys.stdin and\n       sys.stdout are the same as C's stdin and stdout, because we\n       need to pass it those. */\n    tmp = PyObject_CallMethodNoArgs(fin, &_Py_ID(fileno));\n    if (tmp == NULL) {\n        PyErr_Clear();\n        tty = 0;\n    }\n    else {\n        fd = PyLong_AsLong(tmp);\n        Py_DECREF(tmp);\n        if (fd < 0 && PyErr_Occurred())\n            return NULL;\n        tty = fd == fileno(stdin) && isatty(fd);\n    }\n    if (tty) {\n        tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(fileno));\n        if (tmp == NULL) {\n            PyErr_Clear();\n            tty = 0;\n        }\n        else {\n            fd = PyLong_AsLong(tmp);\n            Py_DECREF(tmp);\n            if (fd < 0 && PyErr_Occurred())\n                return NULL;\n            tty = fd == fileno(stdout) && isatty(fd);\n        }\n    }\n\n    /* If we're interactive, use (GNU) readline */\n    if (tty) {\n        PyObject *po = NULL;\n        const char *promptstr;\n        char *s = NULL;\n        PyObject *stdin_encoding = NULL, *stdin_errors = NULL;\n        PyObject *stdout_encoding = NULL, *stdout_errors = NULL;\n        const char *stdin_encoding_str, *stdin_errors_str;\n        PyObject *result;\n        size_t len;\n\n        /* stdin is a text stream, so it must have an encoding. */\n        stdin_encoding = PyObject_GetAttr(fin, &_Py_ID(encoding));\n        stdin_errors = PyObject_GetAttr(fin, &_Py_ID(errors));\n        if (!stdin_encoding || !stdin_errors ||\n                !PyUnicode_Check(stdin_encoding) ||\n                !PyUnicode_Check(stdin_errors)) {\n            tty = 0;\n            goto _readline_errors;\n        }\n        stdin_encoding_str = PyUnicode_AsUTF8(stdin_encoding);\n        stdin_errors_str = PyUnicode_AsUTF8(stdin_errors);\n        if (!stdin_encoding_str || !stdin_errors_str)\n            goto _readline_errors;\n        tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(flush));\n        if (tmp == NULL)\n            PyErr_Clear();\n        else\n            Py_DECREF(tmp);\n        if (prompt != NULL) {\n            /* We have a prompt, encode it as stdout would */\n            const char *stdout_encoding_str, *stdout_errors_str;\n            PyObject *stringpo;\n            stdout_encoding = PyObject_GetAttr(fout, &_Py_ID(encoding));\n            stdout_errors = PyObject_GetAttr(fout, &_Py_ID(errors));\n            if (!stdout_encoding || !stdout_errors ||\n                    !PyUnicode_Check(stdout_encoding) ||\n                    !PyUnicode_Check(stdout_errors)) {\n                tty = 0;\n                goto _readline_errors;\n            }\n            stdout_encoding_str = PyUnicode_AsUTF8(stdout_encoding);\n            stdout_errors_str = PyUnicode_AsUTF8(stdout_errors);\n            if (!stdout_encoding_str || !stdout_errors_str)\n                goto _readline_errors;\n            stringpo = PyObject_Str(prompt);\n            if (stringpo == NULL)\n                goto _readline_errors;\n            po = PyUnicode_AsEncodedString(stringpo,\n                stdout_encoding_str, stdout_errors_str);\n            Py_CLEAR(stdout_encoding);\n            Py_CLEAR(stdout_errors);\n            Py_CLEAR(stringpo);\n            if (po == NULL)\n                goto _readline_errors;\n            assert(PyBytes_Check(po));\n            promptstr = PyBytes_AS_STRING(po);\n        }\n        else {\n            po = NULL;\n            promptstr = \"\";\n        }\n        s = PyOS_Readline(stdin, stdout, promptstr);\n        if (s == NULL) {\n            PyErr_CheckSignals();\n            if (!PyErr_Occurred())\n                PyErr_SetNone(PyExc_KeyboardInterrupt);\n            goto _readline_errors;\n        }\n\n        len = strlen(s);\n        if (len == 0) {\n            PyErr_SetNone(PyExc_EOFError);\n            result = NULL;\n        }\n        else {\n            if (len > PY_SSIZE_T_MAX) {\n                PyErr_SetString(PyExc_OverflowError,\n                                \"input: input too long\");\n                result = NULL;\n            }\n            else {\n                len--;   /* strip trailing '\\n' */\n                if (len != 0 && s[len-1] == '\\r')\n                    len--;   /* strip trailing '\\r' */\n                result = PyUnicode_Decode(s, len, stdin_encoding_str,\n                                                  stdin_errors_str);\n            }\n        }\n        Py_DECREF(stdin_encoding);\n        Py_DECREF(stdin_errors);\n        Py_XDECREF(po);\n        PyMem_Free(s);\n\n        if (result != NULL) {\n            if (PySys_Audit(\"builtins.input/result\", \"O\", result) < 0) {\n                return NULL;\n            }\n        }\n\n        return result;\n\n    _readline_errors:\n        Py_XDECREF(stdin_encoding);\n        Py_XDECREF(stdout_encoding);\n        Py_XDECREF(stdin_errors);\n        Py_XDECREF(stdout_errors);\n        Py_XDECREF(po);\n        if (tty)\n            return NULL;\n\n        PyErr_Clear();\n    }\n\n    /* Fallback if we're not interactive */\n    if (prompt != NULL) {\n        if (PyFile_WriteObject(prompt, fout, Py_PRINT_RAW) != 0)\n            return NULL;\n    }\n    tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(flush));\n    if (tmp == NULL)\n        PyErr_Clear();\n    else\n        Py_DECREF(tmp);\n    return PyFile_GetLine(fin, -1);\n}\n\n\n/*[clinic input]\nrepr as builtin_repr\n\n    obj: object\n    /\n\nReturn the canonical string representation of the object.\n\nFor many object types, including most builtins, eval(repr(obj)) == obj.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_repr(PyObject *module, PyObject *obj)\n/*[clinic end generated code: output=7ed3778c44fd0194 input=1c9e6d66d3e3be04]*/\n{\n    return PyObject_Repr(obj);\n}\n\n\n/*[clinic input]\nround as builtin_round\n\n    number: object\n    ndigits: object = None\n\nRound a number to a given precision in decimal digits.\n\nThe return value is an integer if ndigits is omitted or None.  Otherwise\nthe return value has the same type as the number.  ndigits may be negative.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_round_impl(PyObject *module, PyObject *number, PyObject *ndigits)\n/*[clinic end generated code: output=ff0d9dd176c02ede input=275678471d7aca15]*/\n{\n    PyObject *round, *result;\n\n    if (!_PyType_IsReady(Py_TYPE(number))) {\n        if (PyType_Ready(Py_TYPE(number)) < 0)\n            return NULL;\n    }\n\n    round = _PyObject_LookupSpecial(number, &_Py_ID(__round__));\n    if (round == NULL) {\n        if (!PyErr_Occurred())\n            PyErr_Format(PyExc_TypeError,\n                         \"type %.100s doesn't define __round__ method\",\n                         Py_TYPE(number)->tp_name);\n        return NULL;\n    }\n\n    if (ndigits == Py_None)\n        result = _PyObject_CallNoArgs(round);\n    else\n        result = PyObject_CallOneArg(round, ndigits);\n    Py_DECREF(round);\n    return result;\n}\n\n\n/*AC: we need to keep the kwds dict intact to easily call into the\n * list.sort method, which isn't currently supported in AC. So we just use\n * the initially generated signature with a custom implementation.\n */\n/* [disabled clinic input]\nsorted as builtin_sorted\n\n    iterable as seq: object\n    key as keyfunc: object = None\n    reverse: object = False\n\nReturn a new list containing all items from the iterable in ascending order.\n\nA custom key function can be supplied to customize the sort order, and the\nreverse flag can be set to request the result in descending order.\n[end disabled clinic input]*/\n\nPyDoc_STRVAR(builtin_sorted__doc__,\n\"sorted($module, iterable, /, *, key=None, reverse=False)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return a new list containing all items from the iterable in ascending order.\\n\"\n\"\\n\"\n\"A custom key function can be supplied to customize the sort order, and the\\n\"\n\"reverse flag can be set to request the result in descending order.\");\n\n#define BUILTIN_SORTED_METHODDEF    \\\n    {\"sorted\", _PyCFunction_CAST(builtin_sorted), METH_FASTCALL | METH_KEYWORDS, builtin_sorted__doc__},\n\nstatic PyObject *\nbuiltin_sorted(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *newlist, *v, *seq, *callable;\n\n    /* Keyword arguments are passed through list.sort() which will check\n       them. */\n    if (!_PyArg_UnpackStack(args, nargs, \"sorted\", 1, 1, &seq))\n        return NULL;\n\n    newlist = PySequence_List(seq);\n    if (newlist == NULL)\n        return NULL;\n\n    callable = PyObject_GetAttr(newlist, &_Py_ID(sort));\n    if (callable == NULL) {\n        Py_DECREF(newlist);\n        return NULL;\n    }\n\n    assert(nargs >= 1);\n    v = PyObject_Vectorcall(callable, args + 1, nargs - 1, kwnames);\n    Py_DECREF(callable);\n    if (v == NULL) {\n        Py_DECREF(newlist);\n        return NULL;\n    }\n    Py_DECREF(v);\n    return newlist;\n}\n\n\n/*[clinic input]\nvars as builtin_vars\n\n    object: object = NULL\n    /\n\nShow vars.\n\nWithout arguments, equivalent to locals().\nWith an argument, equivalent to object.__dict__.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_vars_impl(PyObject *module, PyObject *object)\n/*[clinic end generated code: output=840a7f64007a3e0a input=80cbdef9182c4ba3]*/\n{\n    PyObject *d;\n\n    if (object == NULL) {\n        d = Py_XNewRef(PyEval_GetLocals());\n    }\n    else {\n        if (_PyObject_LookupAttr(object, &_Py_ID(__dict__), &d) == 0) {\n            PyErr_SetString(PyExc_TypeError,\n                \"vars() argument must have __dict__ attribute\");\n        }\n    }\n    return d;\n}\n\n\n/*[clinic input]\nsum as builtin_sum\n\n    iterable: object\n    /\n    start: object(c_default=\"NULL\") = 0\n\nReturn the sum of a 'start' value (default: 0) plus an iterable of numbers\n\nWhen the iterable is empty, return the start value.\nThis function is intended specifically for use with numeric values and may\nreject non-numeric types.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start)\n/*[clinic end generated code: output=df758cec7d1d302f input=162b50765250d222]*/\n{\n    PyObject *result = start;\n    PyObject *temp, *item, *iter;\n\n    iter = PyObject_GetIter(iterable);\n    if (iter == NULL)\n        return NULL;\n\n    if (result == NULL) {\n        result = PyLong_FromLong(0);\n        if (result == NULL) {\n            Py_DECREF(iter);\n            return NULL;\n        }\n    } else {\n        /* reject string values for 'start' parameter */\n        if (PyUnicode_Check(result)) {\n            PyErr_SetString(PyExc_TypeError,\n                \"sum() can't sum strings [use ''.join(seq) instead]\");\n            Py_DECREF(iter);\n            return NULL;\n        }\n        if (PyBytes_Check(result)) {\n            PyErr_SetString(PyExc_TypeError,\n                \"sum() can't sum bytes [use b''.join(seq) instead]\");\n            Py_DECREF(iter);\n            return NULL;\n        }\n        if (PyByteArray_Check(result)) {\n            PyErr_SetString(PyExc_TypeError,\n                \"sum() can't sum bytearray [use b''.join(seq) instead]\");\n            Py_DECREF(iter);\n            return NULL;\n        }\n        Py_INCREF(result);\n    }\n\n#ifndef SLOW_SUM\n    /* Fast addition by keeping temporary sums in C instead of new Python objects.\n       Assumes all inputs are the same type.  If the assumption fails, default\n       to the more general routine.\n    */\n    if (PyLong_CheckExact(result)) {\n        int overflow;\n        Py_ssize_t i_result = PyLong_AsLongAndOverflow(result, &overflow);\n        /* If this already overflowed, don't even enter the loop. */\n        if (overflow == 0) {\n            Py_SETREF(result, NULL);\n        }\n        while(result == NULL) {\n            item = PyIter_Next(iter);\n            if (item == NULL) {\n                Py_DECREF(iter);\n                if (PyErr_Occurred())\n                    return NULL;\n                return PyLong_FromSsize_t(i_result);\n            }\n            if (PyLong_CheckExact(item) || PyBool_Check(item)) {\n                Py_ssize_t b;\n                overflow = 0;\n                /* Single digits are common, fast, and cannot overflow on unpacking. */\n                if (_PyLong_IsCompact((PyLongObject *)item)) {\n                    b = _PyLong_CompactValue((PyLongObject *)item);\n                }\n                else {\n                    b = PyLong_AsLongAndOverflow(item, &overflow);\n                }\n                if (overflow == 0 &&\n                    (i_result >= 0 ? (b <= LONG_MAX - i_result)\n                                   : (b >= LONG_MIN - i_result)))\n                {\n                    i_result += b;\n                    Py_DECREF(item);\n                    continue;\n                }\n            }\n            /* Either overflowed or is not an int. Restore real objects and process normally */\n            result = PyLong_FromSsize_t(i_result);\n            if (result == NULL) {\n                Py_DECREF(item);\n                Py_DECREF(iter);\n                return NULL;\n            }\n            temp = PyNumber_Add(result, item);\n            Py_DECREF(result);\n            Py_DECREF(item);\n            result = temp;\n            if (result == NULL) {\n                Py_DECREF(iter);\n                return NULL;\n            }\n        }\n    }\n\n    if (PyFloat_CheckExact(result)) {\n        double f_result = PyFloat_AS_DOUBLE(result);\n        double c = 0.0;\n        Py_SETREF(result, NULL);\n        while(result == NULL) {\n            item = PyIter_Next(iter);\n            if (item == NULL) {\n                Py_DECREF(iter);\n                if (PyErr_Occurred())\n                    return NULL;\n                /* Avoid losing the sign on a negative result,\n                   and don't let adding the compensation convert\n                   an infinite or overflowed sum to a NaN. */\n                if (c && Py_IS_FINITE(c)) {\n                    f_result += c;\n                }\n                return PyFloat_FromDouble(f_result);\n            }\n            if (PyFloat_CheckExact(item)) {\n                // Improved Kahan–Babuška algorithm by Arnold Neumaier\n                // https://www.mat.univie.ac.at/~neum/scan/01.pdf\n                double x = PyFloat_AS_DOUBLE(item);\n                double t = f_result + x;\n                if (fabs(f_result) >= fabs(x)) {\n                    c += (f_result - t) + x;\n                } else {\n                    c += (x - t) + f_result;\n                }\n                f_result = t;\n                _Py_DECREF_SPECIALIZED(item, _PyFloat_ExactDealloc);\n                continue;\n            }\n            if (PyLong_Check(item)) {\n                long value;\n                int overflow;\n                value = PyLong_AsLongAndOverflow(item, &overflow);\n                if (!overflow) {\n                    f_result += (double)value;\n                    Py_DECREF(item);\n                    continue;\n                }\n            }\n            if (c && Py_IS_FINITE(c)) {\n                f_result += c;\n            }\n            result = PyFloat_FromDouble(f_result);\n            if (result == NULL) {\n                Py_DECREF(item);\n                Py_DECREF(iter);\n                return NULL;\n            }\n            temp = PyNumber_Add(result, item);\n            Py_DECREF(result);\n            Py_DECREF(item);\n            result = temp;\n            if (result == NULL) {\n                Py_DECREF(iter);\n                return NULL;\n            }\n        }\n    }\n#endif\n\n    for(;;) {\n        item = PyIter_Next(iter);\n        if (item == NULL) {\n            /* error, or end-of-sequence */\n            if (PyErr_Occurred()) {\n                Py_SETREF(result, NULL);\n            }\n            break;\n        }\n        /* It's tempting to use PyNumber_InPlaceAdd instead of\n           PyNumber_Add here, to avoid quadratic running time\n           when doing 'sum(list_of_lists, [])'.  However, this\n           would produce a change in behaviour: a snippet like\n\n             empty = []\n             sum([[x] for x in range(10)], empty)\n\n           would change the value of empty. In fact, using\n           in-place addition rather that binary addition for\n           any of the steps introduces subtle behavior changes:\n\n           https://bugs.python.org/issue18305 */\n        temp = PyNumber_Add(result, item);\n        Py_DECREF(result);\n        Py_DECREF(item);\n        result = temp;\n        if (result == NULL)\n            break;\n    }\n    Py_DECREF(iter);\n    return result;\n}\n\n\n/*[clinic input]\nisinstance as builtin_isinstance\n\n    obj: object\n    class_or_tuple: object\n    /\n\nReturn whether an object is an instance of a class or of a subclass thereof.\n\nA tuple, as in ``isinstance(x, (A, B, ...))``, may be given as the target to\ncheck against. This is equivalent to ``isinstance(x, A) or isinstance(x, B)\nor ...`` etc.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_isinstance_impl(PyObject *module, PyObject *obj,\n                        PyObject *class_or_tuple)\n/*[clinic end generated code: output=6faf01472c13b003 input=ffa743db1daf7549]*/\n{\n    int retval;\n\n    retval = PyObject_IsInstance(obj, class_or_tuple);\n    if (retval < 0)\n        return NULL;\n    return PyBool_FromLong(retval);\n}\n\n\n/*[clinic input]\nissubclass as builtin_issubclass\n\n    cls: object\n    class_or_tuple: object\n    /\n\nReturn whether 'cls' is derived from another class or is the same class.\n\nA tuple, as in ``issubclass(x, (A, B, ...))``, may be given as the target to\ncheck against. This is equivalent to ``issubclass(x, A) or issubclass(x, B)\nor ...``.\n[clinic start generated code]*/\n\nstatic PyObject *\nbuiltin_issubclass_impl(PyObject *module, PyObject *cls,\n                        PyObject *class_or_tuple)\n/*[clinic end generated code: output=358412410cd7a250 input=a24b9f3d58c370d6]*/\n{\n    int retval;\n\n    retval = PyObject_IsSubclass(cls, class_or_tuple);\n    if (retval < 0)\n        return NULL;\n    return PyBool_FromLong(retval);\n}\n\ntypedef struct {\n    PyObject_HEAD\n    Py_ssize_t tuplesize;\n    PyObject *ittuple;     /* tuple of iterators */\n    PyObject *result;\n    int strict;\n} zipobject;\n\nstatic PyObject *\nzip_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n{\n    zipobject *lz;\n    Py_ssize_t i;\n    PyObject *ittuple;  /* tuple of iterators */\n    PyObject *result;\n    Py_ssize_t tuplesize;\n    int strict = 0;\n\n    if (kwds) {\n        PyObject *empty = PyTuple_New(0);\n        if (empty == NULL) {\n            return NULL;\n        }\n        static char *kwlist[] = {\"strict\", NULL};\n        int parsed = PyArg_ParseTupleAndKeywords(\n                empty, kwds, \"|$p:zip\", kwlist, &strict);\n        Py_DECREF(empty);\n        if (!parsed) {\n            return NULL;\n        }\n    }\n\n    /* args must be a tuple */\n    assert(PyTuple_Check(args));\n    tuplesize = PyTuple_GET_SIZE(args);\n\n    /* obtain iterators */\n    ittuple = PyTuple_New(tuplesize);\n    if (ittuple == NULL)\n        return NULL;\n    for (i=0; i < tuplesize; ++i) {\n        PyObject *item = PyTuple_GET_ITEM(args, i);\n        PyObject *it = PyObject_GetIter(item);\n        if (it == NULL) {\n            Py_DECREF(ittuple);\n            return NULL;\n        }\n        PyTuple_SET_ITEM(ittuple, i, it);\n    }\n\n    /* create a result holder */\n    result = PyTuple_New(tuplesize);\n    if (result == NULL) {\n        Py_DECREF(ittuple);\n        return NULL;\n    }\n    for (i=0 ; i < tuplesize ; i++) {\n        PyTuple_SET_ITEM(result, i, Py_NewRef(Py_None));\n    }\n\n    /* create zipobject structure */\n    lz = (zipobject *)type->tp_alloc(type, 0);\n    if (lz == NULL) {\n        Py_DECREF(ittuple);\n        Py_DECREF(result);\n        return NULL;\n    }\n    lz->ittuple = ittuple;\n    lz->tuplesize = tuplesize;\n    lz->result = result;\n    lz->strict = strict;\n\n    return (PyObject *)lz;\n}\n\nstatic void\nzip_dealloc(zipobject *lz)\n{\n    PyObject_GC_UnTrack(lz);\n    Py_XDECREF(lz->ittuple);\n    Py_XDECREF(lz->result);\n    Py_TYPE(lz)->tp_free(lz);\n}\n\nstatic int\nzip_traverse(zipobject *lz, visitproc visit, void *arg)\n{\n    Py_VISIT(lz->ittuple);\n    Py_VISIT(lz->result);\n    return 0;\n}\n\nstatic PyObject *\nzip_next(zipobject *lz)\n{\n    Py_ssize_t i;\n    Py_ssize_t tuplesize = lz->tuplesize;\n    PyObject *result = lz->result;\n    PyObject *it;\n    PyObject *item;\n    PyObject *olditem;\n\n    if (tuplesize == 0)\n        return NULL;\n    if (Py_REFCNT(result) == 1) {\n        Py_INCREF(result);\n        for (i=0 ; i < tuplesize ; i++) {\n            it = PyTuple_GET_ITEM(lz->ittuple, i);\n            item = (*Py_TYPE(it)->tp_iternext)(it);\n            if (item == NULL) {\n                Py_DECREF(result);\n                if (lz->strict) {\n                    goto check;\n                }\n                return NULL;\n            }\n            olditem = PyTuple_GET_ITEM(result, i);\n            PyTuple_SET_ITEM(result, i, item);\n            Py_DECREF(olditem);\n        }\n        // bpo-42536: The GC may have untracked this result tuple. Since we're\n        // recycling it, make sure it's tracked again:\n        if (!_PyObject_GC_IS_TRACKED(result)) {\n            _PyObject_GC_TRACK(result);\n        }\n    } else {\n        result = PyTuple_New(tuplesize);\n        if (result == NULL)\n            return NULL;\n        for (i=0 ; i < tuplesize ; i++) {\n            it = PyTuple_GET_ITEM(lz->ittuple, i);\n            item = (*Py_TYPE(it)->tp_iternext)(it);\n            if (item == NULL) {\n                Py_DECREF(result);\n                if (lz->strict) {\n                    goto check;\n                }\n                return NULL;\n            }\n            PyTuple_SET_ITEM(result, i, item);\n        }\n    }\n    return result;\ncheck:\n    if (PyErr_Occurred()) {\n        if (!PyErr_ExceptionMatches(PyExc_StopIteration)) {\n            // next() on argument i raised an exception (not StopIteration)\n            return NULL;\n        }\n        PyErr_Clear();\n    }\n    if (i) {\n        // ValueError: zip() argument 2 is shorter than argument 1\n        // ValueError: zip() argument 3 is shorter than arguments 1-2\n        const char* plural = i == 1 ? \" \" : \"s 1-\";\n        return PyErr_Format(PyExc_ValueError,\n                            \"zip() argument %d is shorter than argument%s%d\",\n                            i + 1, plural, i);\n    }\n    for (i = 1; i < tuplesize; i++) {\n        it = PyTuple_GET_ITEM(lz->ittuple, i);\n        item = (*Py_TYPE(it)->tp_iternext)(it);\n        if (item) {\n            Py_DECREF(item);\n            const char* plural = i == 1 ? \" \" : \"s 1-\";\n            return PyErr_Format(PyExc_ValueError,\n                                \"zip() argument %d is longer than argument%s%d\",\n                                i + 1, plural, i);\n        }\n        if (PyErr_Occurred()) {\n            if (!PyErr_ExceptionMatches(PyExc_StopIteration)) {\n                // next() on argument i raised an exception (not StopIteration)\n                return NULL;\n            }\n            PyErr_Clear();\n        }\n        // Argument i is exhausted. So far so good...\n    }\n    // All arguments are exhausted. Success!\n    return NULL;\n}\n\nstatic PyObject *\nzip_reduce(zipobject *lz, PyObject *Py_UNUSED(ignored))\n{\n    /* Just recreate the zip with the internal iterator tuple */\n    if (lz->strict) {\n        return PyTuple_Pack(3, Py_TYPE(lz), lz->ittuple, Py_True);\n    }\n    return PyTuple_Pack(2, Py_TYPE(lz), lz->ittuple);\n}\n\nPyDoc_STRVAR(setstate_doc, \"Set state information for unpickling.\");\n\nstatic PyObject *\nzip_setstate(zipobject *lz, PyObject *state)\n{\n    int strict = PyObject_IsTrue(state);\n    if (strict < 0) {\n        return NULL;\n    }\n    lz->strict = strict;\n    Py_RETURN_NONE;\n}\n\nstatic PyMethodDef zip_methods[] = {\n    {\"__reduce__\", _PyCFunction_CAST(zip_reduce), METH_NOARGS, reduce_doc},\n    {\"__setstate__\", _PyCFunction_CAST(zip_setstate), METH_O, setstate_doc},\n    {NULL}  /* sentinel */\n};\n\nPyDoc_STRVAR(zip_doc,\n\"zip(*iterables, strict=False) --> Yield tuples until an input is exhausted.\\n\\\n\\n\\\n   >>> list(zip('abcdefg', range(3), range(4)))\\n\\\n   [('a', 0, 0), ('b', 1, 1), ('c', 2, 2)]\\n\\\n\\n\\\nThe zip object yields n-length tuples, where n is the number of iterables\\n\\\npassed as positional arguments to zip().  The i-th element in every tuple\\n\\\ncomes from the i-th iterable argument to zip().  This continues until the\\n\\\nshortest argument is exhausted.\\n\\\n\\n\\\nIf strict is true and one of the arguments is exhausted before the others,\\n\\\nraise a ValueError.\");\n\nPyTypeObject PyZip_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"zip\",                              /* tp_name */\n    sizeof(zipobject),                  /* tp_basicsize */\n    0,                                  /* tp_itemsize */\n    /* methods */\n    (destructor)zip_dealloc,            /* tp_dealloc */\n    0,                                  /* tp_vectorcall_offset */\n    0,                                  /* tp_getattr */\n    0,                                  /* tp_setattr */\n    0,                                  /* tp_as_async */\n    0,                                  /* tp_repr */\n    0,                                  /* tp_as_number */\n    0,                                  /* tp_as_sequence */\n    0,                                  /* tp_as_mapping */\n    0,                                  /* tp_hash */\n    0,                                  /* tp_call */\n    0,                                  /* tp_str */\n    PyObject_GenericGetAttr,            /* tp_getattro */\n    0,                                  /* tp_setattro */\n    0,                                  /* tp_as_buffer */\n    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\n        Py_TPFLAGS_BASETYPE,            /* tp_flags */\n    zip_doc,                            /* tp_doc */\n    (traverseproc)zip_traverse,    /* tp_traverse */\n    0,                                  /* tp_clear */\n    0,                                  /* tp_richcompare */\n    0,                                  /* tp_weaklistoffset */\n    PyObject_SelfIter,                  /* tp_iter */\n    (iternextfunc)zip_next,     /* tp_iternext */\n    zip_methods,                        /* tp_methods */\n    0,                                  /* tp_members */\n    0,                                  /* tp_getset */\n    0,                                  /* tp_base */\n    0,                                  /* tp_dict */\n    0,                                  /* tp_descr_get */\n    0,                                  /* tp_descr_set */\n    0,                                  /* tp_dictoffset */\n    0,                                  /* tp_init */\n    PyType_GenericAlloc,                /* tp_alloc */\n    zip_new,                            /* tp_new */\n    PyObject_GC_Del,                    /* tp_free */\n};\n\n\nstatic PyMethodDef builtin_methods[] = {\n    {\"__build_class__\", _PyCFunction_CAST(builtin___build_class__),\n     METH_FASTCALL | METH_KEYWORDS, build_class_doc},\n    BUILTIN___IMPORT___METHODDEF\n    BUILTIN_ABS_METHODDEF\n    BUILTIN_ALL_METHODDEF\n    BUILTIN_ANY_METHODDEF\n    BUILTIN_ASCII_METHODDEF\n    BUILTIN_BIN_METHODDEF\n    {\"breakpoint\", _PyCFunction_CAST(builtin_breakpoint), METH_FASTCALL | METH_KEYWORDS, breakpoint_doc},\n    BUILTIN_CALLABLE_METHODDEF\n    BUILTIN_CHR_METHODDEF\n    BUILTIN_COMPILE_METHODDEF\n    BUILTIN_DELATTR_METHODDEF\n    BUILTIN_DIR_METHODDEF\n    BUILTIN_DIVMOD_METHODDEF\n    BUILTIN_EVAL_METHODDEF\n    BUILTIN_EXEC_METHODDEF\n    BUILTIN_FORMAT_METHODDEF\n    BUILTIN_GETATTR_METHODDEF\n    BUILTIN_GLOBALS_METHODDEF\n    BUILTIN_HASATTR_METHODDEF\n    BUILTIN_HASH_METHODDEF\n    BUILTIN_HEX_METHODDEF\n    BUILTIN_ID_METHODDEF\n    BUILTIN_INPUT_METHODDEF\n    BUILTIN_ISINSTANCE_METHODDEF\n    BUILTIN_ISSUBCLASS_METHODDEF\n    BUILTIN_ITER_METHODDEF\n    BUILTIN_AITER_METHODDEF\n    BUILTIN_LEN_METHODDEF\n    BUILTIN_LOCALS_METHODDEF\n    {\"max\", _PyCFunction_CAST(builtin_max), METH_VARARGS | METH_KEYWORDS, max_doc},\n    {\"min\", _PyCFunction_CAST(builtin_min), METH_VARARGS | METH_KEYWORDS, min_doc},\n    BUILTIN_NEXT_METHODDEF\n    BUILTIN_ANEXT_METHODDEF\n    BUILTIN_OCT_METHODDEF\n    BUILTIN_ORD_METHODDEF\n    BUILTIN_POW_METHODDEF\n    BUILTIN_PRINT_METHODDEF\n    BUILTIN_REPR_METHODDEF\n    BUILTIN_ROUND_METHODDEF\n    BUILTIN_SETATTR_METHODDEF\n    BUILTIN_SORTED_METHODDEF\n    BUILTIN_SUM_METHODDEF\n    BUILTIN_VARS_METHODDEF\n    {NULL,              NULL},\n};\n\nPyDoc_STRVAR(builtin_doc,\n\"Built-in functions, types, exceptions, and other objects.\\n\\\n\\n\\\nThis module provides direct access to all 'built-in'\\n\\\nidentifiers of Python; for example, builtins.len is\\n\\\nthe full name for the built-in function len().\\n\\\n\\n\\\nThis module is not normally accessed explicitly by most\\n\\\napplications, but can be useful in modules that provide\\n\\\nobjects with the same name as a built-in value, but in\\n\\\nwhich the built-in of that name is also needed.\");\n\nstatic struct PyModuleDef builtinsmodule = {\n    PyModuleDef_HEAD_INIT,\n    \"builtins\",\n    builtin_doc,\n    -1, /* multiple \"initialization\" just copies the module dict. */\n    builtin_methods,\n    NULL,\n    NULL,\n    NULL,\n    NULL\n};\n\n\nPyObject *\n_PyBuiltin_Init(PyInterpreterState *interp)\n{\n    PyObject *mod, *dict, *debug;\n\n    const PyConfig *config = _PyInterpreterState_GetConfig(interp);\n\n    mod = _PyModule_CreateInitialized(&builtinsmodule, PYTHON_API_VERSION);\n    if (mod == NULL)\n        return NULL;\n    dict = PyModule_GetDict(mod);\n\n#ifdef Py_TRACE_REFS\n    /* \"builtins\" exposes a number of statically allocated objects\n     * that, before this code was added in 2.3, never showed up in\n     * the list of \"all objects\" maintained by Py_TRACE_REFS.  As a\n     * result, programs leaking references to None and False (etc)\n     * couldn't be diagnosed by examining sys.getobjects(0).\n     */\n#define ADD_TO_ALL(OBJECT) _Py_AddToAllObjects((PyObject *)(OBJECT), 0)\n#else\n#define ADD_TO_ALL(OBJECT) (void)0\n#endif\n\n#define SETBUILTIN(NAME, OBJECT) \\\n    if (PyDict_SetItemString(dict, NAME, (PyObject *)OBJECT) < 0)       \\\n        return NULL;                                                    \\\n    ADD_TO_ALL(OBJECT)\n\n    SETBUILTIN(\"None\",                  Py_None);\n    SETBUILTIN(\"Ellipsis\",              Py_Ellipsis);\n    SETBUILTIN(\"NotImplemented\",        Py_NotImplemented);\n    SETBUILTIN(\"False\",                 Py_False);\n    SETBUILTIN(\"True\",                  Py_True);\n    SETBUILTIN(\"bool\",                  &PyBool_Type);\n    SETBUILTIN(\"memoryview\",        &PyMemoryView_Type);\n    SETBUILTIN(\"bytearray\",             &PyByteArray_Type);\n    SETBUILTIN(\"bytes\",                 &PyBytes_Type);\n    SETBUILTIN(\"classmethod\",           &PyClassMethod_Type);\n    SETBUILTIN(\"complex\",               &PyComplex_Type);\n    SETBUILTIN(\"dict\",                  &PyDict_Type);\n    SETBUILTIN(\"enumerate\",             &PyEnum_Type);\n    SETBUILTIN(\"filter\",                &PyFilter_Type);\n    SETBUILTIN(\"float\",                 &PyFloat_Type);\n    SETBUILTIN(\"frozenset\",             &PyFrozenSet_Type);\n    SETBUILTIN(\"property\",              &PyProperty_Type);\n    SETBUILTIN(\"int\",                   &PyLong_Type);\n    SETBUILTIN(\"list\",                  &PyList_Type);\n    SETBUILTIN(\"map\",                   &PyMap_Type);\n    SETBUILTIN(\"object\",                &PyBaseObject_Type);\n    SETBUILTIN(\"range\",                 &PyRange_Type);\n    SETBUILTIN(\"reversed\",              &PyReversed_Type);\n    SETBUILTIN(\"set\",                   &PySet_Type);\n    SETBUILTIN(\"slice\",                 &PySlice_Type);\n    SETBUILTIN(\"staticmethod\",          &PyStaticMethod_Type);\n    SETBUILTIN(\"str\",                   &PyUnicode_Type);\n    SETBUILTIN(\"super\",                 &PySuper_Type);\n    SETBUILTIN(\"tuple\",                 &PyTuple_Type);\n    SETBUILTIN(\"type\",                  &PyType_Type);\n    SETBUILTIN(\"zip\",                   &PyZip_Type);\n    debug = PyBool_FromLong(config->optimization_level == 0);\n    if (PyDict_SetItemString(dict, \"__debug__\", debug) < 0) {\n        Py_DECREF(debug);\n        return NULL;\n    }\n    Py_DECREF(debug);\n\n    return mod;\n#undef ADD_TO_ALL\n#undef SETBUILTIN\n}\n"
  },
  {
    "path": "Bootstrap_Hash.c",
    "content": "#include \"Python.h\"\n#include \"pycore_initconfig.h\"\n#include \"pycore_fileutils.h\"     // _Py_fstat_noraise()\n#include \"pycore_runtime.h\"       // _PyRuntime\n\n#ifdef MS_WINDOWS\n#  include <windows.h>\n#  include <bcrypt.h>\n#else\n#  include <fcntl.h>\n#  ifdef HAVE_SYS_STAT_H\n#    include <sys/stat.h>\n#  endif\n#  ifdef HAVE_LINUX_RANDOM_H\n#    include <linux/random.h>\n#  endif\n#  if defined(HAVE_SYS_RANDOM_H) && (defined(HAVE_GETRANDOM) || defined(HAVE_GETENTROPY))\n#    include <sys/random.h>\n#  endif\n#  if !defined(HAVE_GETRANDOM) && defined(HAVE_GETRANDOM_SYSCALL)\n#    include <sys/syscall.h>\n#  endif\n#endif\n\n#ifdef _Py_MEMORY_SANITIZER\n#  include <sanitizer/msan_interface.h>\n#endif\n\n#if defined(__APPLE__) && defined(__has_builtin)\n#  if __has_builtin(__builtin_available)\n#    define HAVE_GETENTRYPY_GETRANDOM_RUNTIME __builtin_available(macOS 10.12, iOS 10.10, tvOS 10.0, watchOS 3.0, *)\n#  endif\n#endif\n#ifndef HAVE_GETENTRYPY_GETRANDOM_RUNTIME\n#  define HAVE_GETENTRYPY_GETRANDOM_RUNTIME 1\n#endif\n\n\n#ifdef Py_DEBUG\nint _Py_HashSecret_Initialized = 0;\n#else\nstatic int _Py_HashSecret_Initialized = 0;\n#endif\n\n#ifdef MS_WINDOWS\n\n/* Fill buffer with size pseudo-random bytes generated by the Windows CryptoGen\n   API. Return 0 on success, or raise an exception and return -1 on error. */\nstatic int\nwin32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)\n{\n    while (size > 0)\n    {\n        DWORD chunk = (DWORD)Py_MIN(size, PY_DWORD_MAX);\n        NTSTATUS status = BCryptGenRandom(NULL, buffer, chunk, BCRYPT_USE_SYSTEM_PREFERRED_RNG);\n        if (!BCRYPT_SUCCESS(status)) {\n            /* BCryptGenRandom() failed */\n            if (raise) {\n                PyErr_SetFromWindowsErr(0);\n            }\n            return -1;\n        }\n        buffer += chunk;\n        size -= chunk;\n    }\n    return 0;\n}\n\n#else /* !MS_WINDOWS */\n\n#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)\n#define PY_GETRANDOM 1\n\n/* Call getrandom() to get random bytes:\n\n   - Return 1 on success\n   - Return 0 if getrandom() is not available (failed with ENOSYS or EPERM),\n     or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom not\n     initialized yet) and raise=0.\n   - Raise an exception (if raise is non-zero) and return -1 on error:\n     if getrandom() failed with EINTR, raise is non-zero and the Python signal\n     handler raised an exception, or if getrandom() failed with a different\n     error.\n\n   getrandom() is retried if it failed with EINTR: interrupted by a signal. */\nstatic int\npy_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)\n{\n    /* Is getrandom() supported by the running kernel? Set to 0 if getrandom()\n       failed with ENOSYS or EPERM. Need Linux kernel 3.17 or newer, or Solaris\n       11.3 or newer */\n    static int getrandom_works = 1;\n    int flags;\n    char *dest;\n    long n;\n\n    if (!getrandom_works) {\n        return 0;\n    }\n\n    flags = blocking ? 0 : GRND_NONBLOCK;\n    dest = buffer;\n    while (0 < size) {\n#if defined(__sun) && defined(__SVR4)\n        /* Issue #26735: On Solaris, getrandom() is limited to returning up\n           to 1024 bytes. Call it multiple times if more bytes are\n           requested. */\n        n = Py_MIN(size, 1024);\n#else\n        n = Py_MIN(size, LONG_MAX);\n#endif\n\n        errno = 0;\n#ifdef HAVE_GETRANDOM\n        if (raise) {\n            Py_BEGIN_ALLOW_THREADS\n            n = getrandom(dest, n, flags);\n            Py_END_ALLOW_THREADS\n        }\n        else {\n            n = getrandom(dest, n, flags);\n        }\n#else\n        /* On Linux, use the syscall() function because the GNU libc doesn't\n           expose the Linux getrandom() syscall yet. See:\n           https://sourceware.org/bugzilla/show_bug.cgi?id=17252 */\n        if (raise) {\n            Py_BEGIN_ALLOW_THREADS\n            n = syscall(SYS_getrandom, dest, n, flags);\n            Py_END_ALLOW_THREADS\n        }\n        else {\n            n = syscall(SYS_getrandom, dest, n, flags);\n        }\n#  ifdef _Py_MEMORY_SANITIZER\n        if (n > 0) {\n             __msan_unpoison(dest, n);\n        }\n#  endif\n#endif\n\n        if (n < 0) {\n            /* ENOSYS: the syscall is not supported by the kernel.\n               EPERM: the syscall is blocked by a security policy (ex: SECCOMP)\n               or something else. */\n            if (errno == ENOSYS || errno == EPERM) {\n                getrandom_works = 0;\n                return 0;\n            }\n\n            /* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system urandom\n               is not initialized yet. For _PyRandom_Init(), we ignore the\n               error and fall back on reading /dev/urandom which never blocks,\n               even if the system urandom is not initialized yet:\n               see the PEP 524. */\n            if (errno == EAGAIN && !raise && !blocking) {\n                return 0;\n            }\n\n            if (errno == EINTR) {\n                if (raise) {\n                    if (PyErr_CheckSignals()) {\n                        return -1;\n                    }\n                }\n\n                /* retry getrandom() if it was interrupted by a signal */\n                continue;\n            }\n\n            if (raise) {\n                PyErr_SetFromErrno(PyExc_OSError);\n            }\n            return -1;\n        }\n\n        dest += n;\n        size -= n;\n    }\n    return 1;\n}\n\n#elif defined(HAVE_GETENTROPY)\n#define PY_GETENTROPY 1\n\n/* Fill buffer with size pseudo-random bytes generated by getentropy():\n\n   - Return 1 on success\n   - Return 0 if getentropy() syscall is not available (failed with ENOSYS or\n     EPERM).\n   - Raise an exception (if raise is non-zero) and return -1 on error:\n     if getentropy() failed with EINTR, raise is non-zero and the Python signal\n     handler raised an exception, or if getentropy() failed with a different\n     error.\n\n   getentropy() is retried if it failed with EINTR: interrupted by a signal. */\n\n#if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability)\nstatic int\npy_getentropy(char *buffer, Py_ssize_t size, int raise)\n        __attribute__((availability(macos,introduced=10.12)))\n        __attribute__((availability(ios,introduced=10.0)))\n        __attribute__((availability(tvos,introduced=10.0)))\n        __attribute__((availability(watchos,introduced=3.0)));\n#endif\n\nstatic int\npy_getentropy(char *buffer, Py_ssize_t size, int raise)\n{\n    /* Is getentropy() supported by the running kernel? Set to 0 if\n       getentropy() failed with ENOSYS or EPERM. */\n    static int getentropy_works = 1;\n\n    if (!getentropy_works) {\n        return 0;\n    }\n\n    while (size > 0) {\n        /* getentropy() is limited to returning up to 256 bytes. Call it\n           multiple times if more bytes are requested. */\n        Py_ssize_t len = Py_MIN(size, 256);\n        int res;\n\n        if (raise) {\n            Py_BEGIN_ALLOW_THREADS\n            res = getentropy(buffer, len);\n            Py_END_ALLOW_THREADS\n        }\n        else {\n            res = getentropy(buffer, len);\n        }\n\n        if (res < 0) {\n            /* ENOSYS: the syscall is not supported by the running kernel.\n               EPERM: the syscall is blocked by a security policy (ex: SECCOMP)\n               or something else. */\n            if (errno == ENOSYS || errno == EPERM) {\n                getentropy_works = 0;\n                return 0;\n            }\n\n            if (errno == EINTR) {\n                if (raise) {\n                    if (PyErr_CheckSignals()) {\n                        return -1;\n                    }\n                }\n\n                /* retry getentropy() if it was interrupted by a signal */\n                continue;\n            }\n\n            if (raise) {\n                PyErr_SetFromErrno(PyExc_OSError);\n            }\n            return -1;\n        }\n\n        buffer += len;\n        size -= len;\n    }\n    return 1;\n}\n#endif /* defined(HAVE_GETENTROPY) && !(defined(__sun) && defined(__SVR4)) */\n\n\n#define urandom_cache (_PyRuntime.pyhash_state.urandom_cache)\n\n/* Read random bytes from the /dev/urandom device:\n\n   - Return 0 on success\n   - Raise an exception (if raise is non-zero) and return -1 on error\n\n   Possible causes of errors:\n\n   - open() failed with ENOENT, ENXIO, ENODEV, EACCES: the /dev/urandom device\n     was not found. For example, it was removed manually or not exposed in a\n     chroot or container.\n   - open() failed with a different error\n   - fstat() failed\n   - read() failed or returned 0\n\n   read() is retried if it failed with EINTR: interrupted by a signal.\n\n   The file descriptor of the device is kept open between calls to avoid using\n   many file descriptors when run in parallel from multiple threads:\n   see the issue #18756.\n\n   st_dev and st_ino fields of the file descriptor (from fstat()) are cached to\n   check if the file descriptor was replaced by a different file (which is\n   likely a bug in the application): see the issue #21207.\n\n   If the file descriptor was closed or replaced, open a new file descriptor\n   but don't close the old file descriptor: it probably points to something\n   important for some third-party code. */\nstatic int\ndev_urandom(char *buffer, Py_ssize_t size, int raise)\n{\n    int fd;\n    Py_ssize_t n;\n\n    if (raise) {\n        struct _Py_stat_struct st;\n        int fstat_result;\n\n        if (urandom_cache.fd >= 0) {\n            Py_BEGIN_ALLOW_THREADS\n            fstat_result = _Py_fstat_noraise(urandom_cache.fd, &st);\n            Py_END_ALLOW_THREADS\n\n            /* Does the fd point to the same thing as before? (issue #21207) */\n            if (fstat_result\n                || st.st_dev != urandom_cache.st_dev\n                || st.st_ino != urandom_cache.st_ino) {\n                /* Something changed: forget the cached fd (but don't close it,\n                   since it probably points to something important for some\n                   third-party code). */\n                urandom_cache.fd = -1;\n            }\n        }\n        if (urandom_cache.fd >= 0)\n            fd = urandom_cache.fd;\n        else {\n            fd = _Py_open(\"/dev/urandom\", O_RDONLY);\n            if (fd < 0) {\n                if (errno == ENOENT || errno == ENXIO ||\n                    errno == ENODEV || errno == EACCES) {\n                    PyErr_SetString(PyExc_NotImplementedError,\n                                    \"/dev/urandom (or equivalent) not found\");\n                }\n                /* otherwise, keep the OSError exception raised by _Py_open() */\n                return -1;\n            }\n            if (urandom_cache.fd >= 0) {\n                /* urandom_fd was initialized by another thread while we were\n                   not holding the GIL, keep it. */\n                close(fd);\n                fd = urandom_cache.fd;\n            }\n            else {\n                if (_Py_fstat(fd, &st)) {\n                    close(fd);\n                    return -1;\n                }\n                else {\n                    urandom_cache.fd = fd;\n                    urandom_cache.st_dev = st.st_dev;\n                    urandom_cache.st_ino = st.st_ino;\n                }\n            }\n        }\n\n        do {\n            n = _Py_read(fd, buffer, (size_t)size);\n            if (n == -1)\n                return -1;\n            if (n == 0) {\n                PyErr_Format(PyExc_RuntimeError,\n                        \"Failed to read %zi bytes from /dev/urandom\",\n                        size);\n                return -1;\n            }\n\n            buffer += n;\n            size -= n;\n        } while (0 < size);\n    }\n    else {\n        fd = _Py_open_noraise(\"/dev/urandom\", O_RDONLY);\n        if (fd < 0) {\n            return -1;\n        }\n\n        while (0 < size)\n        {\n            do {\n                n = read(fd, buffer, (size_t)size);\n            } while (n < 0 && errno == EINTR);\n\n            if (n <= 0) {\n                /* stop on error or if read(size) returned 0 */\n                close(fd);\n                return -1;\n            }\n\n            buffer += n;\n            size -= n;\n        }\n        close(fd);\n    }\n    return 0;\n}\n\nstatic void\ndev_urandom_close(void)\n{\n    if (urandom_cache.fd >= 0) {\n        close(urandom_cache.fd);\n        urandom_cache.fd = -1;\n    }\n}\n\n#undef urandom_cache\n\n#endif /* !MS_WINDOWS */\n\n\n/* Fill buffer with pseudo-random bytes generated by a linear congruent\n   generator (LCG):\n\n       x(n+1) = (x(n) * 214013 + 2531011) % 2^32\n\n   Use bits 23..16 of x(n) to generate a byte. */\nstatic void\nlcg_urandom(unsigned int x0, unsigned char *buffer, size_t size)\n{\n    size_t index;\n    unsigned int x;\n\n    x = x0;\n    for (index=0; index < size; index++) {\n        x *= 214013;\n        x += 2531011;\n        /* modulo 2 ^ (8 * sizeof(int)) */\n        buffer[index] = (x >> 16) & 0xff;\n    }\n}\n\n/* Read random bytes:\n\n   - Return 0 on success\n   - Raise an exception (if raise is non-zero) and return -1 on error\n\n   Used sources of entropy ordered by preference, preferred source first:\n\n   - BCryptGenRandom() on Windows\n   - getrandom() function (ex: Linux and Solaris): call py_getrandom()\n   - getentropy() function (ex: OpenBSD): call py_getentropy()\n   - /dev/urandom device\n\n   Read from the /dev/urandom device if getrandom() or getentropy() function\n   is not available or does not work.\n\n   Prefer getrandom() over getentropy() because getrandom() supports blocking\n   and non-blocking mode: see the PEP 524. Python requires non-blocking RNG at\n   startup to initialize its hash secret, but os.urandom() must block until the\n   system urandom is initialized (at least on Linux 3.17 and newer).\n\n   Prefer getrandom() and getentropy() over reading directly /dev/urandom\n   because these functions don't need file descriptors and so avoid ENFILE or\n   EMFILE errors (too many open files): see the issue #18756.\n\n   Only the getrandom() function supports non-blocking mode.\n\n   Only use RNG running in the kernel. They are more secure because it is\n   harder to get the internal state of a RNG running in the kernel land than a\n   RNG running in the user land. The kernel has a direct access to the hardware\n   and has access to hardware RNG, they are used as entropy sources.\n\n   Note: the OpenSSL RAND_pseudo_bytes() function does not automatically reseed\n   its RNG on fork(), two child processes (with the same pid) generate the same\n   random numbers: see issue #18747. Kernel RNGs don't have this issue,\n   they have access to good quality entropy sources.\n\n   If raise is zero:\n\n   - Don't raise an exception on error\n   - Don't call the Python signal handler (don't call PyErr_CheckSignals()) if\n     a function fails with EINTR: retry directly the interrupted function\n   - Don't release the GIL to call functions.\n*/\nstatic int\npyurandom(void *buffer, Py_ssize_t size, int blocking, int raise)\n{\n#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)\n    int res;\n#endif\n\n    if (size < 0) {\n        if (raise) {\n            PyErr_Format(PyExc_ValueError,\n                         \"negative argument not allowed\");\n        }\n        return -1;\n    }\n\n    if (size == 0) {\n        return 0;\n    }\n\n#ifdef MS_WINDOWS\n    return win32_urandom((unsigned char *)buffer, size, raise);\n#else\n\n#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)\n    if (HAVE_GETENTRYPY_GETRANDOM_RUNTIME) {\n#ifdef PY_GETRANDOM\n        res = py_getrandom(buffer, size, blocking, raise);\n#else\n        res = py_getentropy(buffer, size, raise);\n#endif\n        if (res < 0) {\n            return -1;\n        }\n        if (res == 1) {\n            return 0;\n        }\n        /* getrandom() or getentropy() function is not available: failed with\n           ENOSYS or EPERM. Fall back on reading from /dev/urandom. */\n        } /* end of availability block */\n#endif\n\n    return dev_urandom(buffer, size, raise);\n#endif\n}\n\n/* Fill buffer with size pseudo-random bytes from the operating system random\n   number generator (RNG). It is suitable for most cryptographic purposes\n   except long living private keys for asymmetric encryption.\n\n   On Linux 3.17 and newer, the getrandom() syscall is used in blocking mode:\n   block until the system urandom entropy pool is initialized (128 bits are\n   collected by the kernel).\n\n   Return 0 on success. Raise an exception and return -1 on error. */\nint\n_PyOS_URandom(void *buffer, Py_ssize_t size)\n{\n    return pyurandom(buffer, size, 1, 1);\n}\n\n/* Fill buffer with size pseudo-random bytes from the operating system random\n   number generator (RNG). It is not suitable for cryptographic purpose.\n\n   On Linux 3.17 and newer (when getrandom() syscall is used), if the system\n   urandom is not initialized yet, the function returns \"weak\" entropy read\n   from /dev/urandom.\n\n   Return 0 on success. Raise an exception and return -1 on error. */\nint\n_PyOS_URandomNonblock(void *buffer, Py_ssize_t size)\n{\n    return pyurandom(buffer, size, 0, 1);\n}\n\n\nPyStatus\n_Py_HashRandomization_Init(const PyConfig *config)\n{\n    void *secret = &_Py_HashSecret;\n    Py_ssize_t secret_size = sizeof(_Py_HashSecret_t);\n\n    if (_Py_HashSecret_Initialized) {\n        return _PyStatus_OK();\n    }\n    _Py_HashSecret_Initialized = 1;\n\n    if (config->use_hash_seed) {\n        if (config->hash_seed == 0) {\n            /* disable the randomized hash */\n            memset(secret, 0, secret_size);\n        }\n        else {\n            /* use the specified hash seed */\n            lcg_urandom(config->hash_seed, secret, secret_size);\n        }\n    }\n    else {\n        /* use a random hash seed */\n        int res;\n\n        /* _PyRandom_Init() is called very early in the Python initialization\n           and so exceptions cannot be used (use raise=0).\n\n           _PyRandom_Init() must not block Python initialization: call\n           pyurandom() is non-blocking mode (blocking=0): see the PEP 524. */\n        res = pyurandom(secret, secret_size, 0, 0);\n        if (res < 0) {\n            return _PyStatus_ERR(\"failed to get random numbers \"\n                                 \"to initialize Python\");\n        }\n    }\n    return _PyStatus_OK();\n}\n\n\nvoid\n_Py_HashRandomization_Fini(void)\n{\n#ifndef MS_WINDOWS\n    dev_urandom_close();\n#endif\n}\n"
  },
  {
    "path": "ByteCodes.c",
    "content": "// This file contains instruction definitions.\n// It is read by Tools/cases_generator/generate_cases.py\n// to generate Python/generated_cases.c.h.\n// Note that there is some dummy C code at the top and bottom of the file\n// to fool text editors like VS Code into believing this is valid C code.\n// The actual instruction definitions start at // BEGIN BYTECODES //.\n// See Tools/cases_generator/README.md for more information.\n\n#include \"Python.h\"\n#include \"pycore_abstract.h\"      // _PyIndex_Check()\n#include \"pycore_call.h\"          // _PyObject_FastCallDictTstate()\n#include \"pycore_ceval.h\"         // _PyEval_SignalAsyncExc()\n#include \"pycore_code.h\"\n#include \"pycore_function.h\"\n#include \"pycore_intrinsics.h\"\n#include \"pycore_long.h\"          // _PyLong_GetZero()\n#include \"pycore_instruments.h\"\n#include \"pycore_object.h\"        // _PyObject_GC_TRACK()\n#include \"pycore_moduleobject.h\"  // PyModuleObject\n#include \"pycore_opcode.h\"        // EXTRA_CASES\n#include \"pycore_opcode_utils.h\"  // MAKE_FUNCTION_*\n#include \"pycore_pyerrors.h\"      // _PyErr_GetRaisedException()\n#include \"pycore_pystate.h\"       // _PyInterpreterState_GET()\n#include \"pycore_range.h\"         // _PyRangeIterObject\n#include \"pycore_sliceobject.h\"   // _PyBuildSlice_ConsumeRefs\n#include \"pycore_sysmodule.h\"     // _PySys_Audit()\n#include \"pycore_tuple.h\"         // _PyTuple_ITEMS()\n#include \"pycore_typeobject.h\"    // _PySuper_Lookup()\n#include \"pycore_emscripten_signal.h\"  // _Py_CHECK_EMSCRIPTEN_SIGNALS\n\n#include \"pycore_dict.h\"\n#include \"dictobject.h\"\n#include \"pycore_frame.h\"\n#include \"opcode.h\"\n#include \"optimizer.h\"\n#include \"pydtrace.h\"\n#include \"setobject.h\"\n#include \"structmember.h\"         // struct PyMemberDef, T_OFFSET_EX\n\n#define USE_COMPUTED_GOTOS 0\n#include \"ceval_macros.h\"\n\n/* Flow control macros */\n#define DEOPT_IF(cond, instname) ((void)0)\n#define ERROR_IF(cond, labelname) ((void)0)\n#define GO_TO_INSTRUCTION(instname) ((void)0)\n\n#define inst(name, ...) case name:\n#define op(name, ...) /* NAME is ignored */\n#define macro(name) static int MACRO_##name\n#define super(name) static int SUPER_##name\n#define family(name, ...) static int family_##name\n\n// Dummy variables for stack effects.\nstatic PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub;\nstatic PyObject *container, *start, *stop, *v, *lhs, *rhs, *res2;\nstatic PyObject *list, *tuple, *dict, *owner, *set, *str, *tup, *map, *keys;\nstatic PyObject *exit_func, *lasti, *val, *retval, *obj, *iter;\nstatic PyObject *aiter, *awaitable, *iterable, *w, *exc_value, *bc, *locals;\nstatic PyObject *orig, *excs, *update, *b, *fromlist, *level, *from;\nstatic PyObject **pieces, **values;\nstatic size_t jump;\n// Dummy variables for cache effects\nstatic uint16_t invert, counter, index, hint;\nstatic uint32_t type_version;\n\nstatic PyObject *\ndummy_func(\n    PyThreadState *tstate,\n    _PyInterpreterFrame *frame,\n    unsigned char opcode,\n    unsigned int oparg,\n    _PyCFrame cframe,\n    _Py_CODEUNIT *next_instr,\n    PyObject **stack_pointer,\n    PyObject *kwnames,\n    int throwflag,\n    binaryfunc binary_ops[],\n    PyObject *args[]\n)\n{\n    // Dummy labels.\n    pop_1_error:\n    // Dummy locals.\n    PyObject *annotations;\n    PyObject *attrs;\n    PyObject *bottom;\n    PyObject *callable;\n    PyObject *callargs;\n    PyObject *closure;\n    PyObject *codeobj;\n    PyObject *cond;\n    PyObject *defaults;\n    PyObject *descr;\n    _PyInterpreterFrame  entry_frame;\n    PyObject *exc;\n    PyObject *exit;\n    PyObject *fget;\n    PyObject *fmt_spec;\n    PyObject *func;\n    uint32_t func_version;\n    PyObject *getattribute;\n    PyObject *kwargs;\n    PyObject *kwdefaults;\n    PyObject *len_o;\n    PyObject *match;\n    PyObject *match_type;\n    PyObject *method;\n    PyObject *mgr;\n    Py_ssize_t min_args;\n    PyObject *names;\n    PyObject *new_exc;\n    PyObject *next;\n    PyObject *none;\n    PyObject *null;\n    PyObject *prev_exc;\n    PyObject *receiver;\n    PyObject *rest;\n    int result;\n    PyObject *self;\n    PyObject *seq;\n    PyObject *slice;\n    PyObject *step;\n    PyObject *subject;\n    PyObject *top;\n    PyObject *type;\n    PyObject *typevars;\n    int values_or_none;\n\n    switch (opcode) {\n\n// BEGIN BYTECODES //\n        inst(NOP, (--)) {\n        }\n\n        inst(RESUME, (--)) {\n            assert(tstate->cframe == &cframe);\n            assert(frame == cframe.current_frame);\n            /* Possibly combine this with eval breaker */\n            if (frame->f_code->_co_instrumentation_version != tstate->interp->monitoring_version) {\n                int err = _Py_Instrument(frame->f_code, tstate->interp);\n                ERROR_IF(err, error);\n                next_instr--;\n            }\n            else if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker) && oparg < 2) {\n                goto handle_eval_breaker;\n            }\n        }\n\n        inst(INSTRUMENTED_RESUME, (--)) {\n            /* Possible performance enhancement:\n             *   We need to check the eval breaker anyway, can we\n             * combine the instrument verison check and the eval breaker test?\n             */\n            if (frame->f_code->_co_instrumentation_version != tstate->interp->monitoring_version) {\n                if (_Py_Instrument(frame->f_code, tstate->interp)) {\n                    goto error;\n                }\n                next_instr--;\n            }\n            else {\n                _PyFrame_SetStackPointer(frame, stack_pointer);\n                int err = _Py_call_instrumentation(\n                        tstate, oparg > 0, frame, next_instr-1);\n                stack_pointer = _PyFrame_GetStackPointer(frame);\n                ERROR_IF(err, error);\n                if (frame->prev_instr != next_instr-1) {\n                    /* Instrumentation has jumped */\n                    next_instr = frame->prev_instr;\n                    DISPATCH();\n                }\n                if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker) && oparg < 2) {\n                    goto handle_eval_breaker;\n                }\n            }\n        }\n\n        inst(LOAD_CLOSURE, (-- value)) {\n            /* We keep LOAD_CLOSURE so that the bytecode stays more readable. */\n            value = GETLOCAL(oparg);\n            ERROR_IF(value == NULL, unbound_local_error);\n            Py_INCREF(value);\n        }\n\n        inst(LOAD_FAST_CHECK, (-- value)) {\n            value = GETLOCAL(oparg);\n            ERROR_IF(value == NULL, unbound_local_error);\n            Py_INCREF(value);\n        }\n\n        inst(LOAD_FAST, (-- value)) {\n            value = GETLOCAL(oparg);\n            assert(value != NULL);\n            Py_INCREF(value);\n        }\n\n        inst(LOAD_FAST_AND_CLEAR, (-- value)) {\n            value = GETLOCAL(oparg);\n            // do not use SETLOCAL here, it decrefs the old value\n            GETLOCAL(oparg) = NULL;\n        }\n\n        inst(LOAD_FAST_LOAD_FAST, ( -- value1, value2)) {\n            uint32_t oparg1 = oparg >> 4;\n            uint32_t oparg2 = oparg & 15;\n            value1 = GETLOCAL(oparg1);\n            value2 = GETLOCAL(oparg2);\n            Py_INCREF(value1);\n            Py_INCREF(value2);\n        }\n\n        inst(LOAD_CONST, (-- value)) {\n            value = GETITEM(frame->f_code->co_consts, oparg);\n            Py_INCREF(value);\n        }\n\n        inst(STORE_FAST, (value --)) {\n            SETLOCAL(oparg, value);\n        }\n\n        inst(STORE_FAST_LOAD_FAST, (value1 -- value2)) {\n            uint32_t oparg1 = oparg >> 4;\n            uint32_t oparg2 = oparg & 15;\n            SETLOCAL(oparg1, value1);\n            value2 = GETLOCAL(oparg2);\n            Py_INCREF(value2);\n        }\n\n        inst(STORE_FAST_STORE_FAST, (value2, value1 --)) {\n            uint32_t oparg1 = oparg >> 4;\n            uint32_t oparg2 = oparg & 15;\n            SETLOCAL(oparg1, value1);\n            SETLOCAL(oparg2, value2);\n        }\n\n        inst(POP_TOP, (value --)) {\n            DECREF_INPUTS();\n        }\n\n        inst(PUSH_NULL, (-- res)) {\n            res = NULL;\n        }\n\n        macro(END_FOR) = POP_TOP + POP_TOP;\n\n        inst(INSTRUMENTED_END_FOR, (receiver, value --)) {\n            /* Need to create a fake StopIteration error here,\n             * to conform to PEP 380 */\n            if (PyGen_Check(receiver)) {\n                PyErr_SetObject(PyExc_StopIteration, value);\n                if (monitor_stop_iteration(tstate, frame, next_instr-1)) {\n                    goto error;\n                }\n                PyErr_SetRaisedException(NULL);\n            }\n            DECREF_INPUTS();\n        }\n\n        inst(END_SEND, (receiver, value -- value)) {\n            Py_DECREF(receiver);\n        }\n\n        inst(INSTRUMENTED_END_SEND, (receiver, value -- value)) {\n            if (PyGen_Check(receiver) || PyCoro_CheckExact(receiver)) {\n                PyErr_SetObject(PyExc_StopIteration, value);\n                if (monitor_stop_iteration(tstate, frame, next_instr-1)) {\n                    goto error;\n                }\n                PyErr_SetRaisedException(NULL);\n            }\n            Py_DECREF(receiver);\n        }\n\n        inst(UNARY_NEGATIVE, (value -- res)) {\n            res = PyNumber_Negative(value);\n            DECREF_INPUTS();\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(UNARY_NOT, (value -- res)) {\n            int err = PyObject_IsTrue(value);\n            DECREF_INPUTS();\n            ERROR_IF(err < 0, error);\n            if (err == 0) {\n                res = Py_True;\n            }\n            else {\n                res = Py_False;\n            }\n        }\n\n        inst(UNARY_INVERT, (value -- res)) {\n            res = PyNumber_Invert(value);\n            DECREF_INPUTS();\n            ERROR_IF(res == NULL, error);\n        }\n\n        family(binary_op, INLINE_CACHE_ENTRIES_BINARY_OP) = {\n            BINARY_OP,\n            BINARY_OP_MULTIPLY_INT,\n            BINARY_OP_ADD_INT,\n            BINARY_OP_SUBTRACT_INT,\n            BINARY_OP_MULTIPLY_FLOAT,\n            BINARY_OP_ADD_FLOAT,\n            BINARY_OP_SUBTRACT_FLOAT,\n            BINARY_OP_ADD_UNICODE,\n            // BINARY_OP_INPLACE_ADD_UNICODE,  // See comments at that opcode.\n        };\n\n        op(_GUARD_BOTH_INT, (left, right -- left, right)) {\n            DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);\n            DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);\n        }\n\n        op(_BINARY_OP_MULTIPLY_INT, (unused/1, left, right -- res)) {\n            STAT_INC(BINARY_OP, hit);\n            res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);\n            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);\n            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);\n            ERROR_IF(res == NULL, error);\n        }\n\n        op(_BINARY_OP_ADD_INT, (unused/1, left, right -- res)) {\n            STAT_INC(BINARY_OP, hit);\n            res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);\n            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);\n            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);\n            ERROR_IF(res == NULL, error);\n        }\n\n        op(_BINARY_OP_SUBTRACT_INT, (unused/1, left, right -- res)) {\n            STAT_INC(BINARY_OP, hit);\n            res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);\n            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);\n            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);\n            ERROR_IF(res == NULL, error);\n        }\n\n        macro(BINARY_OP_MULTIPLY_INT) =\n            _GUARD_BOTH_INT + _BINARY_OP_MULTIPLY_INT;\n        macro(BINARY_OP_ADD_INT) =\n            _GUARD_BOTH_INT + _BINARY_OP_ADD_INT;\n        macro(BINARY_OP_SUBTRACT_INT) =\n            _GUARD_BOTH_INT + _BINARY_OP_SUBTRACT_INT;\n\n        op(_GUARD_BOTH_FLOAT, (left, right -- left, right)) {\n            DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);\n            DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);\n        }\n\n        op(_BINARY_OP_MULTIPLY_FLOAT, (unused/1, left, right -- res)) {\n            STAT_INC(BINARY_OP, hit);\n            double dres =\n                ((PyFloatObject *)left)->ob_fval *\n                ((PyFloatObject *)right)->ob_fval;\n            DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);\n        }\n\n        op(_BINARY_OP_ADD_FLOAT, (unused/1, left, right -- res)) {\n            STAT_INC(BINARY_OP, hit);\n            double dres =\n                ((PyFloatObject *)left)->ob_fval +\n                ((PyFloatObject *)right)->ob_fval;\n            DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);\n        }\n\n        op(_BINARY_OP_SUBTRACT_FLOAT, (unused/1, left, right -- res)) {\n            STAT_INC(BINARY_OP, hit);\n            double dres =\n                ((PyFloatObject *)left)->ob_fval -\n                ((PyFloatObject *)right)->ob_fval;\n            DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);\n        }\n\n        macro(BINARY_OP_MULTIPLY_FLOAT) =\n            _GUARD_BOTH_FLOAT + _BINARY_OP_MULTIPLY_FLOAT;\n        macro(BINARY_OP_ADD_FLOAT) =\n            _GUARD_BOTH_FLOAT + _BINARY_OP_ADD_FLOAT;\n        macro(BINARY_OP_SUBTRACT_FLOAT) =\n            _GUARD_BOTH_FLOAT + _BINARY_OP_SUBTRACT_FLOAT;\n\n        op(_GUARD_BOTH_UNICODE, (left, right -- left, right)) {\n            DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);\n            DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP);\n        }\n\n        op(_BINARY_OP_ADD_UNICODE, (unused/1, left, right -- res)) {\n            STAT_INC(BINARY_OP, hit);\n            res = PyUnicode_Concat(left, right);\n            _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);\n            _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);\n            ERROR_IF(res == NULL, error);\n        }\n\n        macro(BINARY_OP_ADD_UNICODE) =\n            _GUARD_BOTH_UNICODE + _BINARY_OP_ADD_UNICODE;\n\n        // This is a subtle one. It's a super-instruction for\n        // BINARY_OP_ADD_UNICODE followed by STORE_FAST\n        // where the store goes into the left argument.\n        // So the inputs are the same as for all BINARY_OP\n        // specializations, but there is no output.\n        // At the end we just skip over the STORE_FAST.\n        op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right --)) {\n            _Py_CODEUNIT true_next = next_instr[INLINE_CACHE_ENTRIES_BINARY_OP];\n            assert(true_next.op.code == STORE_FAST);\n            PyObject **target_local = &GETLOCAL(true_next.op.arg);\n            DEOPT_IF(*target_local != left, BINARY_OP);\n            STAT_INC(BINARY_OP, hit);\n            /* Handle `left = left + right` or `left += right` for str.\n             *\n             * When possible, extend `left` in place rather than\n             * allocating a new PyUnicodeObject. This attempts to avoid\n             * quadratic behavior when one neglects to use str.join().\n             *\n             * If `left` has only two references remaining (one from\n             * the stack, one in the locals), DECREFing `left` leaves\n             * only the locals reference, so PyUnicode_Append knows\n             * that the string is safe to mutate.\n             */\n            assert(Py_REFCNT(left) >= 2);\n            _Py_DECREF_NO_DEALLOC(left);\n            PyUnicode_Append(target_local, right);\n            _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);\n            ERROR_IF(*target_local == NULL, error);\n            // The STORE_FAST is already done.\n            JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP + 1);\n        }\n\n        macro(BINARY_OP_INPLACE_ADD_UNICODE) =\n            _GUARD_BOTH_UNICODE + _BINARY_OP_INPLACE_ADD_UNICODE;\n\n        family(binary_subscr, INLINE_CACHE_ENTRIES_BINARY_SUBSCR) = {\n            BINARY_SUBSCR,\n            BINARY_SUBSCR_DICT,\n            BINARY_SUBSCR_GETITEM,\n            BINARY_SUBSCR_LIST_INT,\n            BINARY_SUBSCR_TUPLE_INT,\n        };\n\n        inst(BINARY_SUBSCR, (unused/1, container, sub -- res)) {\n            #if ENABLE_SPECIALIZATION\n            _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_BinarySubscr(container, sub, next_instr);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(BINARY_SUBSCR, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            res = PyObject_GetItem(container, sub);\n            DECREF_INPUTS();\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(BINARY_SLICE, (container, start, stop -- res)) {\n            PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop);\n            // Can't use ERROR_IF() here, because we haven't\n            // DECREF'ed container yet, and we still own slice.\n            if (slice == NULL) {\n                res = NULL;\n            }\n            else {\n                res = PyObject_GetItem(container, slice);\n                Py_DECREF(slice);\n            }\n            Py_DECREF(container);\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(STORE_SLICE, (v, container, start, stop -- )) {\n            PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop);\n            int err;\n            if (slice == NULL) {\n                err = 1;\n            }\n            else {\n                err = PyObject_SetItem(container, slice, v);\n                Py_DECREF(slice);\n            }\n            Py_DECREF(v);\n            Py_DECREF(container);\n            ERROR_IF(err, error);\n        }\n\n        inst(BINARY_SUBSCR_LIST_INT, (unused/1, list, sub -- res)) {\n            DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);\n            DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR);\n\n            // Deopt unless 0 <= sub < PyList_Size(list)\n            DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR);\n            Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];\n            DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR);\n            STAT_INC(BINARY_SUBSCR, hit);\n            res = PyList_GET_ITEM(list, index);\n            assert(res != NULL);\n            Py_INCREF(res);\n            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);\n            Py_DECREF(list);\n        }\n\n        inst(BINARY_SUBSCR_TUPLE_INT, (unused/1, tuple, sub -- res)) {\n            DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);\n            DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR);\n\n            // Deopt unless 0 <= sub < PyTuple_Size(list)\n            DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR);\n            Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];\n            DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR);\n            STAT_INC(BINARY_SUBSCR, hit);\n            res = PyTuple_GET_ITEM(tuple, index);\n            assert(res != NULL);\n            Py_INCREF(res);\n            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);\n            Py_DECREF(tuple);\n        }\n\n        inst(BINARY_SUBSCR_DICT, (unused/1, dict, sub -- res)) {\n            DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR);\n            STAT_INC(BINARY_SUBSCR, hit);\n            res = PyDict_GetItemWithError(dict, sub);\n            if (res == NULL) {\n                if (!_PyErr_Occurred(tstate)) {\n                    _PyErr_SetKeyError(sub);\n                }\n                DECREF_INPUTS();\n                ERROR_IF(true, error);\n            }\n            Py_INCREF(res);  // Do this before DECREF'ing dict, sub\n            DECREF_INPUTS();\n        }\n\n        inst(BINARY_SUBSCR_GETITEM, (unused/1, container, sub -- unused)) {\n            DEOPT_IF(tstate->interp->eval_frame, BINARY_SUBSCR);\n            PyTypeObject *tp = Py_TYPE(container);\n            DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE), BINARY_SUBSCR);\n            PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;\n            PyObject *cached = ht->_spec_cache.getitem;\n            DEOPT_IF(cached == NULL, BINARY_SUBSCR);\n            assert(PyFunction_Check(cached));\n            PyFunctionObject *getitem = (PyFunctionObject *)cached;\n            uint32_t cached_version = ht->_spec_cache.getitem_version;\n            DEOPT_IF(getitem->func_version != cached_version, BINARY_SUBSCR);\n            PyCodeObject *code = (PyCodeObject *)getitem->func_code;\n            assert(code->co_argcount == 2);\n            DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), BINARY_SUBSCR);\n            STAT_INC(BINARY_SUBSCR, hit);\n            Py_INCREF(getitem);\n            _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2);\n            STACK_SHRINK(2);\n            new_frame->localsplus[0] = container;\n            new_frame->localsplus[1] = sub;\n            JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);\n            frame->return_offset = 0;\n            DISPATCH_INLINED(new_frame);\n        }\n\n        inst(LIST_APPEND, (list, unused[oparg-1], v -- list, unused[oparg-1])) {\n            ERROR_IF(_PyList_AppendTakeRef((PyListObject *)list, v) < 0, error);\n        }\n\n        inst(SET_ADD, (set, unused[oparg-1], v -- set, unused[oparg-1])) {\n            int err = PySet_Add(set, v);\n            DECREF_INPUTS();\n            ERROR_IF(err, error);\n        }\n\n        family(store_subscr, INLINE_CACHE_ENTRIES_STORE_SUBSCR) = {\n            STORE_SUBSCR,\n            STORE_SUBSCR_DICT,\n            STORE_SUBSCR_LIST_INT,\n        };\n\n        inst(STORE_SUBSCR, (counter/1, v, container, sub -- )) {\n            #if ENABLE_SPECIALIZATION\n            if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {\n                next_instr--;\n                _Py_Specialize_StoreSubscr(container, sub, next_instr);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(STORE_SUBSCR, deferred);\n            _PyStoreSubscrCache *cache = (_PyStoreSubscrCache *)next_instr;\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #else\n            (void)counter;  // Unused.\n            #endif  /* ENABLE_SPECIALIZATION */\n            /* container[sub] = v */\n            int err = PyObject_SetItem(container, sub, v);\n            DECREF_INPUTS();\n            ERROR_IF(err, error);\n        }\n\n        inst(STORE_SUBSCR_LIST_INT, (unused/1, value, list, sub -- )) {\n            DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR);\n            DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR);\n\n            // Ensure nonnegative, zero-or-one-digit ints.\n            DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), STORE_SUBSCR);\n            Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];\n            // Ensure index < len(list)\n            DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR);\n            STAT_INC(STORE_SUBSCR, hit);\n\n            PyObject *old_value = PyList_GET_ITEM(list, index);\n            PyList_SET_ITEM(list, index, value);\n            assert(old_value != NULL);\n            Py_DECREF(old_value);\n            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);\n            Py_DECREF(list);\n        }\n\n        inst(STORE_SUBSCR_DICT, (unused/1, value, dict, sub -- )) {\n            DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR);\n            STAT_INC(STORE_SUBSCR, hit);\n            int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value);\n            Py_DECREF(dict);\n            ERROR_IF(err, error);\n        }\n\n        inst(DELETE_SUBSCR, (container, sub --)) {\n            /* del container[sub] */\n            int err = PyObject_DelItem(container, sub);\n            DECREF_INPUTS();\n            ERROR_IF(err, error);\n        }\n\n        inst(CALL_INTRINSIC_1, (value -- res)) {\n            assert(oparg <= MAX_INTRINSIC_1);\n            res = _PyIntrinsics_UnaryFunctions[oparg](tstate, value);\n            DECREF_INPUTS();\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(CALL_INTRINSIC_2, (value2, value1 -- res)) {\n            assert(oparg <= MAX_INTRINSIC_2);\n            res = _PyIntrinsics_BinaryFunctions[oparg](tstate, value2, value1);\n            DECREF_INPUTS();\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(RAISE_VARARGS, (args[oparg] -- )) {\n            PyObject *cause = NULL, *exc = NULL;\n            switch (oparg) {\n            case 2:\n                cause = args[1];\n                /* fall through */\n            case 1:\n                exc = args[0];\n                /* fall through */\n            case 0:\n                ERROR_IF(do_raise(tstate, exc, cause), exception_unwind);\n                break;\n            default:\n                _PyErr_SetString(tstate, PyExc_SystemError,\n                                 \"bad RAISE_VARARGS oparg\");\n                break;\n            }\n            ERROR_IF(true, error);\n        }\n\n        inst(INTERPRETER_EXIT, (retval --)) {\n            assert(frame == &entry_frame);\n            assert(_PyFrame_IsIncomplete(frame));\n            STACK_SHRINK(1);  // Since we're not going to DISPATCH()\n            assert(EMPTY());\n            /* Restore previous cframe and return. */\n            tstate->cframe = cframe.previous;\n            assert(tstate->cframe->current_frame == frame->previous);\n            assert(!_PyErr_Occurred(tstate));\n            _Py_LeaveRecursiveCallTstate(tstate);\n            return retval;\n        }\n\n        inst(RETURN_VALUE, (retval --)) {\n            STACK_SHRINK(1);\n            assert(EMPTY());\n            _PyFrame_SetStackPointer(frame, stack_pointer);\n            _Py_LeaveRecursiveCallPy(tstate);\n            assert(frame != &entry_frame);\n            // GH-99729: We need to unlink the frame *before* clearing it:\n            _PyInterpreterFrame *dying = frame;\n            frame = cframe.current_frame = dying->previous;\n            _PyEvalFrameClearAndPop(tstate, dying);\n            frame->prev_instr += frame->return_offset;\n            _PyFrame_StackPush(frame, retval);\n            goto resume_frame;\n        }\n\n        inst(INSTRUMENTED_RETURN_VALUE, (retval --)) {\n            int err = _Py_call_instrumentation_arg(\n                    tstate, PY_MONITORING_EVENT_PY_RETURN,\n                    frame, next_instr-1, retval);\n            if (err) goto error;\n            STACK_SHRINK(1);\n            assert(EMPTY());\n            _PyFrame_SetStackPointer(frame, stack_pointer);\n            _Py_LeaveRecursiveCallPy(tstate);\n            assert(frame != &entry_frame);\n            // GH-99729: We need to unlink the frame *before* clearing it:\n            _PyInterpreterFrame *dying = frame;\n            frame = cframe.current_frame = dying->previous;\n            _PyEvalFrameClearAndPop(tstate, dying);\n            frame->prev_instr += frame->return_offset;\n            _PyFrame_StackPush(frame, retval);\n            goto resume_frame;\n        }\n\n        inst(RETURN_CONST, (--)) {\n            PyObject *retval = GETITEM(frame->f_code->co_consts, oparg);\n            Py_INCREF(retval);\n            assert(EMPTY());\n            _PyFrame_SetStackPointer(frame, stack_pointer);\n            _Py_LeaveRecursiveCallPy(tstate);\n            assert(frame != &entry_frame);\n            // GH-99729: We need to unlink the frame *before* clearing it:\n            _PyInterpreterFrame *dying = frame;\n            frame = cframe.current_frame = dying->previous;\n            _PyEvalFrameClearAndPop(tstate, dying);\n            frame->prev_instr += frame->return_offset;\n            _PyFrame_StackPush(frame, retval);\n            goto resume_frame;\n        }\n\n        inst(INSTRUMENTED_RETURN_CONST, (--)) {\n            PyObject *retval = GETITEM(frame->f_code->co_consts, oparg);\n            int err = _Py_call_instrumentation_arg(\n                    tstate, PY_MONITORING_EVENT_PY_RETURN,\n                    frame, next_instr-1, retval);\n            if (err) goto error;\n            Py_INCREF(retval);\n            assert(EMPTY());\n            _PyFrame_SetStackPointer(frame, stack_pointer);\n            _Py_LeaveRecursiveCallPy(tstate);\n            assert(frame != &entry_frame);\n            // GH-99729: We need to unlink the frame *before* clearing it:\n            _PyInterpreterFrame *dying = frame;\n            frame = cframe.current_frame = dying->previous;\n            _PyEvalFrameClearAndPop(tstate, dying);\n            frame->prev_instr += frame->return_offset;\n            _PyFrame_StackPush(frame, retval);\n            goto resume_frame;\n        }\n\n        inst(GET_AITER, (obj -- iter)) {\n            unaryfunc getter = NULL;\n            PyTypeObject *type = Py_TYPE(obj);\n\n            if (type->tp_as_async != NULL) {\n                getter = type->tp_as_async->am_aiter;\n            }\n\n            if (getter == NULL) {\n                _PyErr_Format(tstate, PyExc_TypeError,\n                              \"'async for' requires an object with \"\n                              \"__aiter__ method, got %.100s\",\n                              type->tp_name);\n                DECREF_INPUTS();\n                ERROR_IF(true, error);\n            }\n\n            iter = (*getter)(obj);\n            DECREF_INPUTS();\n            ERROR_IF(iter == NULL, error);\n\n            if (Py_TYPE(iter)->tp_as_async == NULL ||\n                    Py_TYPE(iter)->tp_as_async->am_anext == NULL) {\n\n                _PyErr_Format(tstate, PyExc_TypeError,\n                              \"'async for' received an object from __aiter__ \"\n                              \"that does not implement __anext__: %.100s\",\n                              Py_TYPE(iter)->tp_name);\n                Py_DECREF(iter);\n                ERROR_IF(true, error);\n            }\n        }\n\n        inst(GET_ANEXT, (aiter -- aiter, awaitable)) {\n            unaryfunc getter = NULL;\n            PyObject *next_iter = NULL;\n            PyTypeObject *type = Py_TYPE(aiter);\n\n            if (PyAsyncGen_CheckExact(aiter)) {\n                awaitable = type->tp_as_async->am_anext(aiter);\n                if (awaitable == NULL) {\n                    goto error;\n                }\n            } else {\n                if (type->tp_as_async != NULL){\n                    getter = type->tp_as_async->am_anext;\n                }\n\n                if (getter != NULL) {\n                    next_iter = (*getter)(aiter);\n                    if (next_iter == NULL) {\n                        goto error;\n                    }\n                }\n                else {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                  \"'async for' requires an iterator with \"\n                                  \"__anext__ method, got %.100s\",\n                                  type->tp_name);\n                    goto error;\n                }\n\n                awaitable = _PyCoro_GetAwaitableIter(next_iter);\n                if (awaitable == NULL) {\n                    _PyErr_FormatFromCause(\n                        PyExc_TypeError,\n                        \"'async for' received an invalid object \"\n                        \"from __anext__: %.100s\",\n                        Py_TYPE(next_iter)->tp_name);\n\n                    Py_DECREF(next_iter);\n                    goto error;\n                } else {\n                    Py_DECREF(next_iter);\n                }\n            }\n        }\n\n        inst(GET_AWAITABLE, (iterable -- iter)) {\n            iter = _PyCoro_GetAwaitableIter(iterable);\n\n            if (iter == NULL) {\n                format_awaitable_error(tstate, Py_TYPE(iterable), oparg);\n            }\n\n            DECREF_INPUTS();\n\n            if (iter != NULL && PyCoro_CheckExact(iter)) {\n                PyObject *yf = _PyGen_yf((PyGenObject*)iter);\n                if (yf != NULL) {\n                    /* `iter` is a coroutine object that is being\n                       awaited, `yf` is a pointer to the current awaitable\n                       being awaited on. */\n                    Py_DECREF(yf);\n                    Py_CLEAR(iter);\n                    _PyErr_SetString(tstate, PyExc_RuntimeError,\n                                     \"coroutine is being awaited already\");\n                    /* The code below jumps to `error` if `iter` is NULL. */\n                }\n            }\n\n            ERROR_IF(iter == NULL, error);\n        }\n\n        family(send, INLINE_CACHE_ENTRIES_SEND) = {\n            SEND,\n            SEND_GEN,\n        };\n\n        inst(SEND, (unused/1, receiver, v -- receiver, retval)) {\n            #if ENABLE_SPECIALIZATION\n            _PySendCache *cache = (_PySendCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_Send(receiver, next_instr);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(SEND, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            assert(frame != &entry_frame);\n            if ((tstate->interp->eval_frame == NULL) &&\n                (Py_TYPE(receiver) == &PyGen_Type || Py_TYPE(receiver) == &PyCoro_Type) &&\n                ((PyGenObject *)receiver)->gi_frame_state < FRAME_EXECUTING)\n            {\n                PyGenObject *gen = (PyGenObject *)receiver;\n                _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;\n                frame->return_offset = oparg;\n                STACK_SHRINK(1);\n                _PyFrame_StackPush(gen_frame, v);\n                gen->gi_frame_state = FRAME_EXECUTING;\n                gen->gi_exc_state.previous_item = tstate->exc_info;\n                tstate->exc_info = &gen->gi_exc_state;\n                JUMPBY(INLINE_CACHE_ENTRIES_SEND);\n                DISPATCH_INLINED(gen_frame);\n            }\n            if (Py_IsNone(v) && PyIter_Check(receiver)) {\n                retval = Py_TYPE(receiver)->tp_iternext(receiver);\n            }\n            else {\n                retval = PyObject_CallMethodOneArg(receiver, &_Py_ID(send), v);\n            }\n            if (retval == NULL) {\n                if (_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)\n                ) {\n                    monitor_raise(tstate, frame, next_instr-1);\n                }\n                if (_PyGen_FetchStopIterationValue(&retval) == 0) {\n                    assert(retval != NULL);\n                    JUMPBY(oparg);\n                }\n                else {\n                    goto error;\n                }\n            }\n            Py_DECREF(v);\n        }\n\n        inst(SEND_GEN, (unused/1, receiver, v -- receiver, unused)) {\n            DEOPT_IF(tstate->interp->eval_frame, SEND);\n            PyGenObject *gen = (PyGenObject *)receiver;\n            DEOPT_IF(Py_TYPE(gen) != &PyGen_Type &&\n                     Py_TYPE(gen) != &PyCoro_Type, SEND);\n            DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, SEND);\n            STAT_INC(SEND, hit);\n            _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;\n            frame->return_offset = oparg;\n            STACK_SHRINK(1);\n            _PyFrame_StackPush(gen_frame, v);\n            gen->gi_frame_state = FRAME_EXECUTING;\n            gen->gi_exc_state.previous_item = tstate->exc_info;\n            tstate->exc_info = &gen->gi_exc_state;\n            JUMPBY(INLINE_CACHE_ENTRIES_SEND);\n            DISPATCH_INLINED(gen_frame);\n        }\n\n        inst(INSTRUMENTED_YIELD_VALUE, (retval -- unused)) {\n            assert(frame != &entry_frame);\n            PyGenObject *gen = _PyFrame_GetGenerator(frame);\n            gen->gi_frame_state = FRAME_SUSPENDED;\n            _PyFrame_SetStackPointer(frame, stack_pointer - 1);\n            int err = _Py_call_instrumentation_arg(\n                    tstate, PY_MONITORING_EVENT_PY_YIELD,\n                    frame, next_instr-1, retval);\n            if (err) goto error;\n            tstate->exc_info = gen->gi_exc_state.previous_item;\n            gen->gi_exc_state.previous_item = NULL;\n            _Py_LeaveRecursiveCallPy(tstate);\n            _PyInterpreterFrame *gen_frame = frame;\n            frame = cframe.current_frame = frame->previous;\n            gen_frame->previous = NULL;\n            _PyFrame_StackPush(frame, retval);\n            goto resume_frame;\n        }\n\n        inst(YIELD_VALUE, (retval -- unused)) {\n            // NOTE: It's important that YIELD_VALUE never raises an exception!\n            // The compiler treats any exception raised here as a failed close()\n            // or throw() call.\n            assert(frame != &entry_frame);\n            PyGenObject *gen = _PyFrame_GetGenerator(frame);\n            gen->gi_frame_state = FRAME_SUSPENDED;\n            _PyFrame_SetStackPointer(frame, stack_pointer - 1);\n            tstate->exc_info = gen->gi_exc_state.previous_item;\n            gen->gi_exc_state.previous_item = NULL;\n            _Py_LeaveRecursiveCallPy(tstate);\n            _PyInterpreterFrame *gen_frame = frame;\n            frame = cframe.current_frame = frame->previous;\n            gen_frame->previous = NULL;\n            _PyFrame_StackPush(frame, retval);\n            goto resume_frame;\n        }\n\n        inst(POP_EXCEPT, (exc_value -- )) {\n            _PyErr_StackItem *exc_info = tstate->exc_info;\n            Py_XSETREF(exc_info->exc_value, exc_value);\n        }\n\n        inst(RERAISE, (values[oparg], exc -- values[oparg])) {\n            assert(oparg >= 0 && oparg <= 2);\n            if (oparg) {\n                PyObject *lasti = values[0];\n                if (PyLong_Check(lasti)) {\n                    frame->prev_instr = _PyCode_CODE(frame->f_code) + PyLong_AsLong(lasti);\n                    assert(!_PyErr_Occurred(tstate));\n                }\n                else {\n                    assert(PyLong_Check(lasti));\n                    _PyErr_SetString(tstate, PyExc_SystemError, \"lasti is not an int\");\n                    goto error;\n                }\n            }\n            assert(exc && PyExceptionInstance_Check(exc));\n            Py_INCREF(exc);\n            _PyErr_SetRaisedException(tstate, exc);\n            goto exception_unwind;\n        }\n\n        inst(END_ASYNC_FOR, (awaitable, exc -- )) {\n            assert(exc && PyExceptionInstance_Check(exc));\n            if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) {\n                DECREF_INPUTS();\n            }\n            else {\n                Py_INCREF(exc);\n                _PyErr_SetRaisedException(tstate, exc);\n                goto exception_unwind;\n            }\n        }\n\n        inst(CLEANUP_THROW, (sub_iter, last_sent_val, exc_value -- none, value)) {\n            assert(throwflag);\n            assert(exc_value && PyExceptionInstance_Check(exc_value));\n            if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) {\n                value = Py_NewRef(((PyStopIterationObject *)exc_value)->value);\n                DECREF_INPUTS();\n                none = Py_None;\n            }\n            else {\n                _PyErr_SetRaisedException(tstate, Py_NewRef(exc_value));\n                goto exception_unwind;\n            }\n        }\n\n        inst(LOAD_ASSERTION_ERROR, ( -- value)) {\n            value = Py_NewRef(PyExc_AssertionError);\n        }\n\n        inst(LOAD_BUILD_CLASS, ( -- bc)) {\n            if (PyDict_CheckExact(BUILTINS())) {\n                bc = _PyDict_GetItemWithError(BUILTINS(),\n                                              &_Py_ID(__build_class__));\n                if (bc == NULL) {\n                    if (!_PyErr_Occurred(tstate)) {\n                        _PyErr_SetString(tstate, PyExc_NameError,\n                                         \"__build_class__ not found\");\n                    }\n                    ERROR_IF(true, error);\n                }\n                Py_INCREF(bc);\n            }\n            else {\n                bc = PyObject_GetItem(BUILTINS(), &_Py_ID(__build_class__));\n                if (bc == NULL) {\n                    if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError))\n                        _PyErr_SetString(tstate, PyExc_NameError,\n                                         \"__build_class__ not found\");\n                    ERROR_IF(true, error);\n                }\n            }\n        }\n\n\n        inst(STORE_NAME, (v -- )) {\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            PyObject *ns = LOCALS();\n            int err;\n            if (ns == NULL) {\n                _PyErr_Format(tstate, PyExc_SystemError,\n                              \"no locals found when storing %R\", name);\n                DECREF_INPUTS();\n                ERROR_IF(true, error);\n            }\n            if (PyDict_CheckExact(ns))\n                err = PyDict_SetItem(ns, name, v);\n            else\n                err = PyObject_SetItem(ns, name, v);\n            DECREF_INPUTS();\n            ERROR_IF(err, error);\n        }\n\n        inst(DELETE_NAME, (--)) {\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            PyObject *ns = LOCALS();\n            int err;\n            if (ns == NULL) {\n                _PyErr_Format(tstate, PyExc_SystemError,\n                              \"no locals when deleting %R\", name);\n                goto error;\n            }\n            err = PyObject_DelItem(ns, name);\n            // Can't use ERROR_IF here.\n            if (err != 0) {\n                format_exc_check_arg(tstate, PyExc_NameError,\n                                     NAME_ERROR_MSG,\n                                     name);\n                goto error;\n            }\n        }\n\n        family(unpack_sequence, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = {\n            UNPACK_SEQUENCE,\n            UNPACK_SEQUENCE_TWO_TUPLE,\n            UNPACK_SEQUENCE_TUPLE,\n            UNPACK_SEQUENCE_LIST,\n        };\n\n        inst(UNPACK_SEQUENCE, (unused/1, seq -- unused[oparg])) {\n            #if ENABLE_SPECIALIZATION\n            _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_UnpackSequence(seq, next_instr, oparg);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(UNPACK_SEQUENCE, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            PyObject **top = stack_pointer + oparg - 1;\n            int res = unpack_iterable(tstate, seq, oparg, -1, top);\n            DECREF_INPUTS();\n            ERROR_IF(res == 0, error);\n        }\n\n        inst(UNPACK_SEQUENCE_TWO_TUPLE, (unused/1, seq -- values[oparg])) {\n            DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE);\n            DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE);\n            assert(oparg == 2);\n            STAT_INC(UNPACK_SEQUENCE, hit);\n            values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1));\n            values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0));\n            DECREF_INPUTS();\n        }\n\n        inst(UNPACK_SEQUENCE_TUPLE, (unused/1, seq -- values[oparg])) {\n            DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE);\n            DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE);\n            STAT_INC(UNPACK_SEQUENCE, hit);\n            PyObject **items = _PyTuple_ITEMS(seq);\n            for (int i = oparg; --i >= 0; ) {\n                *values++ = Py_NewRef(items[i]);\n            }\n            DECREF_INPUTS();\n        }\n\n        inst(UNPACK_SEQUENCE_LIST, (unused/1, seq -- values[oparg])) {\n            DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE);\n            DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE);\n            STAT_INC(UNPACK_SEQUENCE, hit);\n            PyObject **items = _PyList_ITEMS(seq);\n            for (int i = oparg; --i >= 0; ) {\n                *values++ = Py_NewRef(items[i]);\n            }\n            DECREF_INPUTS();\n        }\n\n        inst(UNPACK_EX, (seq -- unused[oparg & 0xFF], unused, unused[oparg >> 8])) {\n            int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8);\n            PyObject **top = stack_pointer + totalargs - 1;\n            int res = unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, top);\n            DECREF_INPUTS();\n            ERROR_IF(res == 0, error);\n        }\n\n        family(store_attr, INLINE_CACHE_ENTRIES_STORE_ATTR) = {\n            STORE_ATTR,\n            STORE_ATTR_INSTANCE_VALUE,\n            STORE_ATTR_SLOT,\n            STORE_ATTR_WITH_HINT,\n        };\n\n        inst(STORE_ATTR, (counter/1, unused/3, v, owner --)) {\n            #if ENABLE_SPECIALIZATION\n            if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {\n                PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n                next_instr--;\n                _Py_Specialize_StoreAttr(owner, next_instr, name);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(STORE_ATTR, deferred);\n            _PyAttrCache *cache = (_PyAttrCache *)next_instr;\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #else\n            (void)counter;  // Unused.\n            #endif  /* ENABLE_SPECIALIZATION */\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            int err = PyObject_SetAttr(owner, name, v);\n            DECREF_INPUTS();\n            ERROR_IF(err, error);\n        }\n\n        inst(DELETE_ATTR, (owner --)) {\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            int err = PyObject_SetAttr(owner, name, (PyObject *)NULL);\n            DECREF_INPUTS();\n            ERROR_IF(err, error);\n        }\n\n        inst(STORE_GLOBAL, (v --)) {\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            int err = PyDict_SetItem(GLOBALS(), name, v);\n            DECREF_INPUTS();\n            ERROR_IF(err, error);\n        }\n\n        inst(DELETE_GLOBAL, (--)) {\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            int err;\n            err = PyDict_DelItem(GLOBALS(), name);\n            // Can't use ERROR_IF here.\n            if (err != 0) {\n                if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n                    format_exc_check_arg(tstate, PyExc_NameError,\n                                         NAME_ERROR_MSG, name);\n                }\n                goto error;\n            }\n        }\n\n        op(_LOAD_LOCALS, ( -- locals)) {\n            locals = LOCALS();\n            if (locals == NULL) {\n                _PyErr_SetString(tstate, PyExc_SystemError,\n                                 \"no locals found\");\n                ERROR_IF(true, error);\n            }\n            Py_INCREF(locals);\n        }\n\n        macro(LOAD_LOCALS) = _LOAD_LOCALS;\n\n        op(_LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) {\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            if (PyDict_CheckExact(mod_or_class_dict)) {\n                v = PyDict_GetItemWithError(mod_or_class_dict, name);\n                if (v != NULL) {\n                    Py_INCREF(v);\n                }\n                else if (_PyErr_Occurred(tstate)) {\n                    Py_DECREF(mod_or_class_dict);\n                    goto error;\n                }\n            }\n            else {\n                v = PyObject_GetItem(mod_or_class_dict, name);\n                if (v == NULL) {\n                    if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n                        Py_DECREF(mod_or_class_dict);\n                        goto error;\n                    }\n                    _PyErr_Clear(tstate);\n                }\n            }\n            Py_DECREF(mod_or_class_dict);\n            if (v == NULL) {\n                v = PyDict_GetItemWithError(GLOBALS(), name);\n                if (v != NULL) {\n                    Py_INCREF(v);\n                }\n                else if (_PyErr_Occurred(tstate)) {\n                    goto error;\n                }\n                else {\n                    if (PyDict_CheckExact(BUILTINS())) {\n                        v = PyDict_GetItemWithError(BUILTINS(), name);\n                        if (v == NULL) {\n                            if (!_PyErr_Occurred(tstate)) {\n                                format_exc_check_arg(\n                                        tstate, PyExc_NameError,\n                                        NAME_ERROR_MSG, name);\n                            }\n                            goto error;\n                        }\n                        Py_INCREF(v);\n                    }\n                    else {\n                        v = PyObject_GetItem(BUILTINS(), name);\n                        if (v == NULL) {\n                            if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n                                format_exc_check_arg(\n                                            tstate, PyExc_NameError,\n                                            NAME_ERROR_MSG, name);\n                            }\n                            goto error;\n                        }\n                    }\n                }\n            }\n        }\n\n        macro(LOAD_NAME) = _LOAD_LOCALS + _LOAD_FROM_DICT_OR_GLOBALS;\n\n        macro(LOAD_FROM_DICT_OR_GLOBALS) = _LOAD_FROM_DICT_OR_GLOBALS;\n\n        family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = {\n            LOAD_GLOBAL,\n            LOAD_GLOBAL_MODULE,\n            LOAD_GLOBAL_BUILTIN,\n        };\n\n        inst(LOAD_GLOBAL, (unused/1, unused/1, unused/1, unused/1 -- null if (oparg & 1), v)) {\n            #if ENABLE_SPECIALIZATION\n            _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);\n                next_instr--;\n                _Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(LOAD_GLOBAL, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);\n            if (PyDict_CheckExact(GLOBALS())\n                && PyDict_CheckExact(BUILTINS()))\n            {\n                v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(),\n                                       (PyDictObject *)BUILTINS(),\n                                       name);\n                if (v == NULL) {\n                    if (!_PyErr_Occurred(tstate)) {\n                        /* _PyDict_LoadGlobal() returns NULL without raising\n                         * an exception if the key doesn't exist */\n                        format_exc_check_arg(tstate, PyExc_NameError,\n                                             NAME_ERROR_MSG, name);\n                    }\n                    ERROR_IF(true, error);\n                }\n                Py_INCREF(v);\n            }\n            else {\n                /* Slow-path if globals or builtins is not a dict */\n\n                /* namespace 1: globals */\n                v = PyObject_GetItem(GLOBALS(), name);\n                if (v == NULL) {\n                    ERROR_IF(!_PyErr_ExceptionMatches(tstate, PyExc_KeyError), error);\n                    _PyErr_Clear(tstate);\n\n                    /* namespace 2: builtins */\n                    v = PyObject_GetItem(BUILTINS(), name);\n                    if (v == NULL) {\n                        if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n                            format_exc_check_arg(\n                                        tstate, PyExc_NameError,\n                                        NAME_ERROR_MSG, name);\n                        }\n                        ERROR_IF(true, error);\n                    }\n                }\n            }\n            null = NULL;\n        }\n\n        inst(LOAD_GLOBAL_MODULE, (unused/1, index/1, version/1, unused/1 -- null if (oparg & 1), res)) {\n            DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);\n            PyDictObject *dict = (PyDictObject *)GLOBALS();\n            DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);\n            assert(DK_IS_UNICODE(dict->ma_keys));\n            PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);\n            res = entries[index].me_value;\n            DEOPT_IF(res == NULL, LOAD_GLOBAL);\n            Py_INCREF(res);\n            STAT_INC(LOAD_GLOBAL, hit);\n            null = NULL;\n        }\n\n        inst(LOAD_GLOBAL_BUILTIN, (unused/1, index/1, mod_version/1, bltn_version/1 -- null if (oparg & 1), res)) {\n            DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);\n            DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL);\n            PyDictObject *mdict = (PyDictObject *)GLOBALS();\n            PyDictObject *bdict = (PyDictObject *)BUILTINS();\n            assert(opcode == LOAD_GLOBAL_BUILTIN);\n            DEOPT_IF(mdict->ma_keys->dk_version != mod_version, LOAD_GLOBAL);\n            DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL);\n            assert(DK_IS_UNICODE(bdict->ma_keys));\n            PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys);\n            res = entries[index].me_value;\n            DEOPT_IF(res == NULL, LOAD_GLOBAL);\n            Py_INCREF(res);\n            STAT_INC(LOAD_GLOBAL, hit);\n            null = NULL;\n        }\n\n        inst(DELETE_FAST, (--)) {\n            PyObject *v = GETLOCAL(oparg);\n            ERROR_IF(v == NULL, unbound_local_error);\n            SETLOCAL(oparg, NULL);\n        }\n\n        inst(MAKE_CELL, (--)) {\n            // \"initial\" is probably NULL but not if it's an arg (or set\n            // via PyFrame_LocalsToFast() before MAKE_CELL has run).\n            PyObject *initial = GETLOCAL(oparg);\n            PyObject *cell = PyCell_New(initial);\n            if (cell == NULL) {\n                goto resume_with_error;\n            }\n            SETLOCAL(oparg, cell);\n        }\n\n        inst(DELETE_DEREF, (--)) {\n            PyObject *cell = GETLOCAL(oparg);\n            PyObject *oldobj = PyCell_GET(cell);\n            // Can't use ERROR_IF here.\n            // Fortunately we don't need its superpower.\n            if (oldobj == NULL) {\n                format_exc_unbound(tstate, frame->f_code, oparg);\n                goto error;\n            }\n            PyCell_SET(cell, NULL);\n            Py_DECREF(oldobj);\n        }\n\n        inst(LOAD_FROM_DICT_OR_DEREF, (class_dict -- value)) {\n            PyObject *name;\n            assert(class_dict);\n            assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus);\n            name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg);\n            if (PyDict_CheckExact(class_dict)) {\n                value = PyDict_GetItemWithError(class_dict, name);\n                if (value != NULL) {\n                    Py_INCREF(value);\n                }\n                else if (_PyErr_Occurred(tstate)) {\n                    Py_DECREF(class_dict);\n                    goto error;\n                }\n            }\n            else {\n                value = PyObject_GetItem(class_dict, name);\n                if (value == NULL) {\n                    if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n                        Py_DECREF(class_dict);\n                        goto error;\n                    }\n                    _PyErr_Clear(tstate);\n                }\n            }\n            Py_DECREF(class_dict);\n            if (!value) {\n                PyObject *cell = GETLOCAL(oparg);\n                value = PyCell_GET(cell);\n                if (value == NULL) {\n                    format_exc_unbound(tstate, frame->f_code, oparg);\n                    goto error;\n                }\n                Py_INCREF(value);\n            }\n        }\n\n        inst(LOAD_DEREF, ( -- value)) {\n            PyObject *cell = GETLOCAL(oparg);\n            value = PyCell_GET(cell);\n            if (value == NULL) {\n                format_exc_unbound(tstate, frame->f_code, oparg);\n                ERROR_IF(true, error);\n            }\n            Py_INCREF(value);\n        }\n\n        inst(STORE_DEREF, (v --)) {\n            PyObject *cell = GETLOCAL(oparg);\n            PyObject *oldobj = PyCell_GET(cell);\n            PyCell_SET(cell, v);\n            Py_XDECREF(oldobj);\n        }\n\n        inst(COPY_FREE_VARS, (--)) {\n            /* Copy closure variables to free variables */\n            PyCodeObject *co = frame->f_code;\n            assert(PyFunction_Check(frame->f_funcobj));\n            PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;\n            assert(oparg == co->co_nfreevars);\n            int offset = co->co_nlocalsplus - oparg;\n            for (int i = 0; i < oparg; ++i) {\n                PyObject *o = PyTuple_GET_ITEM(closure, i);\n                frame->localsplus[offset + i] = Py_NewRef(o);\n            }\n        }\n\n        inst(BUILD_STRING, (pieces[oparg] -- str)) {\n            str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg);\n            DECREF_INPUTS();\n            ERROR_IF(str == NULL, error);\n        }\n\n        inst(BUILD_TUPLE, (values[oparg] -- tup)) {\n            tup = _PyTuple_FromArraySteal(values, oparg);\n            ERROR_IF(tup == NULL, error);\n        }\n\n        inst(BUILD_LIST, (values[oparg] -- list)) {\n            list = _PyList_FromArraySteal(values, oparg);\n            ERROR_IF(list == NULL, error);\n        }\n\n        inst(LIST_EXTEND, (list, unused[oparg-1], iterable -- list, unused[oparg-1])) {\n            PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable);\n            if (none_val == NULL) {\n                if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&\n                   (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable)))\n                {\n                    _PyErr_Clear(tstate);\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                          \"Value after * must be an iterable, not %.200s\",\n                          Py_TYPE(iterable)->tp_name);\n                }\n                DECREF_INPUTS();\n                ERROR_IF(true, error);\n            }\n            assert(Py_IsNone(none_val));\n            DECREF_INPUTS();\n        }\n\n        inst(SET_UPDATE, (set, unused[oparg-1], iterable -- set, unused[oparg-1])) {\n            int err = _PySet_Update(set, iterable);\n            DECREF_INPUTS();\n            ERROR_IF(err < 0, error);\n        }\n\n        inst(BUILD_SET, (values[oparg] -- set)) {\n            set = PySet_New(NULL);\n            if (set == NULL)\n                goto error;\n            int err = 0;\n            for (int i = 0; i < oparg; i++) {\n                PyObject *item = values[i];\n                if (err == 0)\n                    err = PySet_Add(set, item);\n                Py_DECREF(item);\n            }\n            if (err != 0) {\n                Py_DECREF(set);\n                ERROR_IF(true, error);\n            }\n        }\n\n        inst(BUILD_MAP, (values[oparg*2] -- map)) {\n            map = _PyDict_FromItems(\n                    values, 2,\n                    values+1, 2,\n                    oparg);\n            if (map == NULL)\n                goto error;\n\n            DECREF_INPUTS();\n            ERROR_IF(map == NULL, error);\n        }\n\n        inst(SETUP_ANNOTATIONS, (--)) {\n            int err;\n            PyObject *ann_dict;\n            if (LOCALS() == NULL) {\n                _PyErr_Format(tstate, PyExc_SystemError,\n                              \"no locals found when setting up annotations\");\n                ERROR_IF(true, error);\n            }\n            /* check if __annotations__ in locals()... */\n            if (PyDict_CheckExact(LOCALS())) {\n                ann_dict = _PyDict_GetItemWithError(LOCALS(),\n                                                    &_Py_ID(__annotations__));\n                if (ann_dict == NULL) {\n                    ERROR_IF(_PyErr_Occurred(tstate), error);\n                    /* ...if not, create a new one */\n                    ann_dict = PyDict_New();\n                    ERROR_IF(ann_dict == NULL, error);\n                    err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__),\n                                         ann_dict);\n                    Py_DECREF(ann_dict);\n                    ERROR_IF(err, error);\n                }\n            }\n            else {\n                /* do the same if locals() is not a dict */\n                ann_dict = PyObject_GetItem(LOCALS(), &_Py_ID(__annotations__));\n                if (ann_dict == NULL) {\n                    ERROR_IF(!_PyErr_ExceptionMatches(tstate, PyExc_KeyError), error);\n                    _PyErr_Clear(tstate);\n                    ann_dict = PyDict_New();\n                    ERROR_IF(ann_dict == NULL, error);\n                    err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__),\n                                           ann_dict);\n                    Py_DECREF(ann_dict);\n                    ERROR_IF(err, error);\n                }\n                else {\n                    Py_DECREF(ann_dict);\n                }\n            }\n        }\n\n        inst(BUILD_CONST_KEY_MAP, (values[oparg], keys -- map)) {\n            if (!PyTuple_CheckExact(keys) ||\n                PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) {\n                _PyErr_SetString(tstate, PyExc_SystemError,\n                                 \"bad BUILD_CONST_KEY_MAP keys argument\");\n                goto error;  // Pop the keys and values.\n            }\n            map = _PyDict_FromItems(\n                    &PyTuple_GET_ITEM(keys, 0), 1,\n                    values, 1, oparg);\n            DECREF_INPUTS();\n            ERROR_IF(map == NULL, error);\n        }\n\n        inst(DICT_UPDATE, (update --)) {\n            PyObject *dict = PEEK(oparg + 1);  // update is still on the stack\n            if (PyDict_Update(dict, update) < 0) {\n                if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                    \"'%.200s' object is not a mapping\",\n                                    Py_TYPE(update)->tp_name);\n                }\n                DECREF_INPUTS();\n                ERROR_IF(true, error);\n            }\n            DECREF_INPUTS();\n        }\n\n        inst(DICT_MERGE, (update --)) {\n            PyObject *dict = PEEK(oparg + 1);  // update is still on the stack\n\n            if (_PyDict_MergeEx(dict, update, 2) < 0) {\n                format_kwargs_error(tstate, PEEK(3 + oparg), update);\n                DECREF_INPUTS();\n                ERROR_IF(true, error);\n            }\n            DECREF_INPUTS();\n        }\n\n        inst(MAP_ADD, (key, value --)) {\n            PyObject *dict = PEEK(oparg + 2);  // key, value are still on the stack\n            assert(PyDict_CheckExact(dict));\n            /* dict[key] = value */\n            // Do not DECREF INPUTS because the function steals the references\n            ERROR_IF(_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0, error);\n        }\n\n        inst(INSTRUMENTED_LOAD_SUPER_ATTR, (unused/9, unused, unused, unused -- unused if (oparg & 1), unused)) {\n            _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr;\n            // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we\n            // don't want to specialize instrumented instructions\n            INCREMENT_ADAPTIVE_COUNTER(cache->counter);\n            GO_TO_INSTRUCTION(LOAD_SUPER_ATTR);\n        }\n\n        family(load_super_attr, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {\n            LOAD_SUPER_ATTR,\n            LOAD_SUPER_ATTR_ATTR,\n            LOAD_SUPER_ATTR_METHOD,\n        };\n\n        inst(LOAD_SUPER_ATTR, (unused/1, global_super, class, self -- res2 if (oparg & 1), res)) {\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);\n            int load_method = oparg & 1;\n            #if ENABLE_SPECIALIZATION\n            _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_LoadSuperAttr(global_super, class, next_instr, load_method);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(LOAD_SUPER_ATTR, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n\n            if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {\n                PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;\n                int err = _Py_call_instrumentation_2args(\n                        tstate, PY_MONITORING_EVENT_CALL,\n                        frame, next_instr-1, global_super, arg);\n                ERROR_IF(err, error);\n            }\n\n            // we make no attempt to optimize here; specializations should\n            // handle any case whose performance we care about\n            PyObject *stack[] = {class, self};\n            PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL);\n            if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {\n                PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;\n                if (super == NULL) {\n                    _Py_call_instrumentation_exc2(\n                        tstate, PY_MONITORING_EVENT_C_RAISE,\n                        frame, next_instr-1, global_super, arg);\n                }\n                else {\n                    int err = _Py_call_instrumentation_2args(\n                        tstate, PY_MONITORING_EVENT_C_RETURN,\n                        frame, next_instr-1, global_super, arg);\n                    if (err < 0) {\n                        Py_CLEAR(super);\n                    }\n                }\n            }\n            DECREF_INPUTS();\n            ERROR_IF(super == NULL, error);\n            res = PyObject_GetAttr(super, name);\n            Py_DECREF(super);\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super, class, self -- res2 if (oparg & 1), res)) {\n            assert(!(oparg & 1));\n            DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);\n            DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);\n            STAT_INC(LOAD_SUPER_ATTR, hit);\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);\n            res = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL);\n            DECREF_INPUTS();\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(LOAD_SUPER_ATTR_METHOD, (unused/1, global_super, class, self -- res2, res)) {\n            assert(oparg & 1);\n            DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);\n            DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);\n            STAT_INC(LOAD_SUPER_ATTR, hit);\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);\n            PyTypeObject *cls = (PyTypeObject *)class;\n            int method_found = 0;\n            res2 = _PySuper_Lookup(cls, self, name,\n                                   cls->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL);\n            Py_DECREF(global_super);\n            Py_DECREF(class);\n            if (res2 == NULL) {\n                Py_DECREF(self);\n                ERROR_IF(true, error);\n            }\n            if (method_found) {\n                res = self; // transfer ownership\n            } else {\n                Py_DECREF(self);\n                res = res2;\n                res2 = NULL;\n            }\n        }\n\n        family(load_attr, INLINE_CACHE_ENTRIES_LOAD_ATTR) = {\n            LOAD_ATTR,\n            LOAD_ATTR_INSTANCE_VALUE,\n            LOAD_ATTR_MODULE,\n            LOAD_ATTR_WITH_HINT,\n            LOAD_ATTR_SLOT,\n            LOAD_ATTR_CLASS,\n            LOAD_ATTR_PROPERTY,\n            LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN,\n            LOAD_ATTR_METHOD_WITH_VALUES,\n            LOAD_ATTR_METHOD_NO_DICT,\n            LOAD_ATTR_METHOD_LAZY_DICT,\n        };\n\n        inst(LOAD_ATTR, (unused/9, owner -- res2 if (oparg & 1), res)) {\n            #if ENABLE_SPECIALIZATION\n            _PyAttrCache *cache = (_PyAttrCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);\n                next_instr--;\n                _Py_Specialize_LoadAttr(owner, next_instr, name);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(LOAD_ATTR, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 1);\n            if (oparg & 1) {\n                /* Designed to work in tandem with CALL, pushes two values. */\n                PyObject* meth = NULL;\n                if (_PyObject_GetMethod(owner, name, &meth)) {\n                    /* We can bypass temporary bound method object.\n                       meth is unbound method and obj is self.\n\n                       meth | self | arg1 | ... | argN\n                     */\n                    assert(meth != NULL);  // No errors on this branch\n                    res2 = meth;\n                    res = owner;  // Transfer ownership\n                }\n                else {\n                    /* meth is not an unbound method (but a regular attr, or\n                       something was returned by a descriptor protocol).  Set\n                       the second element of the stack to NULL, to signal\n                       CALL that it's not a method call.\n\n                       NULL | meth | arg1 | ... | argN\n                    */\n                    DECREF_INPUTS();\n                    ERROR_IF(meth == NULL, error);\n                    res2 = NULL;\n                    res = meth;\n                }\n            }\n            else {\n                /* Classic, pushes one value. */\n                res = PyObject_GetAttr(owner, name);\n                DECREF_INPUTS();\n                ERROR_IF(res == NULL, error);\n            }\n        }\n\n        inst(LOAD_ATTR_INSTANCE_VALUE, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) {\n            PyTypeObject *tp = Py_TYPE(owner);\n            assert(type_version != 0);\n            DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);\n            assert(tp->tp_dictoffset < 0);\n            assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);\n            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);\n            DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);\n            res = _PyDictOrValues_GetValues(dorv)->values[index];\n            DEOPT_IF(res == NULL, LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            Py_INCREF(res);\n            res2 = NULL;\n            DECREF_INPUTS();\n        }\n\n        inst(LOAD_ATTR_MODULE, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) {\n            DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR);\n            PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;\n            assert(dict != NULL);\n            DEOPT_IF(dict->ma_keys->dk_version != type_version, LOAD_ATTR);\n            assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);\n            assert(index < dict->ma_keys->dk_nentries);\n            PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index;\n            res = ep->me_value;\n            DEOPT_IF(res == NULL, LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            Py_INCREF(res);\n            res2 = NULL;\n            DECREF_INPUTS();\n        }\n\n        inst(LOAD_ATTR_WITH_HINT, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) {\n            PyTypeObject *tp = Py_TYPE(owner);\n            assert(type_version != 0);\n            DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);\n            assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);\n            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);\n            DEOPT_IF(_PyDictOrValues_IsValues(dorv), LOAD_ATTR);\n            PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);\n            DEOPT_IF(dict == NULL, LOAD_ATTR);\n            assert(PyDict_CheckExact((PyObject *)dict));\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);\n            uint16_t hint = index;\n            DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR);\n            if (DK_IS_UNICODE(dict->ma_keys)) {\n                PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;\n                DEOPT_IF(ep->me_key != name, LOAD_ATTR);\n                res = ep->me_value;\n            }\n            else {\n                PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint;\n                DEOPT_IF(ep->me_key != name, LOAD_ATTR);\n                res = ep->me_value;\n            }\n            DEOPT_IF(res == NULL, LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            Py_INCREF(res);\n            res2 = NULL;\n            DECREF_INPUTS();\n        }\n\n        inst(LOAD_ATTR_SLOT, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) {\n            PyTypeObject *tp = Py_TYPE(owner);\n            assert(type_version != 0);\n            DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);\n            char *addr = (char *)owner + index;\n            res = *(PyObject **)addr;\n            DEOPT_IF(res == NULL, LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            Py_INCREF(res);\n            res2 = NULL;\n            DECREF_INPUTS();\n        }\n\n        inst(LOAD_ATTR_CLASS, (unused/1, type_version/2, unused/2, descr/4, cls -- res2 if (oparg & 1), res)) {\n\n            DEOPT_IF(!PyType_Check(cls), LOAD_ATTR);\n            DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version,\n                LOAD_ATTR);\n            assert(type_version != 0);\n\n            STAT_INC(LOAD_ATTR, hit);\n            res2 = NULL;\n            res = descr;\n            assert(res != NULL);\n            Py_INCREF(res);\n            DECREF_INPUTS();\n        }\n\n        inst(LOAD_ATTR_PROPERTY, (unused/1, type_version/2, func_version/2, fget/4, owner -- unused if (oparg & 1), unused)) {\n            DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);\n\n            PyTypeObject *cls = Py_TYPE(owner);\n            DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR);\n            assert(type_version != 0);\n            assert(Py_IS_TYPE(fget, &PyFunction_Type));\n            PyFunctionObject *f = (PyFunctionObject *)fget;\n            assert(func_version != 0);\n            DEOPT_IF(f->func_version != func_version, LOAD_ATTR);\n            PyCodeObject *code = (PyCodeObject *)f->func_code;\n            assert(code->co_argcount == 1);\n            DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            Py_INCREF(fget);\n            _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 1);\n            // Manipulate stack directly because we exit with DISPATCH_INLINED().\n            SET_TOP(NULL);\n            int shrink_stack = !(oparg & 1);\n            STACK_SHRINK(shrink_stack);\n            new_frame->localsplus[0] = owner;\n            JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);\n            frame->return_offset = 0;\n            DISPATCH_INLINED(new_frame);\n        }\n\n        inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused if (oparg & 1), unused)) {\n            DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);\n            PyTypeObject *cls = Py_TYPE(owner);\n            DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR);\n            assert(type_version != 0);\n            assert(Py_IS_TYPE(getattribute, &PyFunction_Type));\n            PyFunctionObject *f = (PyFunctionObject *)getattribute;\n            assert(func_version != 0);\n            DEOPT_IF(f->func_version != func_version, LOAD_ATTR);\n            PyCodeObject *code = (PyCodeObject *)f->func_code;\n            assert(code->co_argcount == 2);\n            DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 1);\n            Py_INCREF(f);\n            _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2);\n            // Manipulate stack directly because we exit with DISPATCH_INLINED().\n            SET_TOP(NULL);\n            int shrink_stack = !(oparg & 1);\n            STACK_SHRINK(shrink_stack);\n            new_frame->localsplus[0] = owner;\n            new_frame->localsplus[1] = Py_NewRef(name);\n            JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);\n            frame->return_offset = 0;\n            DISPATCH_INLINED(new_frame);\n        }\n\n        inst(STORE_ATTR_INSTANCE_VALUE, (unused/1, type_version/2, index/1, value, owner --)) {\n            PyTypeObject *tp = Py_TYPE(owner);\n            assert(type_version != 0);\n            DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);\n            assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);\n            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);\n            DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR);\n            STAT_INC(STORE_ATTR, hit);\n            PyDictValues *values = _PyDictOrValues_GetValues(dorv);\n            PyObject *old_value = values->values[index];\n            values->values[index] = value;\n            if (old_value == NULL) {\n                _PyDictValues_AddToInsertionOrder(values, index);\n            }\n            else {\n                Py_DECREF(old_value);\n            }\n            Py_DECREF(owner);\n        }\n\n        inst(STORE_ATTR_WITH_HINT, (unused/1, type_version/2, hint/1, value, owner --)) {\n            PyTypeObject *tp = Py_TYPE(owner);\n            assert(type_version != 0);\n            DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);\n            assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);\n            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);\n            DEOPT_IF(_PyDictOrValues_IsValues(dorv), STORE_ATTR);\n            PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);\n            DEOPT_IF(dict == NULL, STORE_ATTR);\n            assert(PyDict_CheckExact((PyObject *)dict));\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR);\n            PyObject *old_value;\n            uint64_t new_version;\n            if (DK_IS_UNICODE(dict->ma_keys)) {\n                PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;\n                DEOPT_IF(ep->me_key != name, STORE_ATTR);\n                old_value = ep->me_value;\n                DEOPT_IF(old_value == NULL, STORE_ATTR);\n                new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);\n                ep->me_value = value;\n            }\n            else {\n                PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint;\n                DEOPT_IF(ep->me_key != name, STORE_ATTR);\n                old_value = ep->me_value;\n                DEOPT_IF(old_value == NULL, STORE_ATTR);\n                new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);\n                ep->me_value = value;\n            }\n            Py_DECREF(old_value);\n            STAT_INC(STORE_ATTR, hit);\n            /* Ensure dict is GC tracked if it needs to be */\n            if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(value)) {\n                _PyObject_GC_TRACK(dict);\n            }\n            /* PEP 509 */\n            dict->ma_version_tag = new_version;\n            Py_DECREF(owner);\n        }\n\n        inst(STORE_ATTR_SLOT, (unused/1, type_version/2, index/1, value, owner --)) {\n            PyTypeObject *tp = Py_TYPE(owner);\n            assert(type_version != 0);\n            DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);\n            char *addr = (char *)owner + index;\n            STAT_INC(STORE_ATTR, hit);\n            PyObject *old_value = *(PyObject **)addr;\n            *(PyObject **)addr = value;\n            Py_XDECREF(old_value);\n            Py_DECREF(owner);\n        }\n\n        family(compare_op, INLINE_CACHE_ENTRIES_COMPARE_OP) = {\n            COMPARE_OP,\n            COMPARE_OP_FLOAT,\n            COMPARE_OP_INT,\n            COMPARE_OP_STR,\n        };\n\n        inst(COMPARE_OP, (unused/1, left, right -- res)) {\n            #if ENABLE_SPECIALIZATION\n            _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_CompareOp(left, right, next_instr, oparg);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(COMPARE_OP, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            assert((oparg >> 4) <= Py_GE);\n            res = PyObject_RichCompare(left, right, oparg>>4);\n            DECREF_INPUTS();\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(COMPARE_OP_FLOAT, (unused/1, left, right -- res)) {\n            DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP);\n            DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP);\n            STAT_INC(COMPARE_OP, hit);\n            double dleft = PyFloat_AS_DOUBLE(left);\n            double dright = PyFloat_AS_DOUBLE(right);\n            // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg\n            int sign_ish = COMPARISON_BIT(dleft, dright);\n            _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);\n            _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);\n            res = (sign_ish & oparg) ? Py_True : Py_False;\n        }\n\n        // Similar to COMPARE_OP_FLOAT\n        inst(COMPARE_OP_INT, (unused/1, left, right -- res)) {\n            DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP);\n            DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP);\n            DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP);\n            DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_OP);\n            STAT_INC(COMPARE_OP, hit);\n            assert(_PyLong_DigitCount((PyLongObject *)left) <= 1 &&\n                   _PyLong_DigitCount((PyLongObject *)right) <= 1);\n            Py_ssize_t ileft = _PyLong_CompactValue((PyLongObject *)left);\n            Py_ssize_t iright = _PyLong_CompactValue((PyLongObject *)right);\n            // 2 if <, 4 if >, 8 if ==; this matches the low 4 bits of the oparg\n            int sign_ish = COMPARISON_BIT(ileft, iright);\n            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);\n            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);\n            res = (sign_ish & oparg) ? Py_True : Py_False;\n        }\n\n        // Similar to COMPARE_OP_FLOAT, but for ==, != only\n        inst(COMPARE_OP_STR, (unused/1, left, right -- res)) {\n            DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);\n            DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP);\n            STAT_INC(COMPARE_OP, hit);\n            int eq = _PyUnicode_Equal(left, right);\n            assert((oparg >>4) == Py_EQ || (oparg >>4) == Py_NE);\n            _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);\n            _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);\n            assert(eq == 0 || eq == 1);\n            assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS);\n            assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS);\n            res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False;\n        }\n\n        inst(IS_OP, (left, right -- b)) {\n            int res = Py_Is(left, right) ^ oparg;\n            DECREF_INPUTS();\n            b = res ? Py_True : Py_False;\n        }\n\n        inst(CONTAINS_OP, (left, right -- b)) {\n            int res = PySequence_Contains(right, left);\n            DECREF_INPUTS();\n            ERROR_IF(res < 0, error);\n            b = (res ^ oparg) ? Py_True : Py_False;\n        }\n\n        inst(CHECK_EG_MATCH, (exc_value, match_type -- rest, match)) {\n            if (check_except_star_type_valid(tstate, match_type) < 0) {\n                DECREF_INPUTS();\n                ERROR_IF(true, error);\n            }\n\n            match = NULL;\n            rest = NULL;\n            int res = exception_group_match(exc_value, match_type,\n                                            &match, &rest);\n            DECREF_INPUTS();\n            ERROR_IF(res < 0, error);\n\n            assert((match == NULL) == (rest == NULL));\n            ERROR_IF(match == NULL, error);\n\n            if (!Py_IsNone(match)) {\n                PyErr_SetHandledException(match);\n            }\n        }\n\n        inst(CHECK_EXC_MATCH, (left, right -- left, b)) {\n            assert(PyExceptionInstance_Check(left));\n            if (check_except_type_valid(tstate, right) < 0) {\n                 DECREF_INPUTS();\n                 ERROR_IF(true, error);\n            }\n\n            int res = PyErr_GivenExceptionMatches(left, right);\n            DECREF_INPUTS();\n            b = res ? Py_True : Py_False;\n        }\n\n         inst(IMPORT_NAME, (level, fromlist -- res)) {\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            res = import_name(tstate, frame, name, fromlist, level);\n            DECREF_INPUTS();\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(IMPORT_FROM, (from -- from, res)) {\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            res = import_from(tstate, from, name);\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(JUMP_FORWARD, (--)) {\n            JUMPBY(oparg);\n        }\n\n        inst(JUMP_BACKWARD, (--)) {\n            _Py_CODEUNIT *here = next_instr - 1;\n            assert(oparg <= INSTR_OFFSET());\n            JUMPBY(1-oparg);\n            #if ENABLE_SPECIALIZATION\n            here[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER);\n            if (here[1].cache > tstate->interp->optimizer_backedge_threshold) {\n                OBJECT_STAT_INC(optimization_attempts);\n                frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);\n                if (frame == NULL) {\n                    frame = cframe.current_frame;\n                    goto error;\n                }\n                here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1);\n                goto resume_frame;\n            }\n            #endif  /* ENABLE_SPECIALIZATION */\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(ENTER_EXECUTOR, (--)) {\n            _PyExecutorObject *executor = (_PyExecutorObject *)frame->f_code->co_executors->executors[oparg];\n            Py_INCREF(executor);\n            frame = executor->execute(executor, frame, stack_pointer);\n            if (frame == NULL) {\n                frame = cframe.current_frame;\n                goto error;\n            }\n            goto resume_frame;\n        }\n\n        inst(POP_JUMP_IF_FALSE, (cond -- )) {\n            if (Py_IsFalse(cond)) {\n                JUMPBY(oparg);\n            }\n            else if (!Py_IsTrue(cond)) {\n                int err = PyObject_IsTrue(cond);\n                DECREF_INPUTS();\n                if (err == 0) {\n                    JUMPBY(oparg);\n                }\n                else {\n                    ERROR_IF(err < 0, error);\n                }\n            }\n        }\n\n        inst(POP_JUMP_IF_TRUE, (cond -- )) {\n            if (Py_IsTrue(cond)) {\n                JUMPBY(oparg);\n            }\n            else if (!Py_IsFalse(cond)) {\n                int err = PyObject_IsTrue(cond);\n                DECREF_INPUTS();\n                if (err > 0) {\n                    JUMPBY(oparg);\n                }\n                else {\n                    ERROR_IF(err < 0, error);\n                }\n            }\n        }\n\n        inst(POP_JUMP_IF_NOT_NONE, (value -- )) {\n            if (!Py_IsNone(value)) {\n                DECREF_INPUTS();\n                JUMPBY(oparg);\n            }\n        }\n\n        inst(POP_JUMP_IF_NONE, (value -- )) {\n            if (Py_IsNone(value)) {\n                JUMPBY(oparg);\n            }\n            else {\n                DECREF_INPUTS();\n            }\n        }\n\n        inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) {\n            /* This bytecode is used in the `yield from` or `await` loop.\n             * If there is an interrupt, we want it handled in the innermost\n             * generator or coroutine, so we deliberately do not check it here.\n             * (see bpo-30039).\n             */\n            JUMPBY(-oparg);\n        }\n\n        inst(GET_LEN, (obj -- obj, len_o)) {\n            // PUSH(len(TOS))\n            Py_ssize_t len_i = PyObject_Length(obj);\n            ERROR_IF(len_i < 0, error);\n            len_o = PyLong_FromSsize_t(len_i);\n            ERROR_IF(len_o == NULL, error);\n        }\n\n        inst(MATCH_CLASS, (subject, type, names -- attrs)) {\n            // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or\n            // None on failure.\n            assert(PyTuple_CheckExact(names));\n            attrs = match_class(tstate, subject, type, oparg, names);\n            DECREF_INPUTS();\n            if (attrs) {\n                assert(PyTuple_CheckExact(attrs));  // Success!\n            }\n            else {\n                ERROR_IF(_PyErr_Occurred(tstate), error);  // Error!\n                attrs = Py_None;  // Failure!\n            }\n        }\n\n        inst(MATCH_MAPPING, (subject -- subject, res)) {\n            int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING;\n            res = match ? Py_True : Py_False;\n        }\n\n        inst(MATCH_SEQUENCE, (subject -- subject, res)) {\n            int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE;\n            res = match ? Py_True : Py_False;\n        }\n\n        inst(MATCH_KEYS, (subject, keys -- subject, keys, values_or_none)) {\n            // On successful match, PUSH(values). Otherwise, PUSH(None).\n            values_or_none = match_keys(tstate, subject, keys);\n            ERROR_IF(values_or_none == NULL, error);\n        }\n\n        inst(GET_ITER, (iterable -- iter)) {\n            /* before: [obj]; after [getiter(obj)] */\n            iter = PyObject_GetIter(iterable);\n            DECREF_INPUTS();\n            ERROR_IF(iter == NULL, error);\n        }\n\n        inst(GET_YIELD_FROM_ITER, (iterable -- iter)) {\n            /* before: [obj]; after [getiter(obj)] */\n            if (PyCoro_CheckExact(iterable)) {\n                /* `iterable` is a coroutine */\n                if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {\n                    /* and it is used in a 'yield from' expression of a\n                       regular generator. */\n                    _PyErr_SetString(tstate, PyExc_TypeError,\n                                     \"cannot 'yield from' a coroutine object \"\n                                     \"in a non-coroutine generator\");\n                    goto error;\n                }\n                iter = iterable;\n            }\n            else if (PyGen_CheckExact(iterable)) {\n                iter = iterable;\n            }\n            else {\n                /* `iterable` is not a generator. */\n                iter = PyObject_GetIter(iterable);\n                if (iter == NULL) {\n                    goto error;\n                }\n                DECREF_INPUTS();\n            }\n        }\n\n        // Most members of this family are \"secretly\" super-instructions.\n        // When the loop is exhausted, they jump, and the jump target is\n        // always END_FOR, which pops two values off the stack.\n        // This is optimized by skipping that instruction and combining\n        // its effect (popping 'iter' instead of pushing 'next'.)\n\n        family(for_iter, INLINE_CACHE_ENTRIES_FOR_ITER) = {\n            FOR_ITER,\n            FOR_ITER_LIST,\n            FOR_ITER_TUPLE,\n            FOR_ITER_RANGE,\n            FOR_ITER_GEN,\n        };\n\n        inst(FOR_ITER, (unused/1, iter -- iter, next)) {\n            #if ENABLE_SPECIALIZATION\n            _PyForIterCache *cache = (_PyForIterCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_ForIter(iter, next_instr, oparg);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(FOR_ITER, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */\n            next = (*Py_TYPE(iter)->tp_iternext)(iter);\n            if (next == NULL) {\n                if (_PyErr_Occurred(tstate)) {\n                    if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) {\n                        goto error;\n                    }\n                    monitor_raise(tstate, frame, next_instr-1);\n                    _PyErr_Clear(tstate);\n                }\n                /* iterator ended normally */\n                assert(next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == END_FOR ||\n                       next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == INSTRUMENTED_END_FOR);\n                Py_DECREF(iter);\n                STACK_SHRINK(1);\n                /* Jump forward oparg, then skip following END_FOR instruction */\n                JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);\n                DISPATCH();\n            }\n            // Common case: no jump, leave it to the code generator\n        }\n\n        inst(INSTRUMENTED_FOR_ITER, ( -- )) {\n            _Py_CODEUNIT *here = next_instr-1;\n            _Py_CODEUNIT *target;\n            PyObject *iter = TOP();\n            PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter);\n            if (next != NULL) {\n                PUSH(next);\n                target = next_instr + INLINE_CACHE_ENTRIES_FOR_ITER;\n            }\n            else {\n                if (_PyErr_Occurred(tstate)) {\n                    if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) {\n                        goto error;\n                    }\n                    monitor_raise(tstate, frame, here);\n                    _PyErr_Clear(tstate);\n                }\n                /* iterator ended normally */\n                assert(next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == END_FOR ||\n                       next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == INSTRUMENTED_END_FOR);\n                STACK_SHRINK(1);\n                Py_DECREF(iter);\n                /* Skip END_FOR */\n                target = next_instr + INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1;\n            }\n            INSTRUMENTED_JUMP(here, target, PY_MONITORING_EVENT_BRANCH);\n        }\n\n        inst(FOR_ITER_LIST, (unused/1, iter -- iter, next)) {\n            DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER);\n            _PyListIterObject *it = (_PyListIterObject *)iter;\n            STAT_INC(FOR_ITER, hit);\n            PyListObject *seq = it->it_seq;\n            if (seq) {\n                if (it->it_index < PyList_GET_SIZE(seq)) {\n                    next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++));\n                    goto end_for_iter_list;  // End of this instruction\n                }\n                it->it_seq = NULL;\n                Py_DECREF(seq);\n            }\n            Py_DECREF(iter);\n            STACK_SHRINK(1);\n            /* Jump forward oparg, then skip following END_FOR instruction */\n            JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);\n            DISPATCH();\n        end_for_iter_list:\n            // Common case: no jump, leave it to the code generator\n        }\n\n        inst(FOR_ITER_TUPLE, (unused/1, iter -- iter, next)) {\n            _PyTupleIterObject *it = (_PyTupleIterObject *)iter;\n            DEOPT_IF(Py_TYPE(it) != &PyTupleIter_Type, FOR_ITER);\n            STAT_INC(FOR_ITER, hit);\n            PyTupleObject *seq = it->it_seq;\n            if (seq) {\n                if (it->it_index < PyTuple_GET_SIZE(seq)) {\n                    next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++));\n                    goto end_for_iter_tuple;  // End of this instruction\n                }\n                it->it_seq = NULL;\n                Py_DECREF(seq);\n            }\n            Py_DECREF(iter);\n            STACK_SHRINK(1);\n            /* Jump forward oparg, then skip following END_FOR instruction */\n            JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);\n            DISPATCH();\n        end_for_iter_tuple:\n            // Common case: no jump, leave it to the code generator\n        }\n\n        inst(FOR_ITER_RANGE, (unused/1, iter -- iter, next)) {\n            _PyRangeIterObject *r = (_PyRangeIterObject *)iter;\n            DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER);\n            STAT_INC(FOR_ITER, hit);\n            if (r->len <= 0) {\n                STACK_SHRINK(1);\n                Py_DECREF(r);\n                // Jump over END_FOR instruction.\n                JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);\n                DISPATCH();\n            }\n            long value = r->start;\n            r->start = value + r->step;\n            r->len--;\n            next = PyLong_FromLong(value);\n            if (next == NULL) {\n                goto error;\n            }\n        }\n\n        inst(FOR_ITER_GEN, (unused/1, iter -- iter, unused)) {\n            DEOPT_IF(tstate->interp->eval_frame, FOR_ITER);\n            PyGenObject *gen = (PyGenObject *)iter;\n            DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER);\n            DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, FOR_ITER);\n            STAT_INC(FOR_ITER, hit);\n            _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;\n            frame->return_offset = oparg;\n            _PyFrame_StackPush(gen_frame, Py_None);\n            gen->gi_frame_state = FRAME_EXECUTING;\n            gen->gi_exc_state.previous_item = tstate->exc_info;\n            tstate->exc_info = &gen->gi_exc_state;\n            JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER);\n            assert(next_instr[oparg].op.code == END_FOR ||\n                   next_instr[oparg].op.code == INSTRUMENTED_END_FOR);\n            DISPATCH_INLINED(gen_frame);\n        }\n\n        inst(BEFORE_ASYNC_WITH, (mgr -- exit, res)) {\n            PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__));\n            if (enter == NULL) {\n                if (!_PyErr_Occurred(tstate)) {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                  \"'%.200s' object does not support the \"\n                                  \"asynchronous context manager protocol\",\n                                  Py_TYPE(mgr)->tp_name);\n                }\n                goto error;\n            }\n            exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__));\n            if (exit == NULL) {\n                if (!_PyErr_Occurred(tstate)) {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                  \"'%.200s' object does not support the \"\n                                  \"asynchronous context manager protocol \"\n                                  \"(missed __aexit__ method)\",\n                                  Py_TYPE(mgr)->tp_name);\n                }\n                Py_DECREF(enter);\n                goto error;\n            }\n            DECREF_INPUTS();\n            res = _PyObject_CallNoArgs(enter);\n            Py_DECREF(enter);\n            if (res == NULL) {\n                Py_DECREF(exit);\n                ERROR_IF(true, error);\n            }\n        }\n\n        inst(BEFORE_WITH, (mgr -- exit, res)) {\n            /* pop the context manager, push its __exit__ and the\n             * value returned from calling its __enter__\n             */\n            PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__enter__));\n            if (enter == NULL) {\n                if (!_PyErr_Occurred(tstate)) {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                  \"'%.200s' object does not support the \"\n                                  \"context manager protocol\",\n                                  Py_TYPE(mgr)->tp_name);\n                }\n                goto error;\n            }\n            exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__));\n            if (exit == NULL) {\n                if (!_PyErr_Occurred(tstate)) {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                  \"'%.200s' object does not support the \"\n                                  \"context manager protocol \"\n                                  \"(missed __exit__ method)\",\n                                  Py_TYPE(mgr)->tp_name);\n                }\n                Py_DECREF(enter);\n                goto error;\n            }\n            DECREF_INPUTS();\n            res = _PyObject_CallNoArgs(enter);\n            Py_DECREF(enter);\n            if (res == NULL) {\n                Py_DECREF(exit);\n                ERROR_IF(true, error);\n            }\n        }\n\n        inst(WITH_EXCEPT_START, (exit_func, lasti, unused, val -- exit_func, lasti, unused, val, res)) {\n            /* At the top of the stack are 4 values:\n               - val: TOP = exc_info()\n               - unused: SECOND = previous exception\n               - lasti: THIRD = lasti of exception in exc_info()\n               - exit_func: FOURTH = the context.__exit__ bound method\n               We call FOURTH(type(TOP), TOP, GetTraceback(TOP)).\n               Then we push the __exit__ return value.\n            */\n            PyObject *exc, *tb;\n\n            assert(val && PyExceptionInstance_Check(val));\n            exc = PyExceptionInstance_Class(val);\n            tb = PyException_GetTraceback(val);\n            Py_XDECREF(tb);\n            assert(PyLong_Check(lasti));\n            (void)lasti; // Shut up compiler warning if asserts are off\n            PyObject *stack[4] = {NULL, exc, val, tb};\n            res = PyObject_Vectorcall(exit_func, stack + 1,\n                    3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(PUSH_EXC_INFO, (new_exc -- prev_exc, new_exc)) {\n            _PyErr_StackItem *exc_info = tstate->exc_info;\n            if (exc_info->exc_value != NULL) {\n                prev_exc = exc_info->exc_value;\n            }\n            else {\n                prev_exc = Py_None;\n            }\n            assert(PyExceptionInstance_Check(new_exc));\n            exc_info->exc_value = Py_NewRef(new_exc);\n        }\n\n        inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (oparg & 1), res)) {\n            /* Cached method object */\n            PyTypeObject *self_cls = Py_TYPE(self);\n            assert(type_version != 0);\n            DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);\n            assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);\n            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(self);\n            DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);\n            PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls;\n            DEOPT_IF(self_heap_type->ht_cached_keys->dk_version !=\n                     keys_version, LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            assert(descr != NULL);\n            res2 = Py_NewRef(descr);\n            assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR));\n            res = self;\n            assert(oparg & 1);\n        }\n\n        inst(LOAD_ATTR_METHOD_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (oparg & 1), res)) {\n            PyTypeObject *self_cls = Py_TYPE(self);\n            DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);\n            assert(self_cls->tp_dictoffset == 0);\n            STAT_INC(LOAD_ATTR, hit);\n            assert(descr != NULL);\n            assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));\n            res2 = Py_NewRef(descr);\n            res = self;\n            assert(oparg & 1);\n        }\n\n        inst(LOAD_ATTR_METHOD_LAZY_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (oparg & 1), res)) {\n            PyTypeObject *self_cls = Py_TYPE(self);\n            DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);\n            Py_ssize_t dictoffset = self_cls->tp_dictoffset;\n            assert(dictoffset > 0);\n            PyObject *dict = *(PyObject **)((char *)self + dictoffset);\n            /* This object has a __dict__, just not yet created */\n            DEOPT_IF(dict != NULL, LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            assert(descr != NULL);\n            assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));\n            res2 = Py_NewRef(descr);\n            res = self;\n            assert(oparg & 1);\n        }\n\n        inst(KW_NAMES, (--)) {\n            assert(kwnames == NULL);\n            assert(oparg < PyTuple_GET_SIZE(frame->f_code->co_consts));\n            kwnames = GETITEM(frame->f_code->co_consts, oparg);\n        }\n\n        inst(INSTRUMENTED_CALL, ( -- )) {\n            int is_meth = PEEK(oparg+2) != NULL;\n            int total_args = oparg + is_meth;\n            PyObject *function = PEEK(total_args + 1);\n            PyObject *arg = total_args == 0 ?\n                &_PyInstrumentation_MISSING : PEEK(total_args);\n            int err = _Py_call_instrumentation_2args(\n                    tstate, PY_MONITORING_EVENT_CALL,\n                    frame, next_instr-1, function, arg);\n            ERROR_IF(err, error);\n            _PyCallCache *cache = (_PyCallCache *)next_instr;\n            INCREMENT_ADAPTIVE_COUNTER(cache->counter);\n            GO_TO_INSTRUCTION(CALL);\n        }\n\n        // Cache layout: counter/1, func_version/2\n        // Neither CALL_INTRINSIC_1/2 nor CALL_FUNCTION_EX are members!\n        family(call, INLINE_CACHE_ENTRIES_CALL) = {\n            CALL,\n            CALL_BOUND_METHOD_EXACT_ARGS,\n            CALL_PY_EXACT_ARGS,\n            CALL_PY_WITH_DEFAULTS,\n            CALL_NO_KW_TYPE_1,\n            CALL_NO_KW_STR_1,\n            CALL_NO_KW_TUPLE_1,\n            CALL_BUILTIN_CLASS,\n            CALL_NO_KW_BUILTIN_O,\n            CALL_NO_KW_BUILTIN_FAST,\n            CALL_BUILTIN_FAST_WITH_KEYWORDS,\n            CALL_NO_KW_LEN,\n            CALL_NO_KW_ISINSTANCE,\n            CALL_NO_KW_LIST_APPEND,\n            CALL_NO_KW_METHOD_DESCRIPTOR_O,\n            CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,\n            CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,\n            CALL_NO_KW_METHOD_DESCRIPTOR_FAST,\n        };\n\n        // On entry, the stack is either\n        //   [NULL, callable, arg1, arg2, ...]\n        // or\n        //   [method, self, arg1, arg2, ...]\n        // (Some args may be keywords, see KW_NAMES, which sets 'kwnames'.)\n        // On exit, the stack is [result].\n        // When calling Python, inline the call using DISPATCH_INLINED().\n        inst(CALL, (unused/1, unused/2, method, callable, args[oparg] -- res)) {\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            #if ENABLE_SPECIALIZATION\n            _PyCallCache *cache = (_PyCallCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_Call(callable, next_instr, total_args, kwnames);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(CALL, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            if (!is_meth && Py_TYPE(callable) == &PyMethod_Type) {\n                is_meth = 1;  // For consistenct; it's dead, though\n                args--;\n                total_args++;\n                PyObject *self = ((PyMethodObject *)callable)->im_self;\n                args[0] = Py_NewRef(self);\n                method = ((PyMethodObject *)callable)->im_func;\n                args[-1] = Py_NewRef(method);\n                Py_DECREF(callable);\n                callable = method;\n            }\n            int positional_args = total_args - KWNAMES_LEN();\n            // Check if the call can be inlined or not\n            if (Py_TYPE(callable) == &PyFunction_Type &&\n                tstate->interp->eval_frame == NULL &&\n                ((PyFunctionObject *)callable)->vectorcall == _PyFunction_Vectorcall)\n            {\n                int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags;\n                PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));\n                _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(\n                    tstate, (PyFunctionObject *)callable, locals,\n                    args, positional_args, kwnames\n                );\n                kwnames = NULL;\n                // Manipulate stack directly since we leave using DISPATCH_INLINED().\n                STACK_SHRINK(oparg + 2);\n                // The frame has stolen all the arguments from the stack,\n                // so there is no need to clean them up.\n                if (new_frame == NULL) {\n                    goto error;\n                }\n                JUMPBY(INLINE_CACHE_ENTRIES_CALL);\n                frame->return_offset = 0;\n                DISPATCH_INLINED(new_frame);\n            }\n            /* Callable is not a normal Python function */\n            res = PyObject_Vectorcall(\n                callable, args,\n                positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET,\n                kwnames);\n            if (opcode == INSTRUMENTED_CALL) {\n                PyObject *arg = total_args == 0 ?\n                    &_PyInstrumentation_MISSING : PEEK(total_args);\n                if (res == NULL) {\n                    _Py_call_instrumentation_exc2(\n                        tstate, PY_MONITORING_EVENT_C_RAISE,\n                        frame, next_instr-1, callable, arg);\n                }\n                else {\n                    int err = _Py_call_instrumentation_2args(\n                        tstate, PY_MONITORING_EVENT_C_RETURN,\n                        frame, next_instr-1, callable, arg);\n                    if (err < 0) {\n                        Py_CLEAR(res);\n                    }\n                }\n            }\n            kwnames = NULL;\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n            Py_DECREF(callable);\n            for (int i = 0; i < total_args; i++) {\n                Py_DECREF(args[i]);\n            }\n            ERROR_IF(res == NULL, error);\n            CHECK_EVAL_BREAKER();\n        }\n\n        // Start out with [NULL, bound_method, arg1, arg2, ...]\n        // Transform to [callable, self, arg1, arg2, ...]\n        // Then fall through to CALL_PY_EXACT_ARGS\n        inst(CALL_BOUND_METHOD_EXACT_ARGS, (unused/1, unused/2, method, callable, unused[oparg] -- unused)) {\n            DEOPT_IF(method != NULL, CALL);\n            DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL);\n            STAT_INC(CALL, hit);\n            PyObject *self = ((PyMethodObject *)callable)->im_self;\n            PEEK(oparg + 1) = Py_NewRef(self);  // callable\n            PyObject *meth = ((PyMethodObject *)callable)->im_func;\n            PEEK(oparg + 2) = Py_NewRef(meth);  // method\n            Py_DECREF(callable);\n            GO_TO_INSTRUCTION(CALL_PY_EXACT_ARGS);\n        }\n\n        inst(CALL_PY_EXACT_ARGS, (unused/1, func_version/2, method, callable, args[oparg] -- unused)) {\n            assert(kwnames == NULL);\n            DEOPT_IF(tstate->interp->eval_frame, CALL);\n            int is_meth = method != NULL;\n            int argcount = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                argcount++;\n            }\n            DEOPT_IF(!PyFunction_Check(callable), CALL);\n            PyFunctionObject *func = (PyFunctionObject *)callable;\n            DEOPT_IF(func->func_version != func_version, CALL);\n            PyCodeObject *code = (PyCodeObject *)func->func_code;\n            DEOPT_IF(code->co_argcount != argcount, CALL);\n            DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL);\n            STAT_INC(CALL, hit);\n            _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, func, argcount);\n            for (int i = 0; i < argcount; i++) {\n                new_frame->localsplus[i] = args[i];\n            }\n            // Manipulate stack directly since we leave using DISPATCH_INLINED().\n            STACK_SHRINK(oparg + 2);\n            JUMPBY(INLINE_CACHE_ENTRIES_CALL);\n            frame->return_offset = 0;\n            DISPATCH_INLINED(new_frame);\n        }\n\n        inst(CALL_PY_WITH_DEFAULTS, (unused/1, func_version/2, method, callable, args[oparg] -- unused)) {\n            assert(kwnames == NULL);\n            DEOPT_IF(tstate->interp->eval_frame, CALL);\n            int is_meth = method != NULL;\n            int argcount = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                argcount++;\n            }\n            DEOPT_IF(!PyFunction_Check(callable), CALL);\n            PyFunctionObject *func = (PyFunctionObject *)callable;\n            DEOPT_IF(func->func_version != func_version, CALL);\n            PyCodeObject *code = (PyCodeObject *)func->func_code;\n            assert(func->func_defaults);\n            assert(PyTuple_CheckExact(func->func_defaults));\n            int defcount = (int)PyTuple_GET_SIZE(func->func_defaults);\n            assert(defcount <= code->co_argcount);\n            int min_args = code->co_argcount - defcount;\n            DEOPT_IF(argcount > code->co_argcount, CALL);\n            DEOPT_IF(argcount < min_args, CALL);\n            DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL);\n            STAT_INC(CALL, hit);\n            _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, func, code->co_argcount);\n            for (int i = 0; i < argcount; i++) {\n                new_frame->localsplus[i] = args[i];\n            }\n            for (int i = argcount; i < code->co_argcount; i++) {\n                PyObject *def = PyTuple_GET_ITEM(func->func_defaults, i - min_args);\n                new_frame->localsplus[i] = Py_NewRef(def);\n            }\n            // Manipulate stack and cache directly since we leave using DISPATCH_INLINED().\n            STACK_SHRINK(oparg + 2);\n            JUMPBY(INLINE_CACHE_ENTRIES_CALL);\n            frame->return_offset = 0;\n            DISPATCH_INLINED(new_frame);\n        }\n\n        inst(CALL_NO_KW_TYPE_1, (unused/1, unused/2, null, callable, args[oparg] -- res)) {\n            assert(kwnames == NULL);\n            assert(oparg == 1);\n            DEOPT_IF(null != NULL, CALL);\n            PyObject *obj = args[0];\n            DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL);\n            STAT_INC(CALL, hit);\n            res = Py_NewRef(Py_TYPE(obj));\n            Py_DECREF(obj);\n            Py_DECREF(&PyType_Type);  // I.e., callable\n        }\n\n        inst(CALL_NO_KW_STR_1, (unused/1, unused/2, null, callable, args[oparg] -- res)) {\n            assert(kwnames == NULL);\n            assert(oparg == 1);\n            DEOPT_IF(null != NULL, CALL);\n            DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, CALL);\n            STAT_INC(CALL, hit);\n            PyObject *arg = args[0];\n            res = PyObject_Str(arg);\n            Py_DECREF(arg);\n            Py_DECREF(&PyUnicode_Type);  // I.e., callable\n            ERROR_IF(res == NULL, error);\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(CALL_NO_KW_TUPLE_1, (unused/1, unused/2, null, callable, args[oparg] -- res)) {\n            assert(kwnames == NULL);\n            assert(oparg == 1);\n            DEOPT_IF(null != NULL, CALL);\n            DEOPT_IF(callable != (PyObject *)&PyTuple_Type, CALL);\n            STAT_INC(CALL, hit);\n            PyObject *arg = args[0];\n            res = PySequence_Tuple(arg);\n            Py_DECREF(arg);\n            Py_DECREF(&PyTuple_Type);  // I.e., tuple\n            ERROR_IF(res == NULL, error);\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(CALL_BUILTIN_CLASS, (unused/1, unused/2, method, callable, args[oparg] -- res)) {\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            int kwnames_len = KWNAMES_LEN();\n            DEOPT_IF(!PyType_Check(callable), CALL);\n            PyTypeObject *tp = (PyTypeObject *)callable;\n            DEOPT_IF(tp->tp_vectorcall == NULL, CALL);\n            STAT_INC(CALL, hit);\n            res = tp->tp_vectorcall((PyObject *)tp, args,\n                                    total_args - kwnames_len, kwnames);\n            kwnames = NULL;\n            /* Free the arguments. */\n            for (int i = 0; i < total_args; i++) {\n                Py_DECREF(args[i]);\n            }\n            Py_DECREF(tp);\n            ERROR_IF(res == NULL, error);\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(CALL_NO_KW_BUILTIN_O, (unused/1, unused/2, method, callable, args[oparg] -- res)) {\n            /* Builtin METH_O functions */\n            assert(kwnames == NULL);\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            DEOPT_IF(total_args != 1, CALL);\n            DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);\n            DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL);\n            STAT_INC(CALL, hit);\n            PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);\n            // This is slower but CPython promises to check all non-vectorcall\n            // function calls.\n            if (_Py_EnterRecursiveCallTstate(tstate, \" while calling a Python object\")) {\n                goto error;\n            }\n            PyObject *arg = args[0];\n            res = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable), arg);\n            _Py_LeaveRecursiveCallTstate(tstate);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n\n            Py_DECREF(arg);\n            Py_DECREF(callable);\n            ERROR_IF(res == NULL, error);\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(CALL_NO_KW_BUILTIN_FAST, (unused/1, unused/2, method, callable, args[oparg] -- res)) {\n            /* Builtin METH_FASTCALL functions, without keywords */\n            assert(kwnames == NULL);\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);\n            DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL, CALL);\n            STAT_INC(CALL, hit);\n            PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);\n            /* res = func(self, args, nargs) */\n            res = ((_PyCFunctionFast)(void(*)(void))cfunc)(\n                PyCFunction_GET_SELF(callable),\n                args,\n                total_args);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n\n            /* Free the arguments. */\n            for (int i = 0; i < total_args; i++) {\n                Py_DECREF(args[i]);\n            }\n            Py_DECREF(callable);\n            ERROR_IF(res == NULL, error);\n                /* Not deopting because this doesn't mean our optimization was\n                   wrong. `res` can be NULL for valid reasons. Eg. getattr(x,\n                   'invalid'). In those cases an exception is set, so we must\n                   handle it.\n                */\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(CALL_BUILTIN_FAST_WITH_KEYWORDS, (unused/1, unused/2, method, callable, args[oparg] -- res)) {\n            /* Builtin METH_FASTCALL | METH_KEYWORDS functions */\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);\n            DEOPT_IF(PyCFunction_GET_FLAGS(callable) !=\n                (METH_FASTCALL | METH_KEYWORDS), CALL);\n            STAT_INC(CALL, hit);\n            /* res = func(self, args, nargs, kwnames) */\n            _PyCFunctionFastWithKeywords cfunc =\n                (_PyCFunctionFastWithKeywords)(void(*)(void))\n                PyCFunction_GET_FUNCTION(callable);\n            res = cfunc(\n                PyCFunction_GET_SELF(callable),\n                args,\n                total_args - KWNAMES_LEN(),\n                kwnames\n            );\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n            kwnames = NULL;\n\n            /* Free the arguments. */\n            for (int i = 0; i < total_args; i++) {\n                Py_DECREF(args[i]);\n            }\n            Py_DECREF(callable);\n            ERROR_IF(res == NULL, error);\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(CALL_NO_KW_LEN, (unused/1, unused/2, method, callable, args[oparg] -- res)) {\n            assert(kwnames == NULL);\n            /* len(o) */\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            DEOPT_IF(total_args != 1, CALL);\n            PyInterpreterState *interp = _PyInterpreterState_GET();\n            DEOPT_IF(callable != interp->callable_cache.len, CALL);\n            STAT_INC(CALL, hit);\n            PyObject *arg = args[0];\n            Py_ssize_t len_i = PyObject_Length(arg);\n            if (len_i < 0) {\n                goto error;\n            }\n            res = PyLong_FromSsize_t(len_i);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n\n            Py_DECREF(callable);\n            Py_DECREF(arg);\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(CALL_NO_KW_ISINSTANCE, (unused/1, unused/2, method, callable, args[oparg] -- res)) {\n            assert(kwnames == NULL);\n            /* isinstance(o, o2) */\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            DEOPT_IF(total_args != 2, CALL);\n            PyInterpreterState *interp = _PyInterpreterState_GET();\n            DEOPT_IF(callable != interp->callable_cache.isinstance, CALL);\n            STAT_INC(CALL, hit);\n            PyObject *cls = args[1];\n            PyObject *inst = args[0];\n            int retval = PyObject_IsInstance(inst, cls);\n            if (retval < 0) {\n                goto error;\n            }\n            res = PyBool_FromLong(retval);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n\n            Py_DECREF(inst);\n            Py_DECREF(cls);\n            Py_DECREF(callable);\n            ERROR_IF(res == NULL, error);\n        }\n\n        // This is secretly a super-instruction\n        inst(CALL_NO_KW_LIST_APPEND, (unused/1, unused/2, method, self, args[oparg] -- unused)) {\n            assert(kwnames == NULL);\n            assert(oparg == 1);\n            assert(method != NULL);\n            PyInterpreterState *interp = _PyInterpreterState_GET();\n            DEOPT_IF(method != interp->callable_cache.list_append, CALL);\n            DEOPT_IF(!PyList_Check(self), CALL);\n            STAT_INC(CALL, hit);\n            if (_PyList_AppendTakeRef((PyListObject *)self, args[0]) < 0) {\n                goto pop_1_error;  // Since arg is DECREF'ed already\n            }\n            Py_DECREF(self);\n            Py_DECREF(method);\n            STACK_SHRINK(3);\n            // CALL + POP_TOP\n            JUMPBY(INLINE_CACHE_ENTRIES_CALL + 1);\n            assert(next_instr[-1].op.code == POP_TOP);\n            DISPATCH();\n        }\n\n        inst(CALL_NO_KW_METHOD_DESCRIPTOR_O, (unused/1, unused/2, method, unused, args[oparg] -- res)) {\n            assert(kwnames == NULL);\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                args--;\n                total_args++;\n            }\n            PyMethodDescrObject *callable =\n                (PyMethodDescrObject *)PEEK(total_args + 1);\n            DEOPT_IF(total_args != 2, CALL);\n            DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL);\n            PyMethodDef *meth = callable->d_method;\n            DEOPT_IF(meth->ml_flags != METH_O, CALL);\n            PyObject *arg = args[1];\n            PyObject *self = args[0];\n            DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL);\n            STAT_INC(CALL, hit);\n            PyCFunction cfunc = meth->ml_meth;\n            // This is slower but CPython promises to check all non-vectorcall\n            // function calls.\n            if (_Py_EnterRecursiveCallTstate(tstate, \" while calling a Python object\")) {\n                goto error;\n            }\n            res = _PyCFunction_TrampolineCall(cfunc, self, arg);\n            _Py_LeaveRecursiveCallTstate(tstate);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n            Py_DECREF(self);\n            Py_DECREF(arg);\n            Py_DECREF(callable);\n            ERROR_IF(res == NULL, error);\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (unused/1, unused/2, method, unused, args[oparg] -- res)) {\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                args--;\n                total_args++;\n            }\n            PyMethodDescrObject *callable =\n                (PyMethodDescrObject *)PEEK(total_args + 1);\n            DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL);\n            PyMethodDef *meth = callable->d_method;\n            DEOPT_IF(meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS), CALL);\n            PyTypeObject *d_type = callable->d_common.d_type;\n            PyObject *self = args[0];\n            DEOPT_IF(!Py_IS_TYPE(self, d_type), CALL);\n            STAT_INC(CALL, hit);\n            int nargs = total_args - 1;\n            _PyCFunctionFastWithKeywords cfunc =\n                (_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;\n            res = cfunc(self, args + 1, nargs - KWNAMES_LEN(), kwnames);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n            kwnames = NULL;\n\n            /* Free the arguments. */\n            for (int i = 0; i < total_args; i++) {\n                Py_DECREF(args[i]);\n            }\n            Py_DECREF(callable);\n            ERROR_IF(res == NULL, error);\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, (unused/1, unused/2, method, unused, args[oparg] -- res)) {\n            assert(kwnames == NULL);\n            assert(oparg == 0 || oparg == 1);\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                args--;\n                total_args++;\n            }\n            DEOPT_IF(total_args != 1, CALL);\n            PyMethodDescrObject *callable = (PyMethodDescrObject *)SECOND();\n            DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL);\n            PyMethodDef *meth = callable->d_method;\n            PyObject *self = args[0];\n            DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL);\n            DEOPT_IF(meth->ml_flags != METH_NOARGS, CALL);\n            STAT_INC(CALL, hit);\n            PyCFunction cfunc = meth->ml_meth;\n            // This is slower but CPython promises to check all non-vectorcall\n            // function calls.\n            if (_Py_EnterRecursiveCallTstate(tstate, \" while calling a Python object\")) {\n                goto error;\n            }\n            res = _PyCFunction_TrampolineCall(cfunc, self, NULL);\n            _Py_LeaveRecursiveCallTstate(tstate);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n            Py_DECREF(self);\n            Py_DECREF(callable);\n            ERROR_IF(res == NULL, error);\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(CALL_NO_KW_METHOD_DESCRIPTOR_FAST, (unused/1, unused/2, method, unused, args[oparg] -- res)) {\n            assert(kwnames == NULL);\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                args--;\n                total_args++;\n            }\n            PyMethodDescrObject *callable =\n                (PyMethodDescrObject *)PEEK(total_args + 1);\n            /* Builtin METH_FASTCALL methods, without keywords */\n            DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL);\n            PyMethodDef *meth = callable->d_method;\n            DEOPT_IF(meth->ml_flags != METH_FASTCALL, CALL);\n            PyObject *self = args[0];\n            DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL);\n            STAT_INC(CALL, hit);\n            _PyCFunctionFast cfunc =\n                (_PyCFunctionFast)(void(*)(void))meth->ml_meth;\n            int nargs = total_args - 1;\n            res = cfunc(self, args + 1, nargs);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n            /* Clear the stack of the arguments. */\n            for (int i = 0; i < total_args; i++) {\n                Py_DECREF(args[i]);\n            }\n            Py_DECREF(callable);\n            ERROR_IF(res == NULL, error);\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(INSTRUMENTED_CALL_FUNCTION_EX, ( -- )) {\n            GO_TO_INSTRUCTION(CALL_FUNCTION_EX);\n        }\n\n        inst(CALL_FUNCTION_EX, (unused, func, callargs, kwargs if (oparg & 1) -- result)) {\n            // DICT_MERGE is called before this opcode if there are kwargs.\n            // It converts all dict subtypes in kwargs into regular dicts.\n            assert(kwargs == NULL || PyDict_CheckExact(kwargs));\n            if (!PyTuple_CheckExact(callargs)) {\n                if (check_args_iterable(tstate, func, callargs) < 0) {\n                    goto error;\n                }\n                PyObject *tuple = PySequence_Tuple(callargs);\n                if (tuple == NULL) {\n                    goto error;\n                }\n                Py_SETREF(callargs, tuple);\n            }\n            assert(PyTuple_CheckExact(callargs));\n            EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_FUNCTION_EX, func);\n            if (opcode == INSTRUMENTED_CALL_FUNCTION_EX &&\n                !PyFunction_Check(func) && !PyMethod_Check(func)\n            ) {\n                PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ?\n                    PyTuple_GET_ITEM(callargs, 0) : Py_None;\n                int err = _Py_call_instrumentation_2args(\n                    tstate, PY_MONITORING_EVENT_CALL,\n                    frame, next_instr-1, func, arg);\n                if (err) goto error;\n                result = PyObject_Call(func, callargs, kwargs);\n                if (result == NULL) {\n                    _Py_call_instrumentation_exc2(\n                        tstate, PY_MONITORING_EVENT_C_RAISE,\n                        frame, next_instr-1, func, arg);\n                }\n                else {\n                    int err = _Py_call_instrumentation_2args(\n                        tstate, PY_MONITORING_EVENT_C_RETURN,\n                        frame, next_instr-1, func, arg);\n                    if (err < 0) {\n                        Py_CLEAR(result);\n                    }\n                }\n            }\n            else {\n                if (Py_TYPE(func) == &PyFunction_Type &&\n                    tstate->interp->eval_frame == NULL &&\n                    ((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) {\n                    assert(PyTuple_CheckExact(callargs));\n                    Py_ssize_t nargs = PyTuple_GET_SIZE(callargs);\n                    int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags;\n                    PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func));\n\n                    _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(tstate,\n                                                                                (PyFunctionObject *)func, locals,\n                                                                                nargs, callargs, kwargs);\n                    // Need to manually shrink the stack since we exit with DISPATCH_INLINED.\n                    STACK_SHRINK(oparg + 3);\n                    if (new_frame == NULL) {\n                        goto error;\n                    }\n                    frame->return_offset = 0;\n                    DISPATCH_INLINED(new_frame);\n                }\n                result = PyObject_Call(func, callargs, kwargs);\n            }\n            DECREF_INPUTS();\n            assert(PEEK(3 + (oparg & 1)) == NULL);\n            ERROR_IF(result == NULL, error);\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(MAKE_FUNCTION, (defaults    if (oparg & MAKE_FUNCTION_DEFAULTS),\n                             kwdefaults  if (oparg & MAKE_FUNCTION_KWDEFAULTS),\n                             annotations if (oparg & MAKE_FUNCTION_ANNOTATIONS),\n                             closure     if (oparg & MAKE_FUNCTION_CLOSURE),\n                             codeobj -- func)) {\n\n            PyFunctionObject *func_obj = (PyFunctionObject *)\n                PyFunction_New(codeobj, GLOBALS());\n\n            Py_DECREF(codeobj);\n            if (func_obj == NULL) {\n                goto error;\n            }\n\n            if (oparg & MAKE_FUNCTION_CLOSURE) {\n                assert(PyTuple_CheckExact(closure));\n                func_obj->func_closure = closure;\n            }\n            if (oparg & MAKE_FUNCTION_ANNOTATIONS) {\n                assert(PyTuple_CheckExact(annotations));\n                func_obj->func_annotations = annotations;\n            }\n            if (oparg & MAKE_FUNCTION_KWDEFAULTS) {\n                assert(PyDict_CheckExact(kwdefaults));\n                func_obj->func_kwdefaults = kwdefaults;\n            }\n            if (oparg & MAKE_FUNCTION_DEFAULTS) {\n                assert(PyTuple_CheckExact(defaults));\n                func_obj->func_defaults = defaults;\n            }\n\n            func_obj->func_version = ((PyCodeObject *)codeobj)->co_version;\n            func = (PyObject *)func_obj;\n        }\n\n        inst(RETURN_GENERATOR, (--)) {\n            assert(PyFunction_Check(frame->f_funcobj));\n            PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;\n            PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);\n            if (gen == NULL) {\n                goto error;\n            }\n            assert(EMPTY());\n            _PyFrame_SetStackPointer(frame, stack_pointer);\n            _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;\n            _PyFrame_Copy(frame, gen_frame);\n            assert(frame->frame_obj == NULL);\n            gen->gi_frame_state = FRAME_CREATED;\n            gen_frame->owner = FRAME_OWNED_BY_GENERATOR;\n            _Py_LeaveRecursiveCallPy(tstate);\n            assert(frame != &entry_frame);\n            _PyInterpreterFrame *prev = frame->previous;\n            _PyThreadState_PopFrame(tstate, frame);\n            frame = cframe.current_frame = prev;\n            _PyFrame_StackPush(frame, (PyObject *)gen);\n            goto resume_frame;\n        }\n\n        inst(BUILD_SLICE, (start, stop, step if (oparg == 3) -- slice)) {\n            slice = PySlice_New(start, stop, step);\n            DECREF_INPUTS();\n            ERROR_IF(slice == NULL, error);\n        }\n\n        inst(FORMAT_VALUE, (value, fmt_spec if ((oparg & FVS_MASK) == FVS_HAVE_SPEC) -- result)) {\n            /* Handles f-string value formatting. */\n            PyObject *(*conv_fn)(PyObject *);\n            int which_conversion = oparg & FVC_MASK;\n\n            /* See if any conversion is specified. */\n            switch (which_conversion) {\n            case FVC_NONE:  conv_fn = NULL;           break;\n            case FVC_STR:   conv_fn = PyObject_Str;   break;\n            case FVC_REPR:  conv_fn = PyObject_Repr;  break;\n            case FVC_ASCII: conv_fn = PyObject_ASCII; break;\n            default:\n                _PyErr_Format(tstate, PyExc_SystemError,\n                              \"unexpected conversion flag %d\",\n                              which_conversion);\n                goto error;\n            }\n\n            /* If there's a conversion function, call it and replace\n               value with that result. Otherwise, just use value,\n               without conversion. */\n            if (conv_fn != NULL) {\n                result = conv_fn(value);\n                Py_DECREF(value);\n                if (result == NULL) {\n                    Py_XDECREF(fmt_spec);\n                    ERROR_IF(true, error);\n                }\n                value = result;\n            }\n\n            result = PyObject_Format(value, fmt_spec);\n            Py_DECREF(value);\n            Py_XDECREF(fmt_spec);\n            ERROR_IF(result == NULL, error);\n        }\n\n        inst(COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) {\n            assert(oparg > 0);\n            top = Py_NewRef(bottom);\n        }\n\n        inst(BINARY_OP, (unused/1, lhs, rhs -- res)) {\n            #if ENABLE_SPECIALIZATION\n            _PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, &GETLOCAL(0));\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(BINARY_OP, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            assert(0 <= oparg);\n            assert((unsigned)oparg < Py_ARRAY_LENGTH(binary_ops));\n            assert(binary_ops[oparg]);\n            res = binary_ops[oparg](lhs, rhs);\n            DECREF_INPUTS();\n            ERROR_IF(res == NULL, error);\n        }\n\n        inst(SWAP, (bottom, unused[oparg-2], top --\n                    top, unused[oparg-2], bottom)) {\n            assert(oparg >= 2);\n        }\n\n        inst(INSTRUMENTED_INSTRUCTION, ( -- )) {\n            int next_opcode = _Py_call_instrumentation_instruction(\n                tstate, frame, next_instr-1);\n            ERROR_IF(next_opcode < 0, error);\n            next_instr--;\n            if (_PyOpcode_Caches[next_opcode]) {\n                _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1);\n                INCREMENT_ADAPTIVE_COUNTER(cache->counter);\n            }\n            assert(next_opcode > 0 && next_opcode < 256);\n            opcode = next_opcode;\n            DISPATCH_GOTO();\n        }\n\n        inst(INSTRUMENTED_JUMP_FORWARD, ( -- )) {\n            INSTRUMENTED_JUMP(next_instr-1, next_instr+oparg, PY_MONITORING_EVENT_JUMP);\n        }\n\n        inst(INSTRUMENTED_JUMP_BACKWARD, ( -- )) {\n            INSTRUMENTED_JUMP(next_instr-1, next_instr+1-oparg, PY_MONITORING_EVENT_JUMP);\n            CHECK_EVAL_BREAKER();\n        }\n\n        inst(INSTRUMENTED_POP_JUMP_IF_TRUE, ( -- )) {\n            PyObject *cond = POP();\n            int err = PyObject_IsTrue(cond);\n            Py_DECREF(cond);\n            ERROR_IF(err < 0, error);\n            _Py_CODEUNIT *here = next_instr-1;\n            assert(err == 0 || err == 1);\n            int offset = err*oparg;\n            INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);\n        }\n\n        inst(INSTRUMENTED_POP_JUMP_IF_FALSE, ( -- )) {\n            PyObject *cond = POP();\n            int err = PyObject_IsTrue(cond);\n            Py_DECREF(cond);\n            ERROR_IF(err < 0, error);\n            _Py_CODEUNIT *here = next_instr-1;\n            assert(err == 0 || err == 1);\n            int offset = (1-err)*oparg;\n            INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);\n        }\n\n        inst(INSTRUMENTED_POP_JUMP_IF_NONE, ( -- )) {\n            PyObject *value = POP();\n            _Py_CODEUNIT *here = next_instr-1;\n            int offset;\n            if (Py_IsNone(value)) {\n                offset = oparg;\n            }\n            else {\n                Py_DECREF(value);\n                offset = 0;\n            }\n            INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);\n        }\n\n        inst(INSTRUMENTED_POP_JUMP_IF_NOT_NONE, ( -- )) {\n            PyObject *value = POP();\n            _Py_CODEUNIT *here = next_instr-1;\n            int offset;\n            if (Py_IsNone(value)) {\n                offset = 0;\n            }\n            else {\n                Py_DECREF(value);\n                 offset = oparg;\n            }\n            INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);\n        }\n\n        inst(EXTENDED_ARG, ( -- )) {\n            assert(oparg);\n            opcode = next_instr->op.code;\n            oparg = oparg << 8 | next_instr->op.arg;\n            PRE_DISPATCH_GOTO();\n            DISPATCH_GOTO();\n        }\n\n        inst(CACHE, (--)) {\n            assert(0 && \"Executing a cache.\");\n            Py_UNREACHABLE();\n        }\n\n        inst(RESERVED, (--)) {\n            assert(0 && \"Executing RESERVED instruction.\");\n            Py_UNREACHABLE();\n        }\n\n\n// END BYTECODES //\n\n    }\n dispatch_opcode:\n error:\n exception_unwind:\n exit_unwind:\n handle_eval_breaker:\n resume_frame:\n resume_with_error:\n start_frame:\n unbound_local_error:\n    ;\n}\n\n// Future families go below this point //\n"
  },
  {
    "path": "CeVal.c",
    "content": "/* Execute compiled code */\n\n#define _PY_INTERPRETER\n\n#include \"Python.h\"\n#include \"pycore_abstract.h\"      // _PyIndex_Check()\n#include \"pycore_call.h\"          // _PyObject_FastCallDictTstate()\n#include \"pycore_ceval.h\"         // _PyEval_SignalAsyncExc()\n#include \"pycore_code.h\"\n#include \"pycore_function.h\"\n#include \"pycore_intrinsics.h\"\n#include \"pycore_long.h\"          // _PyLong_GetZero()\n#include \"pycore_instruments.h\"\n#include \"pycore_object.h\"        // _PyObject_GC_TRACK()\n#include \"pycore_moduleobject.h\"  // PyModuleObject\n#include \"pycore_opcode.h\"        // EXTRA_CASES\n#include \"pycore_opcode_utils.h\"  // MAKE_FUNCTION_*\n#include \"pycore_pyerrors.h\"      // _PyErr_GetRaisedException()\n#include \"pycore_pystate.h\"       // _PyInterpreterState_GET()\n#include \"pycore_range.h\"         // _PyRangeIterObject\n#include \"pycore_sliceobject.h\"   // _PyBuildSlice_ConsumeRefs\n#include \"pycore_sysmodule.h\"     // _PySys_Audit()\n#include \"pycore_tuple.h\"         // _PyTuple_ITEMS()\n#include \"pycore_typeobject.h\"    // _PySuper_Lookup()\n#include \"pycore_emscripten_signal.h\"  // _Py_CHECK_EMSCRIPTEN_SIGNALS\n\n#include \"pycore_dict.h\"\n#include \"dictobject.h\"\n#include \"pycore_frame.h\"\n#include \"frameobject.h\"          // _PyInterpreterFrame_GetLine\n#include \"opcode.h\"\n#include \"pydtrace.h\"\n#include \"setobject.h\"\n#include \"structmember.h\"         // struct PyMemberDef, T_OFFSET_EX\n\n#include <ctype.h>\n#include <stdbool.h>\n\n#ifdef Py_DEBUG\n   /* For debugging the interpreter: */\n#  define LLTRACE  1      /* Low-level trace feature */\n#endif\n\n#if !defined(Py_BUILD_CORE)\n#  error \"ceval.c must be build with Py_BUILD_CORE define for best performance\"\n#endif\n\n#if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS)\n// GH-89279: The MSVC compiler does not inline these static inline functions\n// in PGO build in _PyEval_EvalFrameDefault(), because this function is over\n// the limit of PGO, and that limit cannot be configured.\n// Define them as macros to make sure that they are always inlined by the\n// preprocessor.\n\n#undef Py_DECREF\n#define Py_DECREF(arg) \\\n    do { \\\n        PyObject *op = _PyObject_CAST(arg); \\\n        if (_Py_IsImmortal(op)) { \\\n            break; \\\n        } \\\n        _Py_DECREF_STAT_INC(); \\\n        if (--op->ob_refcnt == 0) { \\\n            destructor dealloc = Py_TYPE(op)->tp_dealloc; \\\n            (*dealloc)(op); \\\n        } \\\n    } while (0)\n\n#undef Py_XDECREF\n#define Py_XDECREF(arg) \\\n    do { \\\n        PyObject *xop = _PyObject_CAST(arg); \\\n        if (xop != NULL) { \\\n            Py_DECREF(xop); \\\n        } \\\n    } while (0)\n\n#undef Py_IS_TYPE\n#define Py_IS_TYPE(ob, type) \\\n    (_PyObject_CAST(ob)->ob_type == (type))\n\n#undef _Py_DECREF_SPECIALIZED\n#define _Py_DECREF_SPECIALIZED(arg, dealloc) \\\n    do { \\\n        PyObject *op = _PyObject_CAST(arg); \\\n        if (_Py_IsImmortal(op)) { \\\n            break; \\\n        } \\\n        _Py_DECREF_STAT_INC(); \\\n        if (--op->ob_refcnt == 0) { \\\n            destructor d = (destructor)(dealloc); \\\n            d(op); \\\n        } \\\n    } while (0)\n#endif\n\n// GH-89279: Similar to above, force inlining by using a macro.\n#if defined(_MSC_VER) && SIZEOF_INT == 4\n#define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) (assert(sizeof((ATOMIC_VAL)->_value) == 4), *((volatile int*)&((ATOMIC_VAL)->_value)))\n#else\n#define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) _Py_atomic_load_relaxed(ATOMIC_VAL)\n#endif\n\n\n#ifdef LLTRACE\nstatic void\ndump_stack(_PyInterpreterFrame *frame, PyObject **stack_pointer)\n{\n    PyObject **stack_base = _PyFrame_Stackbase(frame);\n    PyObject *exc = PyErr_GetRaisedException();\n    printf(\"    stack=[\");\n    for (PyObject **ptr = stack_base; ptr < stack_pointer; ptr++) {\n        if (ptr != stack_base) {\n            printf(\", \");\n        }\n        if (PyObject_Print(*ptr, stdout, 0) != 0) {\n            PyErr_Clear();\n            printf(\"<%s object at %p>\",\n                   Py_TYPE(*ptr)->tp_name, (void *)(*ptr));\n        }\n    }\n    printf(\"]\\n\");\n    fflush(stdout);\n    PyErr_SetRaisedException(exc);\n}\n\nstatic void\nlltrace_instruction(_PyInterpreterFrame *frame,\n                    PyObject **stack_pointer,\n                    _Py_CODEUNIT *next_instr)\n{\n    /* This dump_stack() operation is risky, since the repr() of some\n       objects enters the interpreter recursively. It is also slow.\n       So you might want to comment it out. */\n    dump_stack(frame, stack_pointer);\n    int oparg = next_instr->op.arg;\n    int opcode = next_instr->op.code;\n    const char *opname = _PyOpcode_OpName[opcode];\n    assert(opname != NULL);\n    int offset = (int)(next_instr - _PyCode_CODE(frame->f_code));\n    if (HAS_ARG((int)_PyOpcode_Deopt[opcode])) {\n        printf(\"%d: %s %d\\n\", offset * 2, opname, oparg);\n    }\n    else {\n        printf(\"%d: %s\\n\", offset * 2, opname);\n    }\n    fflush(stdout);\n}\nstatic void\nlltrace_resume_frame(_PyInterpreterFrame *frame)\n{\n    PyObject *fobj = frame->f_funcobj;\n    if (frame->owner == FRAME_OWNED_BY_CSTACK ||\n        fobj == NULL ||\n        !PyFunction_Check(fobj)\n    ) {\n        printf(\"\\nResuming frame.\\n\");\n        return;\n    }\n    PyFunctionObject *f = (PyFunctionObject *)fobj;\n    PyObject *exc = PyErr_GetRaisedException();\n    PyObject *name = f->func_qualname;\n    if (name == NULL) {\n        name = f->func_name;\n    }\n    printf(\"\\nResuming frame\");\n    if (name) {\n        printf(\" for \");\n        if (PyObject_Print(name, stdout, 0) < 0) {\n            PyErr_Clear();\n        }\n    }\n    if (f->func_module) {\n        printf(\" in module \");\n        if (PyObject_Print(f->func_module, stdout, 0) < 0) {\n            PyErr_Clear();\n        }\n    }\n    printf(\"\\n\");\n    fflush(stdout);\n    PyErr_SetRaisedException(exc);\n}\n#endif\n\nstatic void monitor_raise(PyThreadState *tstate,\n                 _PyInterpreterFrame *frame,\n                 _Py_CODEUNIT *instr);\nstatic int monitor_stop_iteration(PyThreadState *tstate,\n                 _PyInterpreterFrame *frame,\n                 _Py_CODEUNIT *instr);\nstatic void monitor_unwind(PyThreadState *tstate,\n                 _PyInterpreterFrame *frame,\n                 _Py_CODEUNIT *instr);\nstatic void monitor_handled(PyThreadState *tstate,\n                 _PyInterpreterFrame *frame,\n                 _Py_CODEUNIT *instr, PyObject *exc);\nstatic void monitor_throw(PyThreadState *tstate,\n                 _PyInterpreterFrame *frame,\n                 _Py_CODEUNIT *instr);\n\nstatic PyObject * import_name(PyThreadState *, _PyInterpreterFrame *,\n                              PyObject *, PyObject *, PyObject *);\nstatic PyObject * import_from(PyThreadState *, PyObject *, PyObject *);\nstatic void format_exc_check_arg(PyThreadState *, PyObject *, const char *, PyObject *);\nstatic void format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg);\nstatic int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg);\nstatic int check_except_type_valid(PyThreadState *tstate, PyObject* right);\nstatic int check_except_star_type_valid(PyThreadState *tstate, PyObject* right);\nstatic void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs);\nstatic void format_awaitable_error(PyThreadState *, PyTypeObject *, int);\nstatic int get_exception_handler(PyCodeObject *, int, int*, int*, int*);\nstatic _PyInterpreterFrame *\n_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,\n                        PyObject *locals, PyObject* const* args,\n                        size_t argcount, PyObject *kwnames);\nstatic  _PyInterpreterFrame *\n_PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func,\n    PyObject *locals, Py_ssize_t nargs, PyObject *callargs, PyObject *kwargs);\nstatic void\n_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame);\n\n#define UNBOUNDLOCAL_ERROR_MSG \\\n    \"cannot access local variable '%s' where it is not associated with a value\"\n#define UNBOUNDFREE_ERROR_MSG \\\n    \"cannot access free variable '%s' where it is not associated with a\" \\\n    \" value in enclosing scope\"\n\n#ifdef HAVE_ERRNO_H\n#include <errno.h>\n#endif\n\nint\nPy_GetRecursionLimit(void)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    return interp->ceval.recursion_limit;\n}\n\nvoid\nPy_SetRecursionLimit(int new_limit)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    interp->ceval.recursion_limit = new_limit;\n    for (PyThreadState *p = interp->threads.head; p != NULL; p = p->next) {\n        int depth = p->py_recursion_limit - p->py_recursion_remaining;\n        p->py_recursion_limit = new_limit;\n        p->py_recursion_remaining = new_limit - depth;\n    }\n}\n\n/* The function _Py_EnterRecursiveCallTstate() only calls _Py_CheckRecursiveCall()\n   if the recursion_depth reaches recursion_limit. */\nint\n_Py_CheckRecursiveCall(PyThreadState *tstate, const char *where)\n{\n#ifdef USE_STACKCHECK\n    if (PyOS_CheckStack()) {\n        ++tstate->c_recursion_remaining;\n        _PyErr_SetString(tstate, PyExc_MemoryError, \"Stack overflow\");\n        return -1;\n    }\n#endif\n    if (tstate->recursion_headroom) {\n        if (tstate->c_recursion_remaining < -50) {\n            /* Overflowing while handling an overflow. Give up. */\n            Py_FatalError(\"Cannot recover from stack overflow.\");\n        }\n    }\n    else {\n        if (tstate->c_recursion_remaining <= 0) {\n            tstate->recursion_headroom++;\n            _PyErr_Format(tstate, PyExc_RecursionError,\n                        \"maximum recursion depth exceeded%s\",\n                        where);\n            tstate->recursion_headroom--;\n            ++tstate->c_recursion_remaining;\n            return -1;\n        }\n    }\n    return 0;\n}\n\n\nstatic const binaryfunc binary_ops[] = {\n    [NB_ADD] = PyNumber_Add,\n    [NB_AND] = PyNumber_And,\n    [NB_FLOOR_DIVIDE] = PyNumber_FloorDivide,\n    [NB_LSHIFT] = PyNumber_Lshift,\n    [NB_MATRIX_MULTIPLY] = PyNumber_MatrixMultiply,\n    [NB_MULTIPLY] = PyNumber_Multiply,\n    [NB_REMAINDER] = PyNumber_Remainder,\n    [NB_OR] = PyNumber_Or,\n    [NB_POWER] = _PyNumber_PowerNoMod,\n    [NB_RSHIFT] = PyNumber_Rshift,\n    [NB_SUBTRACT] = PyNumber_Subtract,\n    [NB_TRUE_DIVIDE] = PyNumber_TrueDivide,\n    [NB_XOR] = PyNumber_Xor,\n    [NB_INPLACE_ADD] = PyNumber_InPlaceAdd,\n    [NB_INPLACE_AND] = PyNumber_InPlaceAnd,\n    [NB_INPLACE_FLOOR_DIVIDE] = PyNumber_InPlaceFloorDivide,\n    [NB_INPLACE_LSHIFT] = PyNumber_InPlaceLshift,\n    [NB_INPLACE_MATRIX_MULTIPLY] = PyNumber_InPlaceMatrixMultiply,\n    [NB_INPLACE_MULTIPLY] = PyNumber_InPlaceMultiply,\n    [NB_INPLACE_REMAINDER] = PyNumber_InPlaceRemainder,\n    [NB_INPLACE_OR] = PyNumber_InPlaceOr,\n    [NB_INPLACE_POWER] = _PyNumber_InPlacePowerNoMod,\n    [NB_INPLACE_RSHIFT] = PyNumber_InPlaceRshift,\n    [NB_INPLACE_SUBTRACT] = PyNumber_InPlaceSubtract,\n    [NB_INPLACE_TRUE_DIVIDE] = PyNumber_InPlaceTrueDivide,\n    [NB_INPLACE_XOR] = PyNumber_InPlaceXor,\n};\n\n\n// PEP 634: Structural Pattern Matching\n\n\n// Return a tuple of values corresponding to keys, with error checks for\n// duplicate/missing keys.\nstatic PyObject*\nmatch_keys(PyThreadState *tstate, PyObject *map, PyObject *keys)\n{\n    assert(PyTuple_CheckExact(keys));\n    Py_ssize_t nkeys = PyTuple_GET_SIZE(keys);\n    if (!nkeys) {\n        // No keys means no items.\n        return PyTuple_New(0);\n    }\n    PyObject *seen = NULL;\n    PyObject *dummy = NULL;\n    PyObject *values = NULL;\n    PyObject *get = NULL;\n    // We use the two argument form of map.get(key, default) for two reasons:\n    // - Atomically check for a key and get its value without error handling.\n    // - Don't cause key creation or resizing in dict subclasses like\n    //   collections.defaultdict that define __missing__ (or similar).\n    int meth_found = _PyObject_GetMethod(map, &_Py_ID(get), &get);\n    if (get == NULL) {\n        goto fail;\n    }\n    seen = PySet_New(NULL);\n    if (seen == NULL) {\n        goto fail;\n    }\n    // dummy = object()\n    dummy = _PyObject_CallNoArgs((PyObject *)&PyBaseObject_Type);\n    if (dummy == NULL) {\n        goto fail;\n    }\n    values = PyTuple_New(nkeys);\n    if (values == NULL) {\n        goto fail;\n    }\n    for (Py_ssize_t i = 0; i < nkeys; i++) {\n        PyObject *key = PyTuple_GET_ITEM(keys, i);\n        if (PySet_Contains(seen, key) || PySet_Add(seen, key)) {\n            if (!_PyErr_Occurred(tstate)) {\n                // Seen it before!\n                _PyErr_Format(tstate, PyExc_ValueError,\n                              \"mapping pattern checks duplicate key (%R)\", key);\n            }\n            goto fail;\n        }\n        PyObject *args[] = { map, key, dummy };\n        PyObject *value = NULL;\n        if (meth_found) {\n            value = PyObject_Vectorcall(get, args, 3, NULL);\n        }\n        else {\n            value = PyObject_Vectorcall(get, &args[1], 2, NULL);\n        }\n        if (value == NULL) {\n            goto fail;\n        }\n        if (value == dummy) {\n            // key not in map!\n            Py_DECREF(value);\n            Py_DECREF(values);\n            // Return None:\n            values = Py_NewRef(Py_None);\n            goto done;\n        }\n        PyTuple_SET_ITEM(values, i, value);\n    }\n    // Success:\ndone:\n    Py_DECREF(get);\n    Py_DECREF(seen);\n    Py_DECREF(dummy);\n    return values;\nfail:\n    Py_XDECREF(get);\n    Py_XDECREF(seen);\n    Py_XDECREF(dummy);\n    Py_XDECREF(values);\n    return NULL;\n}\n\n// Extract a named attribute from the subject, with additional bookkeeping to\n// raise TypeErrors for repeated lookups. On failure, return NULL (with no\n// error set). Use _PyErr_Occurred(tstate) to disambiguate.\nstatic PyObject*\nmatch_class_attr(PyThreadState *tstate, PyObject *subject, PyObject *type,\n                 PyObject *name, PyObject *seen)\n{\n    assert(PyUnicode_CheckExact(name));\n    assert(PySet_CheckExact(seen));\n    if (PySet_Contains(seen, name) || PySet_Add(seen, name)) {\n        if (!_PyErr_Occurred(tstate)) {\n            // Seen it before!\n            _PyErr_Format(tstate, PyExc_TypeError,\n                          \"%s() got multiple sub-patterns for attribute %R\",\n                          ((PyTypeObject*)type)->tp_name, name);\n        }\n        return NULL;\n    }\n    PyObject *attr = PyObject_GetAttr(subject, name);\n    if (attr == NULL && _PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {\n        _PyErr_Clear(tstate);\n    }\n    return attr;\n}\n\n// On success (match), return a tuple of extracted attributes. On failure (no\n// match), return NULL. Use _PyErr_Occurred(tstate) to disambiguate.\nstatic PyObject*\nmatch_class(PyThreadState *tstate, PyObject *subject, PyObject *type,\n            Py_ssize_t nargs, PyObject *kwargs)\n{\n    if (!PyType_Check(type)) {\n        const char *e = \"called match pattern must be a class\";\n        _PyErr_Format(tstate, PyExc_TypeError, e);\n        return NULL;\n    }\n    assert(PyTuple_CheckExact(kwargs));\n    // First, an isinstance check:\n    if (PyObject_IsInstance(subject, type) <= 0) {\n        return NULL;\n    }\n    // So far so good:\n    PyObject *seen = PySet_New(NULL);\n    if (seen == NULL) {\n        return NULL;\n    }\n    PyObject *attrs = PyList_New(0);\n    if (attrs == NULL) {\n        Py_DECREF(seen);\n        return NULL;\n    }\n    // NOTE: From this point on, goto fail on failure:\n    PyObject *match_args = NULL;\n    // First, the positional subpatterns:\n    if (nargs) {\n        int match_self = 0;\n        match_args = PyObject_GetAttrString(type, \"__match_args__\");\n        if (match_args) {\n            if (!PyTuple_CheckExact(match_args)) {\n                const char *e = \"%s.__match_args__ must be a tuple (got %s)\";\n                _PyErr_Format(tstate, PyExc_TypeError, e,\n                              ((PyTypeObject *)type)->tp_name,\n                              Py_TYPE(match_args)->tp_name);\n                goto fail;\n            }\n        }\n        else if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {\n            _PyErr_Clear(tstate);\n            // _Py_TPFLAGS_MATCH_SELF is only acknowledged if the type does not\n            // define __match_args__. This is natural behavior for subclasses:\n            // it's as if __match_args__ is some \"magic\" value that is lost as\n            // soon as they redefine it.\n            match_args = PyTuple_New(0);\n            match_self = PyType_HasFeature((PyTypeObject*)type,\n                                            _Py_TPFLAGS_MATCH_SELF);\n        }\n        else {\n            goto fail;\n        }\n        assert(PyTuple_CheckExact(match_args));\n        Py_ssize_t allowed = match_self ? 1 : PyTuple_GET_SIZE(match_args);\n        if (allowed < nargs) {\n            const char *plural = (allowed == 1) ? \"\" : \"s\";\n            _PyErr_Format(tstate, PyExc_TypeError,\n                          \"%s() accepts %d positional sub-pattern%s (%d given)\",\n                          ((PyTypeObject*)type)->tp_name,\n                          allowed, plural, nargs);\n            goto fail;\n        }\n        if (match_self) {\n            // Easy. Copy the subject itself, and move on to kwargs.\n            PyList_Append(attrs, subject);\n        }\n        else {\n            for (Py_ssize_t i = 0; i < nargs; i++) {\n                PyObject *name = PyTuple_GET_ITEM(match_args, i);\n                if (!PyUnicode_CheckExact(name)) {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                  \"__match_args__ elements must be strings \"\n                                  \"(got %s)\", Py_TYPE(name)->tp_name);\n                    goto fail;\n                }\n                PyObject *attr = match_class_attr(tstate, subject, type, name,\n                                                  seen);\n                if (attr == NULL) {\n                    goto fail;\n                }\n                PyList_Append(attrs, attr);\n                Py_DECREF(attr);\n            }\n        }\n        Py_CLEAR(match_args);\n    }\n    // Finally, the keyword subpatterns:\n    for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwargs); i++) {\n        PyObject *name = PyTuple_GET_ITEM(kwargs, i);\n        PyObject *attr = match_class_attr(tstate, subject, type, name, seen);\n        if (attr == NULL) {\n            goto fail;\n        }\n        PyList_Append(attrs, attr);\n        Py_DECREF(attr);\n    }\n    Py_SETREF(attrs, PyList_AsTuple(attrs));\n    Py_DECREF(seen);\n    return attrs;\nfail:\n    // We really don't care whether an error was raised or not... that's our\n    // caller's problem. All we know is that the match failed.\n    Py_XDECREF(match_args);\n    Py_DECREF(seen);\n    Py_DECREF(attrs);\n    return NULL;\n}\n\n\nstatic int do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause);\nstatic int exception_group_match(\n    PyObject* exc_value, PyObject *match_type,\n    PyObject **match, PyObject **rest);\n\nstatic int unpack_iterable(PyThreadState *, PyObject *, int, int, PyObject **);\n\nPyObject *\nPyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (locals == NULL) {\n        locals = globals;\n    }\n    PyObject *builtins = _PyEval_BuiltinsFromGlobals(tstate, globals); // borrowed ref\n    if (builtins == NULL) {\n        return NULL;\n    }\n    PyFrameConstructor desc = {\n        .fc_globals = globals,\n        .fc_builtins = builtins,\n        .fc_name = ((PyCodeObject *)co)->co_name,\n        .fc_qualname = ((PyCodeObject *)co)->co_name,\n        .fc_code = co,\n        .fc_defaults = NULL,\n        .fc_kwdefaults = NULL,\n        .fc_closure = NULL\n    };\n    PyFunctionObject *func = _PyFunction_FromConstructor(&desc);\n    if (func == NULL) {\n        return NULL;\n    }\n    EVAL_CALL_STAT_INC(EVAL_CALL_LEGACY);\n    PyObject *res = _PyEval_Vector(tstate, func, locals, NULL, 0, NULL);\n    Py_DECREF(func);\n    return res;\n}\n\n\n/* Interpreter main loop */\n\nPyObject *\nPyEval_EvalFrame(PyFrameObject *f)\n{\n    /* Function kept for backward compatibility */\n    PyThreadState *tstate = _PyThreadState_GET();\n    return _PyEval_EvalFrame(tstate, f->f_frame, 0);\n}\n\nPyObject *\nPyEval_EvalFrameEx(PyFrameObject *f, int throwflag)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    return _PyEval_EvalFrame(tstate, f->f_frame, throwflag);\n}\n\n#include \"ceval_macros.h\"\n\n\nint _Py_CheckRecursiveCallPy(\n    PyThreadState *tstate)\n{\n    if (tstate->recursion_headroom) {\n        if (tstate->py_recursion_remaining < -50) {\n            /* Overflowing while handling an overflow. Give up. */\n            Py_FatalError(\"Cannot recover from Python stack overflow.\");\n        }\n    }\n    else {\n        if (tstate->py_recursion_remaining <= 0) {\n            tstate->recursion_headroom++;\n            _PyErr_Format(tstate, PyExc_RecursionError,\n                        \"maximum recursion depth exceeded\");\n            tstate->recursion_headroom--;\n            return -1;\n        }\n    }\n    return 0;\n}\n\nstatic inline int _Py_EnterRecursivePy(PyThreadState *tstate) {\n    return (tstate->py_recursion_remaining-- <= 0) &&\n        _Py_CheckRecursiveCallPy(tstate);\n}\n\n\nstatic inline void _Py_LeaveRecursiveCallPy(PyThreadState *tstate)  {\n    tstate->py_recursion_remaining++;\n}\n\n\n/* Disable unused label warnings.  They are handy for debugging, even\n   if computed gotos aren't used. */\n\n/* TBD - what about other compilers? */\n#if defined(__GNUC__)\n#  pragma GCC diagnostic push\n#  pragma GCC diagnostic ignored \"-Wunused-label\"\n#elif defined(_MSC_VER) /* MS_WINDOWS */\n#  pragma warning(push)\n#  pragma warning(disable:4102)\n#endif\n\nPyObject* _Py_HOT_FUNCTION\n_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)\n{\n    _Py_EnsureTstateNotNULL(tstate);\n    CALL_STAT_INC(pyeval_calls);\n\n#if USE_COMPUTED_GOTOS\n/* Import the static jump table */\n#include \"opcode_targets.h\"\n#endif\n\n#ifdef Py_STATS\n    int lastopcode = 0;\n#endif\n    // opcode is an 8-bit value to improve the code generated by MSVC\n    // for the big switch below (in combination with the EXTRA_CASES macro).\n    uint8_t opcode;        /* Current opcode */\n    int oparg;         /* Current opcode argument, if any */\n#ifdef LLTRACE\n    int lltrace = 0;\n#endif\n\n    _PyCFrame cframe;\n    _PyInterpreterFrame  entry_frame;\n    PyObject *kwnames = NULL; // Borrowed reference. Reset by CALL instructions.\n\n    /* WARNING: Because the _PyCFrame lives on the C stack,\n     * but can be accessed from a heap allocated object (tstate)\n     * strict stack discipline must be maintained.\n     */\n    _PyCFrame *prev_cframe = tstate->cframe;\n    cframe.previous = prev_cframe;\n    tstate->cframe = &cframe;\n\n    assert(tstate->interp->interpreter_trampoline != NULL);\n#ifdef Py_DEBUG\n    /* Set these to invalid but identifiable values for debugging. */\n    entry_frame.f_funcobj = (PyObject*)0xaaa0;\n    entry_frame.f_locals = (PyObject*)0xaaa1;\n    entry_frame.frame_obj = (PyFrameObject*)0xaaa2;\n    entry_frame.f_globals = (PyObject*)0xaaa3;\n    entry_frame.f_builtins = (PyObject*)0xaaa4;\n#endif\n    entry_frame.f_code = tstate->interp->interpreter_trampoline;\n    entry_frame.prev_instr =\n        _PyCode_CODE(tstate->interp->interpreter_trampoline);\n    entry_frame.stacktop = 0;\n    entry_frame.owner = FRAME_OWNED_BY_CSTACK;\n    entry_frame.return_offset = 0;\n    /* Push frame */\n    entry_frame.previous = prev_cframe->current_frame;\n    frame->previous = &entry_frame;\n    cframe.current_frame = frame;\n\n    if (_Py_EnterRecursiveCallTstate(tstate, \"\")) {\n        tstate->c_recursion_remaining--;\n        tstate->py_recursion_remaining--;\n        goto exit_unwind;\n    }\n\n    /* support for generator.throw() */\n    if (throwflag) {\n        if (_Py_EnterRecursivePy(tstate)) {\n            goto exit_unwind;\n        }\n        /* Because this avoids the RESUME,\n         * we need to update instrumentation */\n        _Py_Instrument(frame->f_code, tstate->interp);\n        monitor_throw(tstate, frame, frame->prev_instr);\n        /* TO DO -- Monitor throw entry. */\n        goto resume_with_error;\n    }\n\n    /* Local \"register\" variables.\n     * These are cached values from the frame and code object.  */\n\n    _Py_CODEUNIT *next_instr;\n    PyObject **stack_pointer;\n\n/* Sets the above local variables from the frame */\n#define SET_LOCALS_FROM_FRAME() \\\n    assert(_PyInterpreterFrame_LASTI(frame) >= -1); \\\n    /* Jump back to the last instruction executed... */ \\\n    next_instr = frame->prev_instr + 1; \\\n    stack_pointer = _PyFrame_GetStackPointer(frame);\n\nstart_frame:\n    if (_Py_EnterRecursivePy(tstate)) {\n        goto exit_unwind;\n    }\n\nresume_frame:\n    SET_LOCALS_FROM_FRAME();\n\n#ifdef LLTRACE\n    {\n        if (frame != &entry_frame) {\n            int r = PyDict_Contains(GLOBALS(), &_Py_ID(__lltrace__));\n            if (r < 0) {\n                goto exit_unwind;\n            }\n            lltrace = r;\n        }\n        if (lltrace) {\n            lltrace_resume_frame(frame);\n        }\n    }\n#endif\n\n#ifdef Py_DEBUG\n    /* _PyEval_EvalFrameDefault() must not be called with an exception set,\n       because it can clear it (directly or indirectly) and so the\n       caller loses its exception */\n    assert(!_PyErr_Occurred(tstate));\n#endif\n\n    DISPATCH();\n\nhandle_eval_breaker:\n\n    /* Do periodic things, like check for signals and async I/0.\n     * We need to do reasonably frequently, but not too frequently.\n     * All loops should include a check of the eval breaker.\n     * We also check on return from any builtin function.\n     */\n    if (_Py_HandlePending(tstate) != 0) {\n        goto error;\n    }\n    DISPATCH();\n\n    {\n    /* Start instructions */\n#if !USE_COMPUTED_GOTOS\n    dispatch_opcode:\n        switch (opcode)\n#endif\n        {\n\n#include \"generated_cases.c.h\"\n\n    /* INSTRUMENTED_LINE has to be here, rather than in bytecodes.c,\n     * because it needs to capture frame->prev_instr before it is updated,\n     * as happens in the standard instruction prologue.\n     */\n#if USE_COMPUTED_GOTOS\n        TARGET_INSTRUMENTED_LINE:\n#else\n        case INSTRUMENTED_LINE:\n#endif\n    {\n        _Py_CODEUNIT *prev = frame->prev_instr;\n        _Py_CODEUNIT *here = frame->prev_instr = next_instr;\n        _PyFrame_SetStackPointer(frame, stack_pointer);\n        int original_opcode = _Py_call_instrumentation_line(\n                tstate, frame, here, prev);\n        stack_pointer = _PyFrame_GetStackPointer(frame);\n        if (original_opcode < 0) {\n            next_instr = here+1;\n            goto error;\n        }\n        next_instr = frame->prev_instr;\n        if (next_instr != here) {\n            DISPATCH();\n        }\n        if (_PyOpcode_Caches[original_opcode]) {\n            _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1);\n            /* Prevent the underlying instruction from specializing\n             * and overwriting the instrumentation. */\n            INCREMENT_ADAPTIVE_COUNTER(cache->counter);\n        }\n        opcode = original_opcode;\n        DISPATCH_GOTO();\n    }\n\n\n#if USE_COMPUTED_GOTOS\n        _unknown_opcode:\n#else\n        EXTRA_CASES  // From opcode.h, a 'case' for each unused opcode\n#endif\n            /* Tell C compilers not to hold the opcode variable in the loop.\n               next_instr points the current instruction without TARGET(). */\n            opcode = next_instr->op.code;\n            _PyErr_Format(tstate, PyExc_SystemError,\n                          \"%U:%d: unknown opcode %d\",\n                          frame->f_code->co_filename,\n                          PyUnstable_InterpreterFrame_GetLine(frame),\n                          opcode);\n            goto error;\n\n        } /* End instructions */\n\n        /* This should never be reached. Every opcode should end with DISPATCH()\n           or goto error. */\n        Py_UNREACHABLE();\n\nunbound_local_error:\n        {\n            format_exc_check_arg(tstate, PyExc_UnboundLocalError,\n                UNBOUNDLOCAL_ERROR_MSG,\n                PyTuple_GetItem(frame->f_code->co_localsplusnames, oparg)\n            );\n            goto error;\n        }\n\npop_4_error:\n    STACK_SHRINK(1);\npop_3_error:\n    STACK_SHRINK(1);\npop_2_error:\n    STACK_SHRINK(1);\npop_1_error:\n    STACK_SHRINK(1);\nerror:\n        kwnames = NULL;\n        /* Double-check exception status. */\n#ifdef NDEBUG\n        if (!_PyErr_Occurred(tstate)) {\n            _PyErr_SetString(tstate, PyExc_SystemError,\n                             \"error return without exception set\");\n        }\n#else\n        assert(_PyErr_Occurred(tstate));\n#endif\n\n        /* Log traceback info. */\n        assert(frame != &entry_frame);\n        if (!_PyFrame_IsIncomplete(frame)) {\n            PyFrameObject *f = _PyFrame_GetFrameObject(frame);\n            if (f != NULL) {\n                PyTraceBack_Here(f);\n            }\n        }\n        monitor_raise(tstate, frame, next_instr-1);\n\nexception_unwind:\n        {\n            /* We can't use frame->f_lasti here, as RERAISE may have set it */\n            int offset = INSTR_OFFSET()-1;\n            int level, handler, lasti;\n            if (get_exception_handler(frame->f_code, offset, &level, &handler, &lasti) == 0) {\n                // No handlers, so exit.\n                assert(_PyErr_Occurred(tstate));\n\n                /* Pop remaining stack entries. */\n                PyObject **stackbase = _PyFrame_Stackbase(frame);\n                while (stack_pointer > stackbase) {\n                    PyObject *o = POP();\n                    Py_XDECREF(o);\n                }\n                assert(STACK_LEVEL() == 0);\n                _PyFrame_SetStackPointer(frame, stack_pointer);\n                monitor_unwind(tstate, frame, next_instr-1);\n                goto exit_unwind;\n            }\n\n            assert(STACK_LEVEL() >= level);\n            PyObject **new_top = _PyFrame_Stackbase(frame) + level;\n            while (stack_pointer > new_top) {\n                PyObject *v = POP();\n                Py_XDECREF(v);\n            }\n            if (lasti) {\n                int frame_lasti = _PyInterpreterFrame_LASTI(frame);\n                PyObject *lasti = PyLong_FromLong(frame_lasti);\n                if (lasti == NULL) {\n                    goto exception_unwind;\n                }\n                PUSH(lasti);\n            }\n\n            /* Make the raw exception data\n                available to the handler,\n                so a program can emulate the\n                Python main loop. */\n            PyObject *exc = _PyErr_GetRaisedException(tstate);\n            PUSH(exc);\n            JUMPTO(handler);\n            monitor_handled(tstate, frame, next_instr, exc);\n            /* Resume normal execution */\n            DISPATCH();\n        }\n    }\n\nexit_unwind:\n    assert(_PyErr_Occurred(tstate));\n    _Py_LeaveRecursiveCallPy(tstate);\n    assert(frame != &entry_frame);\n    // GH-99729: We need to unlink the frame *before* clearing it:\n    _PyInterpreterFrame *dying = frame;\n    frame = cframe.current_frame = dying->previous;\n    _PyEvalFrameClearAndPop(tstate, dying);\n    frame->return_offset = 0;\n    if (frame == &entry_frame) {\n        /* Restore previous cframe and exit */\n        tstate->cframe = cframe.previous;\n        assert(tstate->cframe->current_frame == frame->previous);\n        _Py_LeaveRecursiveCallTstate(tstate);\n        return NULL;\n    }\n\nresume_with_error:\n    SET_LOCALS_FROM_FRAME();\n    goto error;\n\n}\n#if defined(__GNUC__)\n#  pragma GCC diagnostic pop\n#elif defined(_MSC_VER) /* MS_WINDOWS */\n#  pragma warning(pop)\n#endif\n\nstatic void\nformat_missing(PyThreadState *tstate, const char *kind,\n               PyCodeObject *co, PyObject *names, PyObject *qualname)\n{\n    int err;\n    Py_ssize_t len = PyList_GET_SIZE(names);\n    PyObject *name_str, *comma, *tail, *tmp;\n\n    assert(PyList_CheckExact(names));\n    assert(len >= 1);\n    /* Deal with the joys of natural language. */\n    switch (len) {\n    case 1:\n        name_str = PyList_GET_ITEM(names, 0);\n        Py_INCREF(name_str);\n        break;\n    case 2:\n        name_str = PyUnicode_FromFormat(\"%U and %U\",\n                                        PyList_GET_ITEM(names, len - 2),\n                                        PyList_GET_ITEM(names, len - 1));\n        break;\n    default:\n        tail = PyUnicode_FromFormat(\", %U, and %U\",\n                                    PyList_GET_ITEM(names, len - 2),\n                                    PyList_GET_ITEM(names, len - 1));\n        if (tail == NULL)\n            return;\n        /* Chop off the last two objects in the list. This shouldn't actually\n           fail, but we can't be too careful. */\n        err = PyList_SetSlice(names, len - 2, len, NULL);\n        if (err == -1) {\n            Py_DECREF(tail);\n            return;\n        }\n        /* Stitch everything up into a nice comma-separated list. */\n        comma = PyUnicode_FromString(\", \");\n        if (comma == NULL) {\n            Py_DECREF(tail);\n            return;\n        }\n        tmp = PyUnicode_Join(comma, names);\n        Py_DECREF(comma);\n        if (tmp == NULL) {\n            Py_DECREF(tail);\n            return;\n        }\n        name_str = PyUnicode_Concat(tmp, tail);\n        Py_DECREF(tmp);\n        Py_DECREF(tail);\n        break;\n    }\n    if (name_str == NULL)\n        return;\n    _PyErr_Format(tstate, PyExc_TypeError,\n                  \"%U() missing %i required %s argument%s: %U\",\n                  qualname,\n                  len,\n                  kind,\n                  len == 1 ? \"\" : \"s\",\n                  name_str);\n    Py_DECREF(name_str);\n}\n\nstatic void\nmissing_arguments(PyThreadState *tstate, PyCodeObject *co,\n                  Py_ssize_t missing, Py_ssize_t defcount,\n                  PyObject **localsplus, PyObject *qualname)\n{\n    Py_ssize_t i, j = 0;\n    Py_ssize_t start, end;\n    int positional = (defcount != -1);\n    const char *kind = positional ? \"positional\" : \"keyword-only\";\n    PyObject *missing_names;\n\n    /* Compute the names of the arguments that are missing. */\n    missing_names = PyList_New(missing);\n    if (missing_names == NULL)\n        return;\n    if (positional) {\n        start = 0;\n        end = co->co_argcount - defcount;\n    }\n    else {\n        start = co->co_argcount;\n        end = start + co->co_kwonlyargcount;\n    }\n    for (i = start; i < end; i++) {\n        if (localsplus[i] == NULL) {\n            PyObject *raw = PyTuple_GET_ITEM(co->co_localsplusnames, i);\n            PyObject *name = PyObject_Repr(raw);\n            if (name == NULL) {\n                Py_DECREF(missing_names);\n                return;\n            }\n            PyList_SET_ITEM(missing_names, j++, name);\n        }\n    }\n    assert(j == missing);\n    format_missing(tstate, kind, co, missing_names, qualname);\n    Py_DECREF(missing_names);\n}\n\nstatic void\ntoo_many_positional(PyThreadState *tstate, PyCodeObject *co,\n                    Py_ssize_t given, PyObject *defaults,\n                    PyObject **localsplus, PyObject *qualname)\n{\n    int plural;\n    Py_ssize_t kwonly_given = 0;\n    Py_ssize_t i;\n    PyObject *sig, *kwonly_sig;\n    Py_ssize_t co_argcount = co->co_argcount;\n\n    assert((co->co_flags & CO_VARARGS) == 0);\n    /* Count missing keyword-only args. */\n    for (i = co_argcount; i < co_argcount + co->co_kwonlyargcount; i++) {\n        if (localsplus[i] != NULL) {\n            kwonly_given++;\n        }\n    }\n    Py_ssize_t defcount = defaults == NULL ? 0 : PyTuple_GET_SIZE(defaults);\n    if (defcount) {\n        Py_ssize_t atleast = co_argcount - defcount;\n        plural = 1;\n        sig = PyUnicode_FromFormat(\"from %zd to %zd\", atleast, co_argcount);\n    }\n    else {\n        plural = (co_argcount != 1);\n        sig = PyUnicode_FromFormat(\"%zd\", co_argcount);\n    }\n    if (sig == NULL)\n        return;\n    if (kwonly_given) {\n        const char *format = \" positional argument%s (and %zd keyword-only argument%s)\";\n        kwonly_sig = PyUnicode_FromFormat(format,\n                                          given != 1 ? \"s\" : \"\",\n                                          kwonly_given,\n                                          kwonly_given != 1 ? \"s\" : \"\");\n        if (kwonly_sig == NULL) {\n            Py_DECREF(sig);\n            return;\n        }\n    }\n    else {\n        /* This will not fail. */\n        kwonly_sig = PyUnicode_FromString(\"\");\n        assert(kwonly_sig != NULL);\n    }\n    _PyErr_Format(tstate, PyExc_TypeError,\n                  \"%U() takes %U positional argument%s but %zd%U %s given\",\n                  qualname,\n                  sig,\n                  plural ? \"s\" : \"\",\n                  given,\n                  kwonly_sig,\n                  given == 1 && !kwonly_given ? \"was\" : \"were\");\n    Py_DECREF(sig);\n    Py_DECREF(kwonly_sig);\n}\n\nstatic int\npositional_only_passed_as_keyword(PyThreadState *tstate, PyCodeObject *co,\n                                  Py_ssize_t kwcount, PyObject* kwnames,\n                                  PyObject *qualname)\n{\n    int posonly_conflicts = 0;\n    PyObject* posonly_names = PyList_New(0);\n    if (posonly_names == NULL) {\n        goto fail;\n    }\n    for(int k=0; k < co->co_posonlyargcount; k++){\n        PyObject* posonly_name = PyTuple_GET_ITEM(co->co_localsplusnames, k);\n\n        for (int k2=0; k2<kwcount; k2++){\n            /* Compare the pointers first and fallback to PyObject_RichCompareBool*/\n            PyObject* kwname = PyTuple_GET_ITEM(kwnames, k2);\n            if (kwname == posonly_name){\n                if(PyList_Append(posonly_names, kwname) != 0) {\n                    goto fail;\n                }\n                posonly_conflicts++;\n                continue;\n            }\n\n            int cmp = PyObject_RichCompareBool(posonly_name, kwname, Py_EQ);\n\n            if ( cmp > 0) {\n                if(PyList_Append(posonly_names, kwname) != 0) {\n                    goto fail;\n                }\n                posonly_conflicts++;\n            } else if (cmp < 0) {\n                goto fail;\n            }\n\n        }\n    }\n    if (posonly_conflicts) {\n        PyObject* comma = PyUnicode_FromString(\", \");\n        if (comma == NULL) {\n            goto fail;\n        }\n        PyObject* error_names = PyUnicode_Join(comma, posonly_names);\n        Py_DECREF(comma);\n        if (error_names == NULL) {\n            goto fail;\n        }\n        _PyErr_Format(tstate, PyExc_TypeError,\n                      \"%U() got some positional-only arguments passed\"\n                      \" as keyword arguments: '%U'\",\n                      qualname, error_names);\n        Py_DECREF(error_names);\n        goto fail;\n    }\n\n    Py_DECREF(posonly_names);\n    return 0;\n\nfail:\n    Py_XDECREF(posonly_names);\n    return 1;\n\n}\n\n\nstatic inline unsigned char *\nscan_back_to_entry_start(unsigned char *p) {\n    for (; (p[0]&128) == 0; p--);\n    return p;\n}\n\nstatic inline unsigned char *\nskip_to_next_entry(unsigned char *p, unsigned char *end) {\n    while (p < end && ((p[0] & 128) == 0)) {\n        p++;\n    }\n    return p;\n}\n\n\n#define MAX_LINEAR_SEARCH 40\n\nstatic int\nget_exception_handler(PyCodeObject *code, int index, int *level, int *handler, int *lasti)\n{\n    unsigned char *start = (unsigned char *)PyBytes_AS_STRING(code->co_exceptiontable);\n    unsigned char *end = start + PyBytes_GET_SIZE(code->co_exceptiontable);\n    /* Invariants:\n     * start_table == end_table OR\n     * start_table points to a legal entry and end_table points\n     * beyond the table or to a legal entry that is after index.\n     */\n    if (end - start > MAX_LINEAR_SEARCH) {\n        int offset;\n        parse_varint(start, &offset);\n        if (offset > index) {\n            return 0;\n        }\n        do {\n            unsigned char * mid = start + ((end-start)>>1);\n            mid = scan_back_to_entry_start(mid);\n            parse_varint(mid, &offset);\n            if (offset > index) {\n                end = mid;\n            }\n            else {\n                start = mid;\n            }\n\n        } while (end - start > MAX_LINEAR_SEARCH);\n    }\n    unsigned char *scan = start;\n    while (scan < end) {\n        int start_offset, size;\n        scan = parse_varint(scan, &start_offset);\n        if (start_offset > index) {\n            break;\n        }\n        scan = parse_varint(scan, &size);\n        if (start_offset + size > index) {\n            scan = parse_varint(scan, handler);\n            int depth_and_lasti;\n            parse_varint(scan, &depth_and_lasti);\n            *level = depth_and_lasti >> 1;\n            *lasti = depth_and_lasti & 1;\n            return 1;\n        }\n        scan = skip_to_next_entry(scan, end);\n    }\n    return 0;\n}\n\nstatic int\ninitialize_locals(PyThreadState *tstate, PyFunctionObject *func,\n    PyObject **localsplus, PyObject *const *args,\n    Py_ssize_t argcount, PyObject *kwnames)\n{\n    PyCodeObject *co = (PyCodeObject*)func->func_code;\n    const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount;\n\n    /* Create a dictionary for keyword parameters (**kwags) */\n    PyObject *kwdict;\n    Py_ssize_t i;\n    if (co->co_flags & CO_VARKEYWORDS) {\n        kwdict = PyDict_New();\n        if (kwdict == NULL) {\n            goto fail_pre_positional;\n        }\n        i = total_args;\n        if (co->co_flags & CO_VARARGS) {\n            i++;\n        }\n        assert(localsplus[i] == NULL);\n        localsplus[i] = kwdict;\n    }\n    else {\n        kwdict = NULL;\n    }\n\n    /* Copy all positional arguments into local variables */\n    Py_ssize_t j, n;\n    if (argcount > co->co_argcount) {\n        n = co->co_argcount;\n    }\n    else {\n        n = argcount;\n    }\n    for (j = 0; j < n; j++) {\n        PyObject *x = args[j];\n        assert(localsplus[j] == NULL);\n        localsplus[j] = x;\n    }\n\n    /* Pack other positional arguments into the *args argument */\n    if (co->co_flags & CO_VARARGS) {\n        PyObject *u = NULL;\n        if (argcount == n) {\n            u = Py_NewRef(&_Py_SINGLETON(tuple_empty));\n        }\n        else {\n            assert(args != NULL);\n            u = _PyTuple_FromArraySteal(args + n, argcount - n);\n        }\n        if (u == NULL) {\n            goto fail_post_positional;\n        }\n        assert(localsplus[total_args] == NULL);\n        localsplus[total_args] = u;\n    }\n    else if (argcount > n) {\n        /* Too many postional args. Error is reported later */\n        for (j = n; j < argcount; j++) {\n            Py_DECREF(args[j]);\n        }\n    }\n\n    /* Handle keyword arguments */\n    if (kwnames != NULL) {\n        Py_ssize_t kwcount = PyTuple_GET_SIZE(kwnames);\n        for (i = 0; i < kwcount; i++) {\n            PyObject **co_varnames;\n            PyObject *keyword = PyTuple_GET_ITEM(kwnames, i);\n            PyObject *value = args[i+argcount];\n            Py_ssize_t j;\n\n            if (keyword == NULL || !PyUnicode_Check(keyword)) {\n                _PyErr_Format(tstate, PyExc_TypeError,\n                            \"%U() keywords must be strings\",\n                          func->func_qualname);\n                goto kw_fail;\n            }\n\n            /* Speed hack: do raw pointer compares. As names are\n            normally interned this should almost always hit. */\n            co_varnames = ((PyTupleObject *)(co->co_localsplusnames))->ob_item;\n            for (j = co->co_posonlyargcount; j < total_args; j++) {\n                PyObject *varname = co_varnames[j];\n                if (varname == keyword) {\n                    goto kw_found;\n                }\n            }\n\n            /* Slow fallback, just in case */\n            for (j = co->co_posonlyargcount; j < total_args; j++) {\n                PyObject *varname = co_varnames[j];\n                int cmp = PyObject_RichCompareBool( keyword, varname, Py_EQ);\n                if (cmp > 0) {\n                    goto kw_found;\n                }\n                else if (cmp < 0) {\n                    goto kw_fail;\n                }\n            }\n\n            assert(j >= total_args);\n            if (kwdict == NULL) {\n\n                if (co->co_posonlyargcount\n                    && positional_only_passed_as_keyword(tstate, co,\n                                                        kwcount, kwnames,\n                                                        func->func_qualname))\n                {\n                    goto kw_fail;\n                }\n\n                _PyErr_Format(tstate, PyExc_TypeError,\n                            \"%U() got an unexpected keyword argument '%S'\",\n                          func->func_qualname, keyword);\n                goto kw_fail;\n            }\n\n            if (PyDict_SetItem(kwdict, keyword, value) == -1) {\n                goto kw_fail;\n            }\n            Py_DECREF(value);\n            continue;\n\n        kw_fail:\n            for (;i < kwcount; i++) {\n                PyObject *value = args[i+argcount];\n                Py_DECREF(value);\n            }\n            goto fail_post_args;\n\n        kw_found:\n            if (localsplus[j] != NULL) {\n                _PyErr_Format(tstate, PyExc_TypeError,\n                            \"%U() got multiple values for argument '%S'\",\n                          func->func_qualname, keyword);\n                goto kw_fail;\n            }\n            localsplus[j] = value;\n        }\n    }\n\n    /* Check the number of positional arguments */\n    if ((argcount > co->co_argcount) && !(co->co_flags & CO_VARARGS)) {\n        too_many_positional(tstate, co, argcount, func->func_defaults, localsplus,\n                            func->func_qualname);\n        goto fail_post_args;\n    }\n\n    /* Add missing positional arguments (copy default values from defs) */\n    if (argcount < co->co_argcount) {\n        Py_ssize_t defcount = func->func_defaults == NULL ? 0 : PyTuple_GET_SIZE(func->func_defaults);\n        Py_ssize_t m = co->co_argcount - defcount;\n        Py_ssize_t missing = 0;\n        for (i = argcount; i < m; i++) {\n            if (localsplus[i] == NULL) {\n                missing++;\n            }\n        }\n        if (missing) {\n            missing_arguments(tstate, co, missing, defcount, localsplus,\n                              func->func_qualname);\n            goto fail_post_args;\n        }\n        if (n > m)\n            i = n - m;\n        else\n            i = 0;\n        if (defcount) {\n            PyObject **defs = &PyTuple_GET_ITEM(func->func_defaults, 0);\n            for (; i < defcount; i++) {\n                if (localsplus[m+i] == NULL) {\n                    PyObject *def = defs[i];\n                    localsplus[m+i] = Py_NewRef(def);\n                }\n            }\n        }\n    }\n\n    /* Add missing keyword arguments (copy default values from kwdefs) */\n    if (co->co_kwonlyargcount > 0) {\n        Py_ssize_t missing = 0;\n        for (i = co->co_argcount; i < total_args; i++) {\n            if (localsplus[i] != NULL)\n                continue;\n            PyObject *varname = PyTuple_GET_ITEM(co->co_localsplusnames, i);\n            if (func->func_kwdefaults != NULL) {\n                PyObject *def = PyDict_GetItemWithError(func->func_kwdefaults, varname);\n                if (def) {\n                    localsplus[i] = Py_NewRef(def);\n                    continue;\n                }\n                else if (_PyErr_Occurred(tstate)) {\n                    goto fail_post_args;\n                }\n            }\n            missing++;\n        }\n        if (missing) {\n            missing_arguments(tstate, co, missing, -1, localsplus,\n                              func->func_qualname);\n            goto fail_post_args;\n        }\n    }\n    return 0;\n\nfail_pre_positional:\n    for (j = 0; j < argcount; j++) {\n        Py_DECREF(args[j]);\n    }\n    /* fall through */\nfail_post_positional:\n    if (kwnames) {\n        Py_ssize_t kwcount = PyTuple_GET_SIZE(kwnames);\n        for (j = argcount; j < argcount+kwcount; j++) {\n            Py_DECREF(args[j]);\n        }\n    }\n    /* fall through */\nfail_post_args:\n    return -1;\n}\n\nstatic void\nclear_thread_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)\n{\n    assert(frame->owner == FRAME_OWNED_BY_THREAD);\n    // Make sure that this is, indeed, the top frame. We can't check this in\n    // _PyThreadState_PopFrame, since f_code is already cleared at that point:\n    assert((PyObject **)frame + frame->f_code->co_framesize ==\n        tstate->datastack_top);\n    tstate->c_recursion_remaining--;\n    assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);\n    _PyFrame_ClearExceptCode(frame);\n    Py_DECREF(frame->f_code);\n    tstate->c_recursion_remaining++;\n    _PyThreadState_PopFrame(tstate, frame);\n}\n\nstatic void\nclear_gen_frame(PyThreadState *tstate, _PyInterpreterFrame * frame)\n{\n    assert(frame->owner == FRAME_OWNED_BY_GENERATOR);\n    PyGenObject *gen = _PyFrame_GetGenerator(frame);\n    gen->gi_frame_state = FRAME_CLEARED;\n    assert(tstate->exc_info == &gen->gi_exc_state);\n    tstate->exc_info = gen->gi_exc_state.previous_item;\n    gen->gi_exc_state.previous_item = NULL;\n    tstate->c_recursion_remaining--;\n    assert(frame->frame_obj == NULL || frame->frame_obj->f_frame == frame);\n    _PyFrame_ClearExceptCode(frame);\n    tstate->c_recursion_remaining++;\n    frame->previous = NULL;\n}\n\nstatic void\n_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame)\n{\n    if (frame->owner == FRAME_OWNED_BY_THREAD) {\n        clear_thread_frame(tstate, frame);\n    }\n    else {\n        clear_gen_frame(tstate, frame);\n    }\n}\n\n/* Consumes references to func, locals and all the args */\nstatic _PyInterpreterFrame *\n_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,\n                        PyObject *locals, PyObject* const* args,\n                        size_t argcount, PyObject *kwnames)\n{\n    PyCodeObject * code = (PyCodeObject *)func->func_code;\n    CALL_STAT_INC(frames_pushed);\n    _PyInterpreterFrame *frame = _PyThreadState_PushFrame(tstate, code->co_framesize);\n    if (frame == NULL) {\n        goto fail;\n    }\n    _PyFrame_Initialize(frame, func, locals, code, 0);\n    if (initialize_locals(tstate, func, frame->localsplus, args, argcount, kwnames)) {\n        assert(frame->owner == FRAME_OWNED_BY_THREAD);\n        clear_thread_frame(tstate, frame);\n        return NULL;\n    }\n    return frame;\nfail:\n    /* Consume the references */\n    for (size_t i = 0; i < argcount; i++) {\n        Py_DECREF(args[i]);\n    }\n    if (kwnames) {\n        Py_ssize_t kwcount = PyTuple_GET_SIZE(kwnames);\n        for (Py_ssize_t i = 0; i < kwcount; i++) {\n            Py_DECREF(args[i+argcount]);\n        }\n    }\n    PyErr_NoMemory();\n    return NULL;\n}\n\n/* Same as _PyEvalFramePushAndInit but takes an args tuple and kwargs dict.\n   Steals references to func, callargs and kwargs.\n*/\nstatic _PyInterpreterFrame *\n_PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func,\n    PyObject *locals, Py_ssize_t nargs, PyObject *callargs, PyObject *kwargs)\n{\n    bool has_dict = (kwargs != NULL && PyDict_GET_SIZE(kwargs) > 0);\n    PyObject *kwnames = NULL;\n    PyObject *const *newargs;\n    if (has_dict) {\n        newargs = _PyStack_UnpackDict(tstate, _PyTuple_ITEMS(callargs), nargs, kwargs, &kwnames);\n        if (newargs == NULL) {\n            Py_DECREF(func);\n            goto error;\n        }\n    }\n    else {\n        newargs = &PyTuple_GET_ITEM(callargs, 0);\n        /* We need to incref all our args since the new frame steals the references. */\n        for (Py_ssize_t i = 0; i < nargs; ++i) {\n            Py_INCREF(PyTuple_GET_ITEM(callargs, i));\n        }\n    }\n    _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(\n        tstate, (PyFunctionObject *)func, locals,\n        newargs, nargs, kwnames\n    );\n    if (has_dict) {\n        _PyStack_UnpackDict_FreeNoDecRef(newargs, kwnames);\n    }\n    /* No need to decref func here because the reference has been stolen by\n       _PyEvalFramePushAndInit.\n    */\n    Py_DECREF(callargs);\n    Py_XDECREF(kwargs);\n    return new_frame;\nerror:\n    Py_DECREF(callargs);\n    Py_XDECREF(kwargs);\n    return NULL;\n}\n\nPyObject *\n_PyEval_Vector(PyThreadState *tstate, PyFunctionObject *func,\n               PyObject *locals,\n               PyObject* const* args, size_t argcount,\n               PyObject *kwnames)\n{\n    /* _PyEvalFramePushAndInit consumes the references\n     * to func, locals and all its arguments */\n    Py_INCREF(func);\n    Py_XINCREF(locals);\n    for (size_t i = 0; i < argcount; i++) {\n        Py_INCREF(args[i]);\n    }\n    if (kwnames) {\n        Py_ssize_t kwcount = PyTuple_GET_SIZE(kwnames);\n        for (Py_ssize_t i = 0; i < kwcount; i++) {\n            Py_INCREF(args[i+argcount]);\n        }\n    }\n    _PyInterpreterFrame *frame = _PyEvalFramePushAndInit(\n        tstate, func, locals, args, argcount, kwnames);\n    if (frame == NULL) {\n        return NULL;\n    }\n    EVAL_CALL_STAT_INC(EVAL_CALL_VECTOR);\n    return _PyEval_EvalFrame(tstate, frame, 0);\n}\n\n/* Legacy API */\nPyObject *\nPyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,\n                  PyObject *const *args, int argcount,\n                  PyObject *const *kws, int kwcount,\n                  PyObject *const *defs, int defcount,\n                  PyObject *kwdefs, PyObject *closure)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *res = NULL;\n    PyObject *defaults = _PyTuple_FromArray(defs, defcount);\n    if (defaults == NULL) {\n        return NULL;\n    }\n    PyObject *builtins = _PyEval_BuiltinsFromGlobals(tstate, globals); // borrowed ref\n    if (builtins == NULL) {\n        Py_DECREF(defaults);\n        return NULL;\n    }\n    if (locals == NULL) {\n        locals = globals;\n    }\n    PyObject *kwnames = NULL;\n    PyObject *const *allargs;\n    PyObject **newargs = NULL;\n    PyFunctionObject *func = NULL;\n    if (kwcount == 0) {\n        allargs = args;\n    }\n    else {\n        kwnames = PyTuple_New(kwcount);\n        if (kwnames == NULL) {\n            goto fail;\n        }\n        newargs = PyMem_Malloc(sizeof(PyObject *)*(kwcount+argcount));\n        if (newargs == NULL) {\n            goto fail;\n        }\n        for (int i = 0; i < argcount; i++) {\n            newargs[i] = args[i];\n        }\n        for (int i = 0; i < kwcount; i++) {\n            PyTuple_SET_ITEM(kwnames, i, Py_NewRef(kws[2*i]));\n            newargs[argcount+i] = kws[2*i+1];\n        }\n        allargs = newargs;\n    }\n    PyFrameConstructor constr = {\n        .fc_globals = globals,\n        .fc_builtins = builtins,\n        .fc_name = ((PyCodeObject *)_co)->co_name,\n        .fc_qualname = ((PyCodeObject *)_co)->co_name,\n        .fc_code = _co,\n        .fc_defaults = defaults,\n        .fc_kwdefaults = kwdefs,\n        .fc_closure = closure\n    };\n    func = _PyFunction_FromConstructor(&constr);\n    if (func == NULL) {\n        goto fail;\n    }\n    EVAL_CALL_STAT_INC(EVAL_CALL_LEGACY);\n    res = _PyEval_Vector(tstate, func, locals,\n                         allargs, argcount,\n                         kwnames);\nfail:\n    Py_XDECREF(func);\n    Py_XDECREF(kwnames);\n    PyMem_Free(newargs);\n    Py_DECREF(defaults);\n    return res;\n}\n\n\n/* Logic for the raise statement (too complicated for inlining).\n   This *consumes* a reference count to each of its arguments. */\nstatic int\ndo_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause)\n{\n    PyObject *type = NULL, *value = NULL;\n\n    if (exc == NULL) {\n        /* Reraise */\n        _PyErr_StackItem *exc_info = _PyErr_GetTopmostException(tstate);\n        exc = exc_info->exc_value;\n        if (Py_IsNone(exc) || exc == NULL) {\n            _PyErr_SetString(tstate, PyExc_RuntimeError,\n                             \"No active exception to reraise\");\n            return 0;\n        }\n        Py_INCREF(exc);\n        assert(PyExceptionInstance_Check(exc));\n        _PyErr_SetRaisedException(tstate, exc);\n        return 1;\n    }\n\n    /* We support the following forms of raise:\n       raise\n       raise <instance>\n       raise <type> */\n\n    if (PyExceptionClass_Check(exc)) {\n        type = exc;\n        value = _PyObject_CallNoArgs(exc);\n        if (value == NULL)\n            goto raise_error;\n        if (!PyExceptionInstance_Check(value)) {\n            _PyErr_Format(tstate, PyExc_TypeError,\n                          \"calling %R should have returned an instance of \"\n                          \"BaseException, not %R\",\n                          type, Py_TYPE(value));\n             goto raise_error;\n        }\n    }\n    else if (PyExceptionInstance_Check(exc)) {\n        value = exc;\n        type = PyExceptionInstance_Class(exc);\n        Py_INCREF(type);\n    }\n    else {\n        /* Not something you can raise.  You get an exception\n           anyway, just not what you specified :-) */\n        Py_DECREF(exc);\n        _PyErr_SetString(tstate, PyExc_TypeError,\n                         \"exceptions must derive from BaseException\");\n        goto raise_error;\n    }\n\n    assert(type != NULL);\n    assert(value != NULL);\n\n    if (cause) {\n        PyObject *fixed_cause;\n        if (PyExceptionClass_Check(cause)) {\n            fixed_cause = _PyObject_CallNoArgs(cause);\n            if (fixed_cause == NULL)\n                goto raise_error;\n            Py_DECREF(cause);\n        }\n        else if (PyExceptionInstance_Check(cause)) {\n            fixed_cause = cause;\n        }\n        else if (Py_IsNone(cause)) {\n            Py_DECREF(cause);\n            fixed_cause = NULL;\n        }\n        else {\n            _PyErr_SetString(tstate, PyExc_TypeError,\n                             \"exception causes must derive from \"\n                             \"BaseException\");\n            goto raise_error;\n        }\n        PyException_SetCause(value, fixed_cause);\n    }\n\n    _PyErr_SetObject(tstate, type, value);\n    /* _PyErr_SetObject incref's its arguments */\n    Py_DECREF(value);\n    Py_DECREF(type);\n    return 0;\n\nraise_error:\n    Py_XDECREF(value);\n    Py_XDECREF(type);\n    Py_XDECREF(cause);\n    return 0;\n}\n\n/* Logic for matching an exception in an except* clause (too\n   complicated for inlining).\n*/\n\nstatic int\nexception_group_match(PyObject* exc_value, PyObject *match_type,\n                      PyObject **match, PyObject **rest)\n{\n    if (Py_IsNone(exc_value)) {\n        *match = Py_NewRef(Py_None);\n        *rest = Py_NewRef(Py_None);\n        return 0;\n    }\n    assert(PyExceptionInstance_Check(exc_value));\n\n    if (PyErr_GivenExceptionMatches(exc_value, match_type)) {\n        /* Full match of exc itself */\n        bool is_eg = _PyBaseExceptionGroup_Check(exc_value);\n        if (is_eg) {\n            *match = Py_NewRef(exc_value);\n        }\n        else {\n            /* naked exception - wrap it */\n            PyObject *excs = PyTuple_Pack(1, exc_value);\n            if (excs == NULL) {\n                return -1;\n            }\n            PyObject *wrapped = _PyExc_CreateExceptionGroup(\"\", excs);\n            Py_DECREF(excs);\n            if (wrapped == NULL) {\n                return -1;\n            }\n            *match = wrapped;\n        }\n        *rest = Py_NewRef(Py_None);\n        return 0;\n    }\n\n    /* exc_value does not match match_type.\n     * Check for partial match if it's an exception group.\n     */\n    if (_PyBaseExceptionGroup_Check(exc_value)) {\n        PyObject *pair = PyObject_CallMethod(exc_value, \"split\", \"(O)\",\n                                             match_type);\n        if (pair == NULL) {\n            return -1;\n        }\n        assert(PyTuple_CheckExact(pair));\n        assert(PyTuple_GET_SIZE(pair) == 2);\n        *match = Py_NewRef(PyTuple_GET_ITEM(pair, 0));\n        *rest = Py_NewRef(PyTuple_GET_ITEM(pair, 1));\n        Py_DECREF(pair);\n        return 0;\n    }\n    /* no match */\n    *match = Py_NewRef(Py_None);\n    *rest = Py_NewRef(exc_value);\n    return 0;\n}\n\n/* Iterate v argcnt times and store the results on the stack (via decreasing\n   sp).  Return 1 for success, 0 if error.\n\n   If argcntafter == -1, do a simple unpack. If it is >= 0, do an unpack\n   with a variable target.\n*/\n\nstatic int\nunpack_iterable(PyThreadState *tstate, PyObject *v,\n                int argcnt, int argcntafter, PyObject **sp)\n{\n    int i = 0, j = 0;\n    Py_ssize_t ll = 0;\n    PyObject *it;  /* iter(v) */\n    PyObject *w;\n    PyObject *l = NULL; /* variable list */\n\n    assert(v != NULL);\n\n    it = PyObject_GetIter(v);\n    if (it == NULL) {\n        if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&\n            Py_TYPE(v)->tp_iter == NULL && !PySequence_Check(v))\n        {\n            _PyErr_Format(tstate, PyExc_TypeError,\n                          \"cannot unpack non-iterable %.200s object\",\n                          Py_TYPE(v)->tp_name);\n        }\n        return 0;\n    }\n\n    for (; i < argcnt; i++) {\n        w = PyIter_Next(it);\n        if (w == NULL) {\n            /* Iterator done, via error or exhaustion. */\n            if (!_PyErr_Occurred(tstate)) {\n                if (argcntafter == -1) {\n                    _PyErr_Format(tstate, PyExc_ValueError,\n                                  \"not enough values to unpack \"\n                                  \"(expected %d, got %d)\",\n                                  argcnt, i);\n                }\n                else {\n                    _PyErr_Format(tstate, PyExc_ValueError,\n                                  \"not enough values to unpack \"\n                                  \"(expected at least %d, got %d)\",\n                                  argcnt + argcntafter, i);\n                }\n            }\n            goto Error;\n        }\n        *--sp = w;\n    }\n\n    if (argcntafter == -1) {\n        /* We better have exhausted the iterator now. */\n        w = PyIter_Next(it);\n        if (w == NULL) {\n            if (_PyErr_Occurred(tstate))\n                goto Error;\n            Py_DECREF(it);\n            return 1;\n        }\n        Py_DECREF(w);\n        _PyErr_Format(tstate, PyExc_ValueError,\n                      \"too many values to unpack (expected %d)\",\n                      argcnt);\n        goto Error;\n    }\n\n    l = PySequence_List(it);\n    if (l == NULL)\n        goto Error;\n    *--sp = l;\n    i++;\n\n    ll = PyList_GET_SIZE(l);\n    if (ll < argcntafter) {\n        _PyErr_Format(tstate, PyExc_ValueError,\n            \"not enough values to unpack (expected at least %d, got %zd)\",\n            argcnt + argcntafter, argcnt + ll);\n        goto Error;\n    }\n\n    /* Pop the \"after-variable\" args off the list. */\n    for (j = argcntafter; j > 0; j--, i++) {\n        *--sp = PyList_GET_ITEM(l, ll - j);\n    }\n    /* Resize the list. */\n    Py_SET_SIZE(l, ll - argcntafter);\n    Py_DECREF(it);\n    return 1;\n\nError:\n    for (; i > 0; i--, sp++)\n        Py_DECREF(*sp);\n    Py_XDECREF(it);\n    return 0;\n}\n\nstatic int\ndo_monitor_exc(PyThreadState *tstate, _PyInterpreterFrame *frame,\n               _Py_CODEUNIT *instr, int event)\n{\n    assert(event < PY_MONITORING_UNGROUPED_EVENTS);\n    PyObject *exc = PyErr_GetRaisedException();\n    assert(exc != NULL);\n    int err = _Py_call_instrumentation_arg(tstate, event, frame, instr, exc);\n    if (err == 0) {\n        PyErr_SetRaisedException(exc);\n    }\n    else {\n        Py_DECREF(exc);\n    }\n    return err;\n}\n\nstatic inline int\nno_tools_for_event(PyThreadState *tstate, _PyInterpreterFrame *frame, int event)\n{\n    _PyCoMonitoringData *data = frame->f_code->_co_monitoring;\n    if (data) {\n        if (data->active_monitors.tools[event] == 0) {\n            return 1;\n        }\n    }\n    else {\n        if (tstate->interp->monitors.tools[event] == 0) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\nstatic void\nmonitor_raise(PyThreadState *tstate, _PyInterpreterFrame *frame,\n              _Py_CODEUNIT *instr)\n{\n    if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_RAISE)) {\n        return;\n    }\n    do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_RAISE);\n}\n\nstatic int\nmonitor_stop_iteration(PyThreadState *tstate, _PyInterpreterFrame *frame,\n                       _Py_CODEUNIT *instr)\n{\n    if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_STOP_ITERATION)) {\n        return 0;\n    }\n    return do_monitor_exc(tstate, frame, instr, PY_MONITORING_EVENT_STOP_ITERATION);\n}\n\nstatic void\nmonitor_unwind(PyThreadState *tstate,\n               _PyInterpreterFrame *frame,\n               _Py_CODEUNIT *instr)\n{\n    if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_PY_UNWIND)) {\n        return;\n    }\n    _Py_call_instrumentation_exc0(tstate, PY_MONITORING_EVENT_PY_UNWIND, frame, instr);\n}\n\n\nstatic void\nmonitor_handled(PyThreadState *tstate,\n                _PyInterpreterFrame *frame,\n                _Py_CODEUNIT *instr, PyObject *exc)\n{\n    if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_EXCEPTION_HANDLED)) {\n        return;\n    }\n    _Py_call_instrumentation_arg(tstate, PY_MONITORING_EVENT_EXCEPTION_HANDLED, frame, instr, exc);\n}\n\nstatic void\nmonitor_throw(PyThreadState *tstate,\n              _PyInterpreterFrame *frame,\n              _Py_CODEUNIT *instr)\n{\n    if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_PY_THROW)) {\n        return;\n    }\n    _Py_call_instrumentation_exc0(tstate, PY_MONITORING_EVENT_PY_THROW, frame, instr);\n}\n\nvoid\nPyThreadState_EnterTracing(PyThreadState *tstate)\n{\n    assert(tstate->tracing >= 0);\n    tstate->tracing++;\n}\n\nvoid\nPyThreadState_LeaveTracing(PyThreadState *tstate)\n{\n    assert(tstate->tracing > 0);\n    tstate->tracing--;\n}\n\n\nPyObject*\n_PyEval_CallTracing(PyObject *func, PyObject *args)\n{\n    // Save and disable tracing\n    PyThreadState *tstate = _PyThreadState_GET();\n    int save_tracing = tstate->tracing;\n    tstate->tracing = 0;\n\n    // Call the tracing function\n    PyObject *result = PyObject_Call(func, args, NULL);\n\n    // Restore tracing\n    tstate->tracing = save_tracing;\n    return result;\n}\n\nvoid\nPyEval_SetProfile(Py_tracefunc func, PyObject *arg)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (_PyEval_SetProfile(tstate, func, arg) < 0) {\n        /* Log _PySys_Audit() error */\n        _PyErr_WriteUnraisableMsg(\"in PyEval_SetProfile\", NULL);\n    }\n}\n\nvoid\nPyEval_SetProfileAllThreads(Py_tracefunc func, PyObject *arg)\n{\n    PyThreadState *this_tstate = _PyThreadState_GET();\n    PyInterpreterState* interp = this_tstate->interp;\n\n    _PyRuntimeState *runtime = &_PyRuntime;\n    HEAD_LOCK(runtime);\n    PyThreadState* ts = PyInterpreterState_ThreadHead(interp);\n    HEAD_UNLOCK(runtime);\n\n    while (ts) {\n        if (_PyEval_SetProfile(ts, func, arg) < 0) {\n            _PyErr_WriteUnraisableMsg(\"in PyEval_SetProfileAllThreads\", NULL);\n        }\n        HEAD_LOCK(runtime);\n        ts = PyThreadState_Next(ts);\n        HEAD_UNLOCK(runtime);\n    }\n}\n\nvoid\nPyEval_SetTrace(Py_tracefunc func, PyObject *arg)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (_PyEval_SetTrace(tstate, func, arg) < 0) {\n        /* Log _PySys_Audit() error */\n        _PyErr_WriteUnraisableMsg(\"in PyEval_SetTrace\", NULL);\n    }\n}\n\nvoid\nPyEval_SetTraceAllThreads(Py_tracefunc func, PyObject *arg)\n{\n    PyThreadState *this_tstate = _PyThreadState_GET();\n    PyInterpreterState* interp = this_tstate->interp;\n\n    _PyRuntimeState *runtime = &_PyRuntime;\n    HEAD_LOCK(runtime);\n    PyThreadState* ts = PyInterpreterState_ThreadHead(interp);\n    HEAD_UNLOCK(runtime);\n\n    while (ts) {\n        if (_PyEval_SetTrace(ts, func, arg) < 0) {\n            _PyErr_WriteUnraisableMsg(\"in PyEval_SetTraceAllThreads\", NULL);\n        }\n        HEAD_LOCK(runtime);\n        ts = PyThreadState_Next(ts);\n        HEAD_UNLOCK(runtime);\n    }\n}\n\nint\n_PyEval_SetCoroutineOriginTrackingDepth(int depth)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (depth < 0) {\n        _PyErr_SetString(tstate, PyExc_ValueError, \"depth must be >= 0\");\n        return -1;\n    }\n    tstate->coroutine_origin_tracking_depth = depth;\n    return 0;\n}\n\n\nint\n_PyEval_GetCoroutineOriginTrackingDepth(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    return tstate->coroutine_origin_tracking_depth;\n}\n\nint\n_PyEval_SetAsyncGenFirstiter(PyObject *firstiter)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    if (_PySys_Audit(tstate, \"sys.set_asyncgen_hook_firstiter\", NULL) < 0) {\n        return -1;\n    }\n\n    Py_XSETREF(tstate->async_gen_firstiter, Py_XNewRef(firstiter));\n    return 0;\n}\n\nPyObject *\n_PyEval_GetAsyncGenFirstiter(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    return tstate->async_gen_firstiter;\n}\n\nint\n_PyEval_SetAsyncGenFinalizer(PyObject *finalizer)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    if (_PySys_Audit(tstate, \"sys.set_asyncgen_hook_finalizer\", NULL) < 0) {\n        return -1;\n    }\n\n    Py_XSETREF(tstate->async_gen_finalizer, Py_XNewRef(finalizer));\n    return 0;\n}\n\nPyObject *\n_PyEval_GetAsyncGenFinalizer(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    return tstate->async_gen_finalizer;\n}\n\n_PyInterpreterFrame *\n_PyEval_GetFrame(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    return _PyThreadState_GetFrame(tstate);\n}\n\nPyFrameObject *\nPyEval_GetFrame(void)\n{\n    _PyInterpreterFrame *frame = _PyEval_GetFrame();\n    if (frame == NULL) {\n        return NULL;\n    }\n    PyFrameObject *f = _PyFrame_GetFrameObject(frame);\n    if (f == NULL) {\n        PyErr_Clear();\n    }\n    return f;\n}\n\nPyObject *\n_PyEval_GetBuiltins(PyThreadState *tstate)\n{\n    _PyInterpreterFrame *frame = _PyThreadState_GetFrame(tstate);\n    if (frame != NULL) {\n        return frame->f_builtins;\n    }\n    return tstate->interp->builtins;\n}\n\nPyObject *\nPyEval_GetBuiltins(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    return _PyEval_GetBuiltins(tstate);\n}\n\n/* Convenience function to get a builtin from its name */\nPyObject *\n_PyEval_GetBuiltin(PyObject *name)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *attr = PyDict_GetItemWithError(PyEval_GetBuiltins(), name);\n    if (attr) {\n        Py_INCREF(attr);\n    }\n    else if (!_PyErr_Occurred(tstate)) {\n        _PyErr_SetObject(tstate, PyExc_AttributeError, name);\n    }\n    return attr;\n}\n\nPyObject *\n_PyEval_GetBuiltinId(_Py_Identifier *name)\n{\n    return _PyEval_GetBuiltin(_PyUnicode_FromId(name));\n}\n\nPyObject *\nPyEval_GetLocals(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n     _PyInterpreterFrame *current_frame = _PyThreadState_GetFrame(tstate);\n    if (current_frame == NULL) {\n        _PyErr_SetString(tstate, PyExc_SystemError, \"frame does not exist\");\n        return NULL;\n    }\n\n    if (_PyFrame_FastToLocalsWithError(current_frame) < 0) {\n        return NULL;\n    }\n\n    PyObject *locals = current_frame->f_locals;\n    assert(locals != NULL);\n    return locals;\n}\n\nPyObject *\nPyEval_GetGlobals(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyInterpreterFrame *current_frame = _PyThreadState_GetFrame(tstate);\n    if (current_frame == NULL) {\n        return NULL;\n    }\n    return current_frame->f_globals;\n}\n\nint\nPyEval_MergeCompilerFlags(PyCompilerFlags *cf)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyInterpreterFrame *current_frame = tstate->cframe->current_frame;\n    int result = cf->cf_flags != 0;\n\n    if (current_frame != NULL) {\n        const int codeflags = current_frame->f_code->co_flags;\n        const int compilerflags = codeflags & PyCF_MASK;\n        if (compilerflags) {\n            result = 1;\n            cf->cf_flags |= compilerflags;\n        }\n    }\n    return result;\n}\n\n\nconst char *\nPyEval_GetFuncName(PyObject *func)\n{\n    if (PyMethod_Check(func))\n        return PyEval_GetFuncName(PyMethod_GET_FUNCTION(func));\n    else if (PyFunction_Check(func))\n        return PyUnicode_AsUTF8(((PyFunctionObject*)func)->func_name);\n    else if (PyCFunction_Check(func))\n        return ((PyCFunctionObject*)func)->m_ml->ml_name;\n    else\n        return Py_TYPE(func)->tp_name;\n}\n\nconst char *\nPyEval_GetFuncDesc(PyObject *func)\n{\n    if (PyMethod_Check(func))\n        return \"()\";\n    else if (PyFunction_Check(func))\n        return \"()\";\n    else if (PyCFunction_Check(func))\n        return \"()\";\n    else\n        return \" object\";\n}\n\n/* Extract a slice index from a PyLong or an object with the\n   nb_index slot defined, and store in *pi.\n   Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,\n   and silently boost values less than PY_SSIZE_T_MIN to PY_SSIZE_T_MIN.\n   Return 0 on error, 1 on success.\n*/\nint\n_PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (!Py_IsNone(v)) {\n        Py_ssize_t x;\n        if (_PyIndex_Check(v)) {\n            x = PyNumber_AsSsize_t(v, NULL);\n            if (x == -1 && _PyErr_Occurred(tstate))\n                return 0;\n        }\n        else {\n            _PyErr_SetString(tstate, PyExc_TypeError,\n                             \"slice indices must be integers or \"\n                             \"None or have an __index__ method\");\n            return 0;\n        }\n        *pi = x;\n    }\n    return 1;\n}\n\nint\n_PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    Py_ssize_t x;\n    if (_PyIndex_Check(v)) {\n        x = PyNumber_AsSsize_t(v, NULL);\n        if (x == -1 && _PyErr_Occurred(tstate))\n            return 0;\n    }\n    else {\n        _PyErr_SetString(tstate, PyExc_TypeError,\n                         \"slice indices must be integers or \"\n                         \"have an __index__ method\");\n        return 0;\n    }\n    *pi = x;\n    return 1;\n}\n\nstatic PyObject *\nimport_name(PyThreadState *tstate, _PyInterpreterFrame *frame,\n            PyObject *name, PyObject *fromlist, PyObject *level)\n{\n    PyObject *import_func, *res;\n    PyObject* stack[5];\n\n    import_func = _PyDict_GetItemWithError(frame->f_builtins, &_Py_ID(__import__));\n    if (import_func == NULL) {\n        if (!_PyErr_Occurred(tstate)) {\n            _PyErr_SetString(tstate, PyExc_ImportError, \"__import__ not found\");\n        }\n        return NULL;\n    }\n    PyObject *locals = frame->f_locals;\n    /* Fast path for not overloaded __import__. */\n    if (_PyImport_IsDefaultImportFunc(tstate->interp, import_func)) {\n        int ilevel = _PyLong_AsInt(level);\n        if (ilevel == -1 && _PyErr_Occurred(tstate)) {\n            return NULL;\n        }\n        res = PyImport_ImportModuleLevelObject(\n                        name,\n                        frame->f_globals,\n                        locals == NULL ? Py_None :locals,\n                        fromlist,\n                        ilevel);\n        return res;\n    }\n\n    Py_INCREF(import_func);\n\n    stack[0] = name;\n    stack[1] = frame->f_globals;\n    stack[2] = locals == NULL ? Py_None : locals;\n    stack[3] = fromlist;\n    stack[4] = level;\n    res = _PyObject_FastCall(import_func, stack, 5);\n    Py_DECREF(import_func);\n    return res;\n}\n\nstatic PyObject *\nimport_from(PyThreadState *tstate, PyObject *v, PyObject *name)\n{\n    PyObject *x;\n    PyObject *fullmodname, *pkgname, *pkgpath, *pkgname_or_unknown, *errmsg;\n\n    if (_PyObject_LookupAttr(v, name, &x) != 0) {\n        return x;\n    }\n    /* Issue #17636: in case this failed because of a circular relative\n       import, try to fallback on reading the module directly from\n       sys.modules. */\n    pkgname = PyObject_GetAttr(v, &_Py_ID(__name__));\n    if (pkgname == NULL) {\n        goto error;\n    }\n    if (!PyUnicode_Check(pkgname)) {\n        Py_CLEAR(pkgname);\n        goto error;\n    }\n    fullmodname = PyUnicode_FromFormat(\"%U.%U\", pkgname, name);\n    if (fullmodname == NULL) {\n        Py_DECREF(pkgname);\n        return NULL;\n    }\n    x = PyImport_GetModule(fullmodname);\n    Py_DECREF(fullmodname);\n    if (x == NULL && !_PyErr_Occurred(tstate)) {\n        goto error;\n    }\n    Py_DECREF(pkgname);\n    return x;\n error:\n    pkgpath = PyModule_GetFilenameObject(v);\n    if (pkgname == NULL) {\n        pkgname_or_unknown = PyUnicode_FromString(\"<unknown module name>\");\n        if (pkgname_or_unknown == NULL) {\n            Py_XDECREF(pkgpath);\n            return NULL;\n        }\n    } else {\n        pkgname_or_unknown = pkgname;\n    }\n\n    if (pkgpath == NULL || !PyUnicode_Check(pkgpath)) {\n        _PyErr_Clear(tstate);\n        errmsg = PyUnicode_FromFormat(\n            \"cannot import name %R from %R (unknown location)\",\n            name, pkgname_or_unknown\n        );\n        /* NULL checks for errmsg and pkgname done by PyErr_SetImportError. */\n        _PyErr_SetImportErrorWithNameFrom(errmsg, pkgname, NULL, name);\n    }\n    else {\n        PyObject *spec = PyObject_GetAttr(v, &_Py_ID(__spec__));\n        const char *fmt =\n            _PyModuleSpec_IsInitializing(spec) ?\n            \"cannot import name %R from partially initialized module %R \"\n            \"(most likely due to a circular import) (%S)\" :\n            \"cannot import name %R from %R (%S)\";\n        Py_XDECREF(spec);\n\n        errmsg = PyUnicode_FromFormat(fmt, name, pkgname_or_unknown, pkgpath);\n        /* NULL checks for errmsg and pkgname done by PyErr_SetImportError. */\n        _PyErr_SetImportErrorWithNameFrom(errmsg, pkgname, pkgpath, name);\n    }\n\n    Py_XDECREF(errmsg);\n    Py_XDECREF(pkgname_or_unknown);\n    Py_XDECREF(pkgpath);\n    return NULL;\n}\n\n#define CANNOT_CATCH_MSG \"catching classes that do not inherit from \"\\\n                         \"BaseException is not allowed\"\n\n#define CANNOT_EXCEPT_STAR_EG \"catching ExceptionGroup with except* \"\\\n                              \"is not allowed. Use except instead.\"\n\nstatic int\ncheck_except_type_valid(PyThreadState *tstate, PyObject* right)\n{\n    if (PyTuple_Check(right)) {\n        Py_ssize_t i, length;\n        length = PyTuple_GET_SIZE(right);\n        for (i = 0; i < length; i++) {\n            PyObject *exc = PyTuple_GET_ITEM(right, i);\n            if (!PyExceptionClass_Check(exc)) {\n                _PyErr_SetString(tstate, PyExc_TypeError,\n                    CANNOT_CATCH_MSG);\n                return -1;\n            }\n        }\n    }\n    else {\n        if (!PyExceptionClass_Check(right)) {\n            _PyErr_SetString(tstate, PyExc_TypeError,\n                CANNOT_CATCH_MSG);\n            return -1;\n        }\n    }\n    return 0;\n}\n\nstatic int\ncheck_except_star_type_valid(PyThreadState *tstate, PyObject* right)\n{\n    if (check_except_type_valid(tstate, right) < 0) {\n        return -1;\n    }\n\n    /* reject except *ExceptionGroup */\n\n    int is_subclass = 0;\n    if (PyTuple_Check(right)) {\n        Py_ssize_t length = PyTuple_GET_SIZE(right);\n        for (Py_ssize_t i = 0; i < length; i++) {\n            PyObject *exc = PyTuple_GET_ITEM(right, i);\n            is_subclass = PyObject_IsSubclass(exc, PyExc_BaseExceptionGroup);\n            if (is_subclass < 0) {\n                return -1;\n            }\n            if (is_subclass) {\n                break;\n            }\n        }\n    }\n    else {\n        is_subclass = PyObject_IsSubclass(right, PyExc_BaseExceptionGroup);\n        if (is_subclass < 0) {\n            return -1;\n        }\n    }\n    if (is_subclass) {\n        _PyErr_SetString(tstate, PyExc_TypeError,\n            CANNOT_EXCEPT_STAR_EG);\n            return -1;\n    }\n    return 0;\n}\n\nstatic int\ncheck_args_iterable(PyThreadState *tstate, PyObject *func, PyObject *args)\n{\n    if (Py_TYPE(args)->tp_iter == NULL && !PySequence_Check(args)) {\n        /* check_args_iterable() may be called with a live exception:\n         * clear it to prevent calling _PyObject_FunctionStr() with an\n         * exception set. */\n        _PyErr_Clear(tstate);\n        PyObject *funcstr = _PyObject_FunctionStr(func);\n        if (funcstr != NULL) {\n            _PyErr_Format(tstate, PyExc_TypeError,\n                          \"%U argument after * must be an iterable, not %.200s\",\n                          funcstr, Py_TYPE(args)->tp_name);\n            Py_DECREF(funcstr);\n        }\n        return -1;\n    }\n    return 0;\n}\n\nstatic void\nformat_kwargs_error(PyThreadState *tstate, PyObject *func, PyObject *kwargs)\n{\n    /* _PyDict_MergeEx raises attribute\n     * error (percolated from an attempt\n     * to get 'keys' attribute) instead of\n     * a type error if its second argument\n     * is not a mapping.\n     */\n    if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {\n        _PyErr_Clear(tstate);\n        PyObject *funcstr = _PyObject_FunctionStr(func);\n        if (funcstr != NULL) {\n            _PyErr_Format(\n                tstate, PyExc_TypeError,\n                \"%U argument after ** must be a mapping, not %.200s\",\n                funcstr, Py_TYPE(kwargs)->tp_name);\n            Py_DECREF(funcstr);\n        }\n    }\n    else if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n        PyObject *exc = _PyErr_GetRaisedException(tstate);\n        PyObject *args = ((PyBaseExceptionObject *)exc)->args;\n        if (exc && PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1) {\n            _PyErr_Clear(tstate);\n            PyObject *funcstr = _PyObject_FunctionStr(func);\n            if (funcstr != NULL) {\n                PyObject *key = PyTuple_GET_ITEM(args, 0);\n                _PyErr_Format(\n                    tstate, PyExc_TypeError,\n                    \"%U got multiple values for keyword argument '%S'\",\n                    funcstr, key);\n                Py_DECREF(funcstr);\n            }\n            Py_XDECREF(exc);\n        }\n        else {\n            _PyErr_SetRaisedException(tstate, exc);\n        }\n    }\n}\n\nstatic void\nformat_exc_check_arg(PyThreadState *tstate, PyObject *exc,\n                     const char *format_str, PyObject *obj)\n{\n    const char *obj_str;\n\n    if (!obj)\n        return;\n\n    obj_str = PyUnicode_AsUTF8(obj);\n    if (!obj_str)\n        return;\n\n    _PyErr_Format(tstate, exc, format_str, obj_str);\n\n    if (exc == PyExc_NameError) {\n        // Include the name in the NameError exceptions to offer suggestions later.\n        PyObject *exc = PyErr_GetRaisedException();\n        if (PyErr_GivenExceptionMatches(exc, PyExc_NameError)) {\n            if (((PyNameErrorObject*)exc)->name == NULL) {\n                // We do not care if this fails because we are going to restore the\n                // NameError anyway.\n                (void)PyObject_SetAttr(exc, &_Py_ID(name), obj);\n            }\n        }\n        PyErr_SetRaisedException(exc);\n    }\n}\n\nstatic void\nformat_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg)\n{\n    PyObject *name;\n    /* Don't stomp existing exception */\n    if (_PyErr_Occurred(tstate))\n        return;\n    name = PyTuple_GET_ITEM(co->co_localsplusnames, oparg);\n    if (oparg < PyCode_GetFirstFree(co)) {\n        format_exc_check_arg(tstate, PyExc_UnboundLocalError,\n                             UNBOUNDLOCAL_ERROR_MSG, name);\n    } else {\n        format_exc_check_arg(tstate, PyExc_NameError,\n                             UNBOUNDFREE_ERROR_MSG, name);\n    }\n}\n\nstatic void\nformat_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int oparg)\n{\n    if (type->tp_as_async == NULL || type->tp_as_async->am_await == NULL) {\n        if (oparg == 1) {\n            _PyErr_Format(tstate, PyExc_TypeError,\n                          \"'async with' received an object from __aenter__ \"\n                          \"that does not implement __await__: %.100s\",\n                          type->tp_name);\n        }\n        else if (oparg == 2) {\n            _PyErr_Format(tstate, PyExc_TypeError,\n                          \"'async with' received an object from __aexit__ \"\n                          \"that does not implement __await__: %.100s\",\n                          type->tp_name);\n        }\n    }\n}\n\n\nPy_ssize_t\nPyUnstable_Eval_RequestCodeExtraIndex(freefunc free)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    Py_ssize_t new_index;\n\n    if (interp->co_extra_user_count == MAX_CO_EXTRA_USERS - 1) {\n        return -1;\n    }\n    new_index = interp->co_extra_user_count++;\n    interp->co_extra_freefuncs[new_index] = free;\n    return new_index;\n}\n\n/* Implement Py_EnterRecursiveCall() and Py_LeaveRecursiveCall() as functions\n   for the limited API. */\n\nint Py_EnterRecursiveCall(const char *where)\n{\n    return _Py_EnterRecursiveCall(where);\n}\n\nvoid Py_LeaveRecursiveCall(void)\n{\n    _Py_LeaveRecursiveCall();\n}\n"
  },
  {
    "path": "Ceval_Gil.c",
    "content": "\n#include \"Python.h\"\n#include \"pycore_atomic.h\"        // _Py_atomic_int\n#include \"pycore_ceval.h\"         // _PyEval_SignalReceived()\n#include \"pycore_pyerrors.h\"      // _PyErr_GetRaisedException()\n#include \"pycore_pylifecycle.h\"   // _PyErr_Print()\n#include \"pycore_initconfig.h\"    // _PyStatus_OK()\n#include \"pycore_interp.h\"        // _Py_RunGC()\n#include \"pycore_pymem.h\"         // _PyMem_IsPtrFreed()\n\n/*\n   Notes about the implementation:\n\n   - The GIL is just a boolean variable (locked) whose access is protected\n     by a mutex (gil_mutex), and whose changes are signalled by a condition\n     variable (gil_cond). gil_mutex is taken for short periods of time,\n     and therefore mostly uncontended.\n\n   - In the GIL-holding thread, the main loop (PyEval_EvalFrameEx) must be\n     able to release the GIL on demand by another thread. A volatile boolean\n     variable (gil_drop_request) is used for that purpose, which is checked\n     at every turn of the eval loop. That variable is set after a wait of\n     `interval` microseconds on `gil_cond` has timed out.\n\n      [Actually, another volatile boolean variable (eval_breaker) is used\n       which ORs several conditions into one. Volatile booleans are\n       sufficient as inter-thread signalling means since Python is run\n       on cache-coherent architectures only.]\n\n   - A thread wanting to take the GIL will first let pass a given amount of\n     time (`interval` microseconds) before setting gil_drop_request. This\n     encourages a defined switching period, but doesn't enforce it since\n     opcodes can take an arbitrary time to execute.\n\n     The `interval` value is available for the user to read and modify\n     using the Python API `sys.{get,set}switchinterval()`.\n\n   - When a thread releases the GIL and gil_drop_request is set, that thread\n     ensures that another GIL-awaiting thread gets scheduled.\n     It does so by waiting on a condition variable (switch_cond) until\n     the value of last_holder is changed to something else than its\n     own thread state pointer, indicating that another thread was able to\n     take the GIL.\n\n     This is meant to prohibit the latency-adverse behaviour on multi-core\n     machines where one thread would speculatively release the GIL, but still\n     run and end up being the first to re-acquire it, making the \"timeslices\"\n     much longer than expected.\n     (Note: this mechanism is enabled with FORCE_SWITCHING above)\n*/\n\n// GH-89279: Force inlining by using a macro.\n#if defined(_MSC_VER) && SIZEOF_INT == 4\n#define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) (assert(sizeof((ATOMIC_VAL)->_value) == 4), *((volatile int*)&((ATOMIC_VAL)->_value)))\n#else\n#define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) _Py_atomic_load_relaxed(ATOMIC_VAL)\n#endif\n\n/* This can set eval_breaker to 0 even though gil_drop_request became\n   1.  We believe this is all right because the eval loop will release\n   the GIL eventually anyway. */\nstatic inline void\nCOMPUTE_EVAL_BREAKER(PyInterpreterState *interp,\n                     struct _ceval_runtime_state *ceval,\n                     struct _ceval_state *ceval2)\n{\n    _Py_atomic_store_relaxed(&ceval2->eval_breaker,\n        _Py_atomic_load_relaxed_int32(&ceval2->gil_drop_request)\n        | (_Py_atomic_load_relaxed_int32(&ceval->signals_pending)\n           && _Py_ThreadCanHandleSignals(interp))\n        | (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do)\n           && _Py_ThreadCanHandlePendingCalls())\n        | ceval2->pending.async_exc\n        | _Py_atomic_load_relaxed_int32(&ceval2->gc_scheduled));\n}\n\n\nstatic inline void\nSET_GIL_DROP_REQUEST(PyInterpreterState *interp)\n{\n    struct _ceval_state *ceval2 = &interp->ceval;\n    _Py_atomic_store_relaxed(&ceval2->gil_drop_request, 1);\n    _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1);\n}\n\n\nstatic inline void\nRESET_GIL_DROP_REQUEST(PyInterpreterState *interp)\n{\n    struct _ceval_runtime_state *ceval = &interp->runtime->ceval;\n    struct _ceval_state *ceval2 = &interp->ceval;\n    _Py_atomic_store_relaxed(&ceval2->gil_drop_request, 0);\n    COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);\n}\n\n\nstatic inline void\nSIGNAL_PENDING_CALLS(PyInterpreterState *interp)\n{\n    struct _ceval_runtime_state *ceval = &interp->runtime->ceval;\n    struct _ceval_state *ceval2 = &interp->ceval;\n    _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 1);\n    COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);\n}\n\n\nstatic inline void\nUNSIGNAL_PENDING_CALLS(PyInterpreterState *interp)\n{\n    struct _ceval_runtime_state *ceval = &interp->runtime->ceval;\n    struct _ceval_state *ceval2 = &interp->ceval;\n    _Py_atomic_store_relaxed(&ceval2->pending.calls_to_do, 0);\n    COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);\n}\n\n\nstatic inline void\nSIGNAL_PENDING_SIGNALS(PyInterpreterState *interp, int force)\n{\n    struct _ceval_runtime_state *ceval = &interp->runtime->ceval;\n    struct _ceval_state *ceval2 = &interp->ceval;\n    _Py_atomic_store_relaxed(&ceval->signals_pending, 1);\n    if (force) {\n        _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1);\n    }\n    else {\n        /* eval_breaker is not set to 1 if thread_can_handle_signals() is false */\n        COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);\n    }\n}\n\n\nstatic inline void\nUNSIGNAL_PENDING_SIGNALS(PyInterpreterState *interp)\n{\n    struct _ceval_runtime_state *ceval = &interp->runtime->ceval;\n    struct _ceval_state *ceval2 = &interp->ceval;\n    _Py_atomic_store_relaxed(&ceval->signals_pending, 0);\n    COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);\n}\n\n\nstatic inline void\nSIGNAL_ASYNC_EXC(PyInterpreterState *interp)\n{\n    struct _ceval_state *ceval2 = &interp->ceval;\n    ceval2->pending.async_exc = 1;\n    _Py_atomic_store_relaxed(&ceval2->eval_breaker, 1);\n}\n\n\nstatic inline void\nUNSIGNAL_ASYNC_EXC(PyInterpreterState *interp)\n{\n    struct _ceval_runtime_state *ceval = &interp->runtime->ceval;\n    struct _ceval_state *ceval2 = &interp->ceval;\n    ceval2->pending.async_exc = 0;\n    COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);\n}\n\n#ifndef NDEBUG\n/* Ensure that tstate is valid */\nstatic int\nis_tstate_valid(PyThreadState *tstate)\n{\n    assert(!_PyMem_IsPtrFreed(tstate));\n    assert(!_PyMem_IsPtrFreed(tstate->interp));\n    return 1;\n}\n#endif\n\n/*\n * Implementation of the Global Interpreter Lock (GIL).\n */\n\n#include <stdlib.h>\n#include <errno.h>\n\n#include \"pycore_atomic.h\"\n\n\n#include \"condvar.h\"\n\n#define MUTEX_INIT(mut) \\\n    if (PyMUTEX_INIT(&(mut))) { \\\n        Py_FatalError(\"PyMUTEX_INIT(\" #mut \") failed\"); };\n#define MUTEX_FINI(mut) \\\n    if (PyMUTEX_FINI(&(mut))) { \\\n        Py_FatalError(\"PyMUTEX_FINI(\" #mut \") failed\"); };\n#define MUTEX_LOCK(mut) \\\n    if (PyMUTEX_LOCK(&(mut))) { \\\n        Py_FatalError(\"PyMUTEX_LOCK(\" #mut \") failed\"); };\n#define MUTEX_UNLOCK(mut) \\\n    if (PyMUTEX_UNLOCK(&(mut))) { \\\n        Py_FatalError(\"PyMUTEX_UNLOCK(\" #mut \") failed\"); };\n\n#define COND_INIT(cond) \\\n    if (PyCOND_INIT(&(cond))) { \\\n        Py_FatalError(\"PyCOND_INIT(\" #cond \") failed\"); };\n#define COND_FINI(cond) \\\n    if (PyCOND_FINI(&(cond))) { \\\n        Py_FatalError(\"PyCOND_FINI(\" #cond \") failed\"); };\n#define COND_SIGNAL(cond) \\\n    if (PyCOND_SIGNAL(&(cond))) { \\\n        Py_FatalError(\"PyCOND_SIGNAL(\" #cond \") failed\"); };\n#define COND_WAIT(cond, mut) \\\n    if (PyCOND_WAIT(&(cond), &(mut))) { \\\n        Py_FatalError(\"PyCOND_WAIT(\" #cond \") failed\"); };\n#define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \\\n    { \\\n        int r = PyCOND_TIMEDWAIT(&(cond), &(mut), (microseconds)); \\\n        if (r < 0) \\\n            Py_FatalError(\"PyCOND_WAIT(\" #cond \") failed\"); \\\n        if (r) /* 1 == timeout, 2 == impl. can't say, so assume timeout */ \\\n            timeout_result = 1; \\\n        else \\\n            timeout_result = 0; \\\n    } \\\n\n\n#define DEFAULT_INTERVAL 5000\n\nstatic void _gil_initialize(struct _gil_runtime_state *gil)\n{\n    _Py_atomic_int uninitialized = {-1};\n    gil->locked = uninitialized;\n    gil->interval = DEFAULT_INTERVAL;\n}\n\nstatic int gil_created(struct _gil_runtime_state *gil)\n{\n    if (gil == NULL) {\n        return 0;\n    }\n    return (_Py_atomic_load_explicit(&gil->locked, _Py_memory_order_acquire) >= 0);\n}\n\nstatic void create_gil(struct _gil_runtime_state *gil)\n{\n    MUTEX_INIT(gil->mutex);\n#ifdef FORCE_SWITCHING\n    MUTEX_INIT(gil->switch_mutex);\n#endif\n    COND_INIT(gil->cond);\n#ifdef FORCE_SWITCHING\n    COND_INIT(gil->switch_cond);\n#endif\n    _Py_atomic_store_relaxed(&gil->last_holder, 0);\n    _Py_ANNOTATE_RWLOCK_CREATE(&gil->locked);\n    _Py_atomic_store_explicit(&gil->locked, 0, _Py_memory_order_release);\n}\n\nstatic void destroy_gil(struct _gil_runtime_state *gil)\n{\n    /* some pthread-like implementations tie the mutex to the cond\n     * and must have the cond destroyed first.\n     */\n    COND_FINI(gil->cond);\n    MUTEX_FINI(gil->mutex);\n#ifdef FORCE_SWITCHING\n    COND_FINI(gil->switch_cond);\n    MUTEX_FINI(gil->switch_mutex);\n#endif\n    _Py_atomic_store_explicit(&gil->locked, -1,\n                              _Py_memory_order_release);\n    _Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked);\n}\n\n#ifdef HAVE_FORK\nstatic void recreate_gil(struct _gil_runtime_state *gil)\n{\n    _Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked);\n    /* XXX should we destroy the old OS resources here? */\n    create_gil(gil);\n}\n#endif\n\nstatic void\ndrop_gil(struct _ceval_state *ceval, PyThreadState *tstate)\n{\n    /* If tstate is NULL, the caller is indicating that we're releasing\n       the GIL for the last time in this thread.  This is particularly\n       relevant when the current thread state is finalizing or its\n       interpreter is finalizing (either may be in an inconsistent\n       state).  In that case the current thread will definitely\n       never try to acquire the GIL again. */\n    // XXX It may be more correct to check tstate->_status.finalizing.\n    // XXX assert(tstate == NULL || !tstate->_status.cleared);\n\n    struct _gil_runtime_state *gil = ceval->gil;\n    if (!_Py_atomic_load_relaxed(&gil->locked)) {\n        Py_FatalError(\"drop_gil: GIL is not locked\");\n    }\n\n    /* tstate is allowed to be NULL (early interpreter init) */\n    if (tstate != NULL) {\n        /* Sub-interpreter support: threads might have been switched\n           under our feet using PyThreadState_Swap(). Fix the GIL last\n           holder variable so that our heuristics work. */\n        _Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate);\n    }\n\n    MUTEX_LOCK(gil->mutex);\n    _Py_ANNOTATE_RWLOCK_RELEASED(&gil->locked, /*is_write=*/1);\n    _Py_atomic_store_relaxed(&gil->locked, 0);\n    COND_SIGNAL(gil->cond);\n    MUTEX_UNLOCK(gil->mutex);\n\n#ifdef FORCE_SWITCHING\n    /* We check tstate first in case we might be releasing the GIL for\n       the last time in this thread.  In that case there's a possible\n       race with tstate->interp getting deleted after gil->mutex is\n       unlocked and before the following code runs, leading to a crash.\n       We can use (tstate == NULL) to indicate the thread is done with\n       the GIL, and that's the only time we might delete the\n       interpreter, so checking tstate first prevents the crash.\n       See https://github.com/python/cpython/issues/104341. */\n    if (tstate != NULL && _Py_atomic_load_relaxed(&ceval->gil_drop_request)) {\n        MUTEX_LOCK(gil->switch_mutex);\n        /* Not switched yet => wait */\n        if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) == tstate)\n        {\n            assert(is_tstate_valid(tstate));\n            RESET_GIL_DROP_REQUEST(tstate->interp);\n            /* NOTE: if COND_WAIT does not atomically start waiting when\n               releasing the mutex, another thread can run through, take\n               the GIL and drop it again, and reset the condition\n               before we even had a chance to wait for it. */\n            COND_WAIT(gil->switch_cond, gil->switch_mutex);\n        }\n        MUTEX_UNLOCK(gil->switch_mutex);\n    }\n#endif\n}\n\n\n/* Check if a Python thread must exit immediately, rather than taking the GIL\n   if Py_Finalize() has been called.\n\n   When this function is called by a daemon thread after Py_Finalize() has been\n   called, the GIL does no longer exist.\n\n   tstate must be non-NULL. */\nstatic inline int\ntstate_must_exit(PyThreadState *tstate)\n{\n    /* bpo-39877: Access _PyRuntime directly rather than using\n       tstate->interp->runtime to support calls from Python daemon threads.\n       After Py_Finalize() has been called, tstate can be a dangling pointer:\n       point to PyThreadState freed memory. */\n    PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime);\n    if (finalizing == NULL) {\n        finalizing = _PyInterpreterState_GetFinalizing(tstate->interp);\n    }\n    return (finalizing != NULL && finalizing != tstate);\n}\n\n\n/* Take the GIL.\n\n   The function saves errno at entry and restores its value at exit.\n\n   tstate must be non-NULL. */\nstatic void\ntake_gil(PyThreadState *tstate)\n{\n    int err = errno;\n\n    assert(tstate != NULL);\n    /* We shouldn't be using a thread state that isn't viable any more. */\n    // XXX It may be more correct to check tstate->_status.finalizing.\n    // XXX assert(!tstate->_status.cleared);\n\n    if (tstate_must_exit(tstate)) {\n        /* bpo-39877: If Py_Finalize() has been called and tstate is not the\n           thread which called Py_Finalize(), exit immediately the thread.\n\n           This code path can be reached by a daemon thread after Py_Finalize()\n           completes. In this case, tstate is a dangling pointer: points to\n           PyThreadState freed memory. */\n        PyThread_exit_thread();\n    }\n\n    assert(is_tstate_valid(tstate));\n    PyInterpreterState *interp = tstate->interp;\n    struct _ceval_state *ceval = &interp->ceval;\n    struct _gil_runtime_state *gil = ceval->gil;\n\n    /* Check that _PyEval_InitThreads() was called to create the lock */\n    assert(gil_created(gil));\n\n    MUTEX_LOCK(gil->mutex);\n\n    if (!_Py_atomic_load_relaxed(&gil->locked)) {\n        goto _ready;\n    }\n\n    int drop_requested = 0;\n    while (_Py_atomic_load_relaxed(&gil->locked)) {\n        unsigned long saved_switchnum = gil->switch_number;\n\n        unsigned long interval = (gil->interval >= 1 ? gil->interval : 1);\n        int timed_out = 0;\n        COND_TIMED_WAIT(gil->cond, gil->mutex, interval, timed_out);\n\n        /* If we timed out and no switch occurred in the meantime, it is time\n           to ask the GIL-holding thread to drop it. */\n        if (timed_out &&\n            _Py_atomic_load_relaxed(&gil->locked) &&\n            gil->switch_number == saved_switchnum)\n        {\n            if (tstate_must_exit(tstate)) {\n                MUTEX_UNLOCK(gil->mutex);\n                // gh-96387: If the loop requested a drop request in a previous\n                // iteration, reset the request. Otherwise, drop_gil() can\n                // block forever waiting for the thread which exited. Drop\n                // requests made by other threads are also reset: these threads\n                // may have to request again a drop request (iterate one more\n                // time).\n                if (drop_requested) {\n                    RESET_GIL_DROP_REQUEST(interp);\n                }\n                PyThread_exit_thread();\n            }\n            assert(is_tstate_valid(tstate));\n\n            SET_GIL_DROP_REQUEST(interp);\n            drop_requested = 1;\n        }\n    }\n\n_ready:\n#ifdef FORCE_SWITCHING\n    /* This mutex must be taken before modifying gil->last_holder:\n       see drop_gil(). */\n    MUTEX_LOCK(gil->switch_mutex);\n#endif\n    /* We now hold the GIL */\n    _Py_atomic_store_relaxed(&gil->locked, 1);\n    _Py_ANNOTATE_RWLOCK_ACQUIRED(&gil->locked, /*is_write=*/1);\n\n    if (tstate != (PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) {\n        _Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate);\n        ++gil->switch_number;\n    }\n\n#ifdef FORCE_SWITCHING\n    COND_SIGNAL(gil->switch_cond);\n    MUTEX_UNLOCK(gil->switch_mutex);\n#endif\n\n    if (tstate_must_exit(tstate)) {\n        /* bpo-36475: If Py_Finalize() has been called and tstate is not\n           the thread which called Py_Finalize(), exit immediately the\n           thread.\n\n           This code path can be reached by a daemon thread which was waiting\n           in take_gil() while the main thread called\n           wait_for_thread_shutdown() from Py_Finalize(). */\n        MUTEX_UNLOCK(gil->mutex);\n        drop_gil(ceval, tstate);\n        PyThread_exit_thread();\n    }\n    assert(is_tstate_valid(tstate));\n\n    if (_Py_atomic_load_relaxed(&ceval->gil_drop_request)) {\n        RESET_GIL_DROP_REQUEST(interp);\n    }\n    else {\n        /* bpo-40010: eval_breaker should be recomputed to be set to 1 if there\n           is a pending signal: signal received by another thread which cannot\n           handle signals.\n\n           Note: RESET_GIL_DROP_REQUEST() calls COMPUTE_EVAL_BREAKER(). */\n        COMPUTE_EVAL_BREAKER(interp, &_PyRuntime.ceval, ceval);\n    }\n\n    /* Don't access tstate if the thread must exit */\n    if (tstate->async_exc != NULL) {\n        _PyEval_SignalAsyncExc(tstate->interp);\n    }\n\n    MUTEX_UNLOCK(gil->mutex);\n\n    errno = err;\n}\n\nvoid _PyEval_SetSwitchInterval(unsigned long microseconds)\n{\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    struct _gil_runtime_state *gil = interp->ceval.gil;\n    assert(gil != NULL);\n    gil->interval = microseconds;\n}\n\nunsigned long _PyEval_GetSwitchInterval(void)\n{\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    struct _gil_runtime_state *gil = interp->ceval.gil;\n    assert(gil != NULL);\n    return gil->interval;\n}\n\n\nint\n_PyEval_ThreadsInitialized(void)\n{\n    /* XXX This is only needed for an assert in PyGILState_Ensure(),\n     * which currently does not work with subinterpreters.\n     * Thus we only use the main interpreter. */\n    PyInterpreterState *interp = _PyInterpreterState_Main();\n    if (interp == NULL) {\n        return 0;\n    }\n    struct _gil_runtime_state *gil = interp->ceval.gil;\n    return gil_created(gil);\n}\n\n// Function removed in the Python 3.13 API but kept in the stable ABI.\nPyAPI_FUNC(int)\nPyEval_ThreadsInitialized(void)\n{\n    return _PyEval_ThreadsInitialized();\n}\n\nstatic inline int\ncurrent_thread_holds_gil(struct _gil_runtime_state *gil, PyThreadState *tstate)\n{\n    if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) != tstate) {\n        return 0;\n    }\n    return _Py_atomic_load_relaxed(&gil->locked);\n}\n\nstatic void\ninit_shared_gil(PyInterpreterState *interp, struct _gil_runtime_state *gil)\n{\n    assert(gil_created(gil));\n    interp->ceval.gil = gil;\n    interp->ceval.own_gil = 0;\n}\n\nstatic void\ninit_own_gil(PyInterpreterState *interp, struct _gil_runtime_state *gil)\n{\n    assert(!gil_created(gil));\n    create_gil(gil);\n    assert(gil_created(gil));\n    interp->ceval.gil = gil;\n    interp->ceval.own_gil = 1;\n}\n\nPyStatus\n_PyEval_InitGIL(PyThreadState *tstate, int own_gil)\n{\n    assert(tstate->interp->ceval.gil == NULL);\n    int locked;\n    if (!own_gil) {\n        /* The interpreter will share the main interpreter's instead. */\n        PyInterpreterState *main_interp = _PyInterpreterState_Main();\n        assert(tstate->interp != main_interp);\n        struct _gil_runtime_state *gil = main_interp->ceval.gil;\n        init_shared_gil(tstate->interp, gil);\n        locked = current_thread_holds_gil(gil, tstate);\n    }\n    else {\n        PyThread_init_thread();\n        init_own_gil(tstate->interp, &tstate->interp->_gil);\n        locked = 0;\n    }\n    if (!locked) {\n        take_gil(tstate);\n    }\n\n    return _PyStatus_OK();\n}\n\nvoid\n_PyEval_FiniGIL(PyInterpreterState *interp)\n{\n    struct _gil_runtime_state *gil = interp->ceval.gil;\n    if (gil == NULL) {\n        /* It was already finalized (or hasn't been initialized yet). */\n        assert(!interp->ceval.own_gil);\n        return;\n    }\n    else if (!interp->ceval.own_gil) {\n#ifdef Py_DEBUG\n        PyInterpreterState *main_interp = _PyInterpreterState_Main();\n        assert(main_interp != NULL && interp != main_interp);\n        assert(interp->ceval.gil == main_interp->ceval.gil);\n#endif\n        interp->ceval.gil = NULL;\n        return;\n    }\n\n    if (!gil_created(gil)) {\n        /* First Py_InitializeFromConfig() call: the GIL doesn't exist\n           yet: do nothing. */\n        return;\n    }\n\n    destroy_gil(gil);\n    assert(!gil_created(gil));\n    interp->ceval.gil = NULL;\n}\n\n// Function removed in the Python 3.13 API but kept in the stable ABI.\nPyAPI_FUNC(void)\nPyEval_InitThreads(void)\n{\n    /* Do nothing: kept for backward compatibility */\n}\n\nvoid\n_PyEval_Fini(void)\n{\n#ifdef Py_STATS\n    _Py_PrintSpecializationStats(1);\n#endif\n}\n\n// Function removed in the Python 3.13 API but kept in the stable ABI.\nPyAPI_FUNC(void)\nPyEval_AcquireLock(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _Py_EnsureTstateNotNULL(tstate);\n\n    take_gil(tstate);\n}\n\n// Function removed in the Python 3.13 API but kept in the stable ABI.\nPyAPI_FUNC(void)\nPyEval_ReleaseLock(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    /* This function must succeed when the current thread state is NULL.\n       We therefore avoid PyThreadState_Get() which dumps a fatal error\n       in debug mode. */\n    struct _ceval_state *ceval = &tstate->interp->ceval;\n    drop_gil(ceval, tstate);\n}\n\nvoid\n_PyEval_AcquireLock(PyThreadState *tstate)\n{\n    _Py_EnsureTstateNotNULL(tstate);\n    take_gil(tstate);\n}\n\nvoid\n_PyEval_ReleaseLock(PyInterpreterState *interp, PyThreadState *tstate)\n{\n    /* If tstate is NULL then we do not expect the current thread\n       to acquire the GIL ever again. */\n    assert(tstate == NULL || tstate->interp == interp);\n    struct _ceval_state *ceval = &interp->ceval;\n    drop_gil(ceval, tstate);\n}\n\nvoid\nPyEval_AcquireThread(PyThreadState *tstate)\n{\n    _Py_EnsureTstateNotNULL(tstate);\n\n    take_gil(tstate);\n\n    if (_PyThreadState_SwapNoGIL(tstate) != NULL) {\n        Py_FatalError(\"non-NULL old thread state\");\n    }\n}\n\nvoid\nPyEval_ReleaseThread(PyThreadState *tstate)\n{\n    assert(is_tstate_valid(tstate));\n\n    PyThreadState *new_tstate = _PyThreadState_SwapNoGIL(NULL);\n    if (new_tstate != tstate) {\n        Py_FatalError(\"wrong thread state\");\n    }\n    struct _ceval_state *ceval = &tstate->interp->ceval;\n    drop_gil(ceval, tstate);\n}\n\n#ifdef HAVE_FORK\n/* This function is called from PyOS_AfterFork_Child to destroy all threads\n   which are not running in the child process, and clear internal locks\n   which might be held by those threads. */\nPyStatus\n_PyEval_ReInitThreads(PyThreadState *tstate)\n{\n    assert(tstate->interp == _PyInterpreterState_Main());\n\n    struct _gil_runtime_state *gil = tstate->interp->ceval.gil;\n    if (!gil_created(gil)) {\n        return _PyStatus_OK();\n    }\n    recreate_gil(gil);\n\n    take_gil(tstate);\n\n    struct _pending_calls *pending = &tstate->interp->ceval.pending;\n    if (_PyThread_at_fork_reinit(&pending->lock) < 0) {\n        return _PyStatus_ERR(\"Can't reinitialize pending calls lock\");\n    }\n\n    /* Destroy all threads except the current one */\n    _PyThreadState_DeleteExcept(tstate);\n    return _PyStatus_OK();\n}\n#endif\n\n/* This function is used to signal that async exceptions are waiting to be\n   raised. */\n\nvoid\n_PyEval_SignalAsyncExc(PyInterpreterState *interp)\n{\n    SIGNAL_ASYNC_EXC(interp);\n}\n\nPyThreadState *\nPyEval_SaveThread(void)\n{\n    PyThreadState *tstate = _PyThreadState_SwapNoGIL(NULL);\n    _Py_EnsureTstateNotNULL(tstate);\n\n    struct _ceval_state *ceval = &tstate->interp->ceval;\n    assert(gil_created(ceval->gil));\n    drop_gil(ceval, tstate);\n    return tstate;\n}\n\nvoid\nPyEval_RestoreThread(PyThreadState *tstate)\n{\n    _Py_EnsureTstateNotNULL(tstate);\n\n    take_gil(tstate);\n\n    _PyThreadState_SwapNoGIL(tstate);\n}\n\n\n/* Mechanism whereby asynchronously executing callbacks (e.g. UNIX\n   signal handlers or Mac I/O completion routines) can schedule calls\n   to a function to be called synchronously.\n   The synchronous function is called with one void* argument.\n   It should return 0 for success or -1 for failure -- failure should\n   be accompanied by an exception.\n\n   If registry succeeds, the registry function returns 0; if it fails\n   (e.g. due to too many pending calls) it returns -1 (without setting\n   an exception condition).\n\n   Note that because registry may occur from within signal handlers,\n   or other asynchronous events, calling malloc() is unsafe!\n\n   Any thread can schedule pending calls, but only the main thread\n   will execute them.\n   There is no facility to schedule calls to a particular thread, but\n   that should be easy to change, should that ever be required.  In\n   that case, the static variables here should go into the python\n   threadstate.\n*/\n\nvoid\n_PyEval_SignalReceived(PyInterpreterState *interp)\n{\n#ifdef MS_WINDOWS\n    // bpo-42296: On Windows, _PyEval_SignalReceived() is called from a signal\n    // handler which can run in a thread different than the Python thread, in\n    // which case _Py_ThreadCanHandleSignals() is wrong. Ignore\n    // _Py_ThreadCanHandleSignals() and always set eval_breaker to 1.\n    //\n    // The next eval_frame_handle_pending() call will call\n    // _Py_ThreadCanHandleSignals() to recompute eval_breaker.\n    int force = 1;\n#else\n    int force = 0;\n#endif\n    /* bpo-30703: Function called when the C signal handler of Python gets a\n       signal. We cannot queue a callback using _PyEval_AddPendingCall() since\n       that function is not async-signal-safe. */\n    SIGNAL_PENDING_SIGNALS(interp, force);\n}\n\n/* Push one item onto the queue while holding the lock. */\nstatic int\n_push_pending_call(struct _pending_calls *pending,\n                   int (*func)(void *), void *arg)\n{\n    int i = pending->last;\n    int j = (i + 1) % NPENDINGCALLS;\n    if (j == pending->first) {\n        return -1; /* Queue full */\n    }\n    pending->calls[i].func = func;\n    pending->calls[i].arg = arg;\n    pending->last = j;\n    return 0;\n}\n\n/* Pop one item off the queue while holding the lock. */\nstatic void\n_pop_pending_call(struct _pending_calls *pending,\n                  int (**func)(void *), void **arg)\n{\n    int i = pending->first;\n    if (i == pending->last) {\n        return; /* Queue empty */\n    }\n\n    *func = pending->calls[i].func;\n    *arg = pending->calls[i].arg;\n    pending->first = (i + 1) % NPENDINGCALLS;\n}\n\n/* This implementation is thread-safe.  It allows\n   scheduling to be made from any thread, and even from an executing\n   callback.\n */\n\nint\n_PyEval_AddPendingCall(PyInterpreterState *interp,\n                       int (*func)(void *), void *arg)\n{\n    struct _pending_calls *pending = &interp->ceval.pending;\n    /* Ensure that _PyEval_InitState() was called\n       and that _PyEval_FiniState() is not called yet. */\n    assert(pending->lock != NULL);\n\n    PyThread_acquire_lock(pending->lock, WAIT_LOCK);\n    int result = _push_pending_call(pending, func, arg);\n    PyThread_release_lock(pending->lock);\n\n    /* signal main loop */\n    SIGNAL_PENDING_CALLS(interp);\n    return result;\n}\n\nint\nPy_AddPendingCall(int (*func)(void *), void *arg)\n{\n    /* Best-effort to support subinterpreters and calls with the GIL released.\n\n       First attempt _PyThreadState_GET() since it supports subinterpreters.\n\n       If the GIL is released, _PyThreadState_GET() returns NULL . In this\n       case, use PyGILState_GetThisThreadState() which works even if the GIL\n       is released.\n\n       Sadly, PyGILState_GetThisThreadState() doesn't support subinterpreters:\n       see bpo-10915 and bpo-15751.\n\n       Py_AddPendingCall() doesn't require the caller to hold the GIL. */\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (tstate == NULL) {\n        tstate = PyGILState_GetThisThreadState();\n    }\n\n    PyInterpreterState *interp;\n    if (tstate != NULL) {\n        interp = tstate->interp;\n    }\n    else {\n        /* Last resort: use the main interpreter */\n        interp = _PyInterpreterState_Main();\n    }\n    return _PyEval_AddPendingCall(interp, func, arg);\n}\n\nstatic int\nhandle_signals(PyThreadState *tstate)\n{\n    assert(is_tstate_valid(tstate));\n    if (!_Py_ThreadCanHandleSignals(tstate->interp)) {\n        return 0;\n    }\n\n    UNSIGNAL_PENDING_SIGNALS(tstate->interp);\n    if (_PyErr_CheckSignalsTstate(tstate) < 0) {\n        /* On failure, re-schedule a call to handle_signals(). */\n        SIGNAL_PENDING_SIGNALS(tstate->interp, 0);\n        return -1;\n    }\n    return 0;\n}\n\nstatic int\nmake_pending_calls(PyInterpreterState *interp)\n{\n    /* only execute pending calls on main thread */\n    if (!_Py_ThreadCanHandlePendingCalls()) {\n        return 0;\n    }\n\n    /* don't perform recursive pending calls */\n    if (interp->ceval.pending.busy) {\n        return 0;\n    }\n    interp->ceval.pending.busy = 1;\n\n    /* unsignal before starting to call callbacks, so that any callback\n       added in-between re-signals */\n    UNSIGNAL_PENDING_CALLS(interp);\n    int res = 0;\n\n    /* perform a bounded number of calls, in case of recursion */\n    struct _pending_calls *pending = &interp->ceval.pending;\n    for (int i=0; i<NPENDINGCALLS; i++) {\n        int (*func)(void *) = NULL;\n        void *arg = NULL;\n\n        /* pop one item off the queue while holding the lock */\n        PyThread_acquire_lock(pending->lock, WAIT_LOCK);\n        _pop_pending_call(pending, &func, &arg);\n        PyThread_release_lock(pending->lock);\n\n        /* having released the lock, perform the callback */\n        if (func == NULL) {\n            break;\n        }\n        res = func(arg);\n        if (res) {\n            goto error;\n        }\n    }\n\n    interp->ceval.pending.busy = 0;\n    return res;\n\nerror:\n    interp->ceval.pending.busy = 0;\n    SIGNAL_PENDING_CALLS(interp);\n    return res;\n}\n\nvoid\n_Py_FinishPendingCalls(PyThreadState *tstate)\n{\n    assert(PyGILState_Check());\n    assert(is_tstate_valid(tstate));\n\n    struct _pending_calls *pending = &tstate->interp->ceval.pending;\n\n    if (!_Py_atomic_load_relaxed_int32(&(pending->calls_to_do))) {\n        return;\n    }\n\n    if (make_pending_calls(tstate->interp) < 0) {\n        PyObject *exc = _PyErr_GetRaisedException(tstate);\n        PyErr_BadInternalCall();\n        _PyErr_ChainExceptions1(exc);\n        _PyErr_Print(tstate);\n    }\n}\n\n/* Py_MakePendingCalls() is a simple wrapper for the sake\n   of backward-compatibility. */\nint\nPy_MakePendingCalls(void)\n{\n    assert(PyGILState_Check());\n\n    PyThreadState *tstate = _PyThreadState_GET();\n    assert(is_tstate_valid(tstate));\n\n    /* Python signal handler doesn't really queue a callback: it only signals\n       that a signal was received, see _PyEval_SignalReceived(). */\n    int res = handle_signals(tstate);\n    if (res != 0) {\n        return res;\n    }\n\n    res = make_pending_calls(tstate->interp);\n    if (res != 0) {\n        return res;\n    }\n\n    return 0;\n}\n\nvoid\n_PyEval_InitState(PyInterpreterState *interp, PyThread_type_lock pending_lock)\n{\n    _gil_initialize(&interp->_gil);\n\n    struct _pending_calls *pending = &interp->ceval.pending;\n    assert(pending->lock == NULL);\n    pending->lock = pending_lock;\n}\n\nvoid\n_PyEval_FiniState(struct _ceval_state *ceval)\n{\n    struct _pending_calls *pending = &ceval->pending;\n    if (pending->lock != NULL) {\n        PyThread_free_lock(pending->lock);\n        pending->lock = NULL;\n    }\n}\n\n/* Handle signals, pending calls, GIL drop request\n   and asynchronous exception */\nint\n_Py_HandlePending(PyThreadState *tstate)\n{\n    _PyRuntimeState * const runtime = &_PyRuntime;\n    struct _ceval_runtime_state *ceval = &runtime->ceval;\n    struct _ceval_state *interp_ceval_state = &tstate->interp->ceval;\n\n    /* Pending signals */\n    if (_Py_atomic_load_relaxed_int32(&ceval->signals_pending)) {\n        if (handle_signals(tstate) != 0) {\n            return -1;\n        }\n    }\n\n    /* Pending calls */\n    if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->pending.calls_to_do)) {\n        if (make_pending_calls(tstate->interp) != 0) {\n            return -1;\n        }\n    }\n\n    /* GC scheduled to run */\n    if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->gc_scheduled)) {\n        _Py_atomic_store_relaxed(&interp_ceval_state->gc_scheduled, 0);\n        COMPUTE_EVAL_BREAKER(tstate->interp, ceval, interp_ceval_state);\n        _Py_RunGC(tstate);\n    }\n\n    /* GIL drop request */\n    if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->gil_drop_request)) {\n        /* Give another thread a chance */\n        if (_PyThreadState_SwapNoGIL(NULL) != tstate) {\n            Py_FatalError(\"tstate mix-up\");\n        }\n        drop_gil(interp_ceval_state, tstate);\n\n        /* Other threads may run now */\n\n        take_gil(tstate);\n\n        if (_PyThreadState_SwapNoGIL(tstate) != NULL) {\n            Py_FatalError(\"orphan tstate\");\n        }\n    }\n\n    /* Check for asynchronous exception. */\n    if (tstate->async_exc != NULL) {\n        PyObject *exc = tstate->async_exc;\n        tstate->async_exc = NULL;\n        UNSIGNAL_ASYNC_EXC(tstate->interp);\n        _PyErr_SetNone(tstate, exc);\n        Py_DECREF(exc);\n        return -1;\n    }\n\n\n    // It is possible that some of the conditions that trigger the eval breaker\n    // are called in a different thread than the Python thread. An example of\n    // this is bpo-42296: On Windows, _PyEval_SignalReceived() can be called in\n    // a different thread than the Python thread, in which case\n    // _Py_ThreadCanHandleSignals() is wrong. Recompute eval_breaker in the\n    // current Python thread with the correct _Py_ThreadCanHandleSignals()\n    // value. It prevents to interrupt the eval loop at every instruction if\n    // the current Python thread cannot handle signals (if\n    // _Py_ThreadCanHandleSignals() is false).\n    COMPUTE_EVAL_BREAKER(tstate->interp, ceval, interp_ceval_state);\n\n    return 0;\n}\n"
  },
  {
    "path": "Ceval_Macros.h",
    "content": "// Macros needed by ceval.c and bytecodes.c\n\n/* Computed GOTOs, or\n       the-optimization-commonly-but-improperly-known-as-\"threaded code\"\n   using gcc's labels-as-values extension\n   (http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html).\n\n   The traditional bytecode evaluation loop uses a \"switch\" statement, which\n   decent compilers will optimize as a single indirect branch instruction\n   combined with a lookup table of jump addresses. However, since the\n   indirect jump instruction is shared by all opcodes, the CPU will have a\n   hard time making the right prediction for where to jump next (actually,\n   it will be always wrong except in the uncommon case of a sequence of\n   several identical opcodes).\n\n   \"Threaded code\" in contrast, uses an explicit jump table and an explicit\n   indirect jump instruction at the end of each opcode. Since the jump\n   instruction is at a different address for each opcode, the CPU will make a\n   separate prediction for each of these instructions, which is equivalent to\n   predicting the second opcode of each opcode pair. These predictions have\n   a much better chance to turn out valid, especially in small bytecode loops.\n\n   A mispredicted branch on a modern CPU flushes the whole pipeline and\n   can cost several CPU cycles (depending on the pipeline depth),\n   and potentially many more instructions (depending on the pipeline width).\n   A correctly predicted branch, however, is nearly free.\n\n   At the time of this writing, the \"threaded code\" version is up to 15-20%\n   faster than the normal \"switch\" version, depending on the compiler and the\n   CPU architecture.\n\n   NOTE: care must be taken that the compiler doesn't try to \"optimize\" the\n   indirect jumps by sharing them between all opcodes. Such optimizations\n   can be disabled on gcc by using the -fno-gcse flag (or possibly\n   -fno-crossjumping).\n*/\n\n/* Use macros rather than inline functions, to make it as clear as possible\n * to the C compiler that the tracing check is a simple test then branch.\n * We want to be sure that the compiler knows this before it generates\n * the CFG.\n */\n\n#ifdef WITH_DTRACE\n#define OR_DTRACE_LINE | (PyDTrace_LINE_ENABLED() ? 255 : 0)\n#else\n#define OR_DTRACE_LINE\n#endif\n\n#ifdef HAVE_COMPUTED_GOTOS\n    #ifndef USE_COMPUTED_GOTOS\n    #define USE_COMPUTED_GOTOS 1\n    #endif\n#else\n    #if defined(USE_COMPUTED_GOTOS) && USE_COMPUTED_GOTOS\n    #error \"Computed gotos are not supported on this compiler.\"\n    #endif\n    #undef USE_COMPUTED_GOTOS\n    #define USE_COMPUTED_GOTOS 0\n#endif\n\n#ifdef Py_STATS\n#define INSTRUCTION_START(op) \\\n    do { \\\n        frame->prev_instr = next_instr++; \\\n        OPCODE_EXE_INC(op); \\\n        if (_py_stats) _py_stats->opcode_stats[lastopcode].pair_count[op]++; \\\n        lastopcode = op; \\\n    } while (0)\n#else\n#define INSTRUCTION_START(op) (frame->prev_instr = next_instr++)\n#endif\n\n#if USE_COMPUTED_GOTOS\n#  define TARGET(op) TARGET_##op: INSTRUCTION_START(op);\n#  define DISPATCH_GOTO() goto *opcode_targets[opcode]\n#else\n#  define TARGET(op) case op: TARGET_##op: INSTRUCTION_START(op);\n#  define DISPATCH_GOTO() goto dispatch_opcode\n#endif\n\n/* PRE_DISPATCH_GOTO() does lltrace if enabled. Normally a no-op */\n#ifdef LLTRACE\n#define PRE_DISPATCH_GOTO() if (lltrace) { \\\n    lltrace_instruction(frame, stack_pointer, next_instr); }\n#else\n#define PRE_DISPATCH_GOTO() ((void)0)\n#endif\n\n\n/* Do interpreter dispatch accounting for tracing and instrumentation */\n#define DISPATCH() \\\n    { \\\n        NEXTOPARG(); \\\n        PRE_DISPATCH_GOTO(); \\\n        DISPATCH_GOTO(); \\\n    }\n\n#define DISPATCH_SAME_OPARG() \\\n    { \\\n        opcode = next_instr->op.code; \\\n        PRE_DISPATCH_GOTO(); \\\n        DISPATCH_GOTO(); \\\n    }\n\n#define DISPATCH_INLINED(NEW_FRAME)                     \\\n    do {                                                \\\n        assert(tstate->interp->eval_frame == NULL);     \\\n        _PyFrame_SetStackPointer(frame, stack_pointer); \\\n        frame->prev_instr = next_instr - 1;             \\\n        (NEW_FRAME)->previous = frame;                  \\\n        frame = cframe.current_frame = (NEW_FRAME);     \\\n        CALL_STAT_INC(inlined_py_calls);                \\\n        goto start_frame;                               \\\n    } while (0)\n\n#define CHECK_EVAL_BREAKER() \\\n    _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); \\\n    if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker)) { \\\n        goto handle_eval_breaker; \\\n    }\n\n\n/* Tuple access macros */\n\n#ifndef Py_DEBUG\n#define GETITEM(v, i) PyTuple_GET_ITEM((v), (i))\n#else\nstatic inline PyObject *\nGETITEM(PyObject *v, Py_ssize_t i) {\n    assert(PyTuple_Check(v));\n    assert(i >= 0);\n    assert(i < PyTuple_GET_SIZE(v));\n    return PyTuple_GET_ITEM(v, i);\n}\n#endif\n\n/* Code access macros */\n\n/* The integer overflow is checked by an assertion below. */\n#define INSTR_OFFSET() ((int)(next_instr - _PyCode_CODE(frame->f_code)))\n#define NEXTOPARG()  do { \\\n        _Py_CODEUNIT word = *next_instr; \\\n        opcode = word.op.code; \\\n        oparg = word.op.arg; \\\n    } while (0)\n#define JUMPTO(x)       (next_instr = _PyCode_CODE(frame->f_code) + (x))\n#define JUMPBY(x)       (next_instr += (x))\n\n/* OpCode prediction macros\n    Some opcodes tend to come in pairs thus making it possible to\n    predict the second code when the first is run.  For example,\n    COMPARE_OP is often followed by POP_JUMP_IF_FALSE or POP_JUMP_IF_TRUE.\n\n    Verifying the prediction costs a single high-speed test of a register\n    variable against a constant.  If the pairing was good, then the\n    processor's own internal branch predication has a high likelihood of\n    success, resulting in a nearly zero-overhead transition to the\n    next opcode.  A successful prediction saves a trip through the eval-loop\n    including its unpredictable switch-case branch.  Combined with the\n    processor's internal branch prediction, a successful PREDICT has the\n    effect of making the two opcodes run as if they were a single new opcode\n    with the bodies combined.\n\n    If collecting opcode statistics, your choices are to either keep the\n    predictions turned-on and interpret the results as if some opcodes\n    had been combined or turn-off predictions so that the opcode frequency\n    counter updates for both opcodes.\n\n    Opcode prediction is disabled with threaded code, since the latter allows\n    the CPU to record separate branch prediction information for each\n    opcode.\n\n*/\n\n#define PREDICT_ID(op)          PRED_##op\n#define PREDICTED(op)           PREDICT_ID(op):\n\n\n/* Stack manipulation macros */\n\n/* The stack can grow at most MAXINT deep, as co_nlocals and\n   co_stacksize are ints. */\n#define STACK_LEVEL()     ((int)(stack_pointer - _PyFrame_Stackbase(frame)))\n#define STACK_SIZE()      (frame->f_code->co_stacksize)\n#define EMPTY()           (STACK_LEVEL() == 0)\n#define TOP()             (stack_pointer[-1])\n#define SECOND()          (stack_pointer[-2])\n#define THIRD()           (stack_pointer[-3])\n#define FOURTH()          (stack_pointer[-4])\n#define PEEK(n)           (stack_pointer[-(n)])\n#define POKE(n, v)        (stack_pointer[-(n)] = (v))\n#define SET_TOP(v)        (stack_pointer[-1] = (v))\n#define SET_SECOND(v)     (stack_pointer[-2] = (v))\n#define BASIC_STACKADJ(n) (stack_pointer += n)\n#define BASIC_PUSH(v)     (*stack_pointer++ = (v))\n#define BASIC_POP()       (*--stack_pointer)\n\n#ifdef Py_DEBUG\n#define PUSH(v)         do { \\\n                            BASIC_PUSH(v); \\\n                            assert(STACK_LEVEL() <= STACK_SIZE()); \\\n                        } while (0)\n#define POP()           (assert(STACK_LEVEL() > 0), BASIC_POP())\n#define STACK_GROW(n)   do { \\\n                            assert(n >= 0); \\\n                            BASIC_STACKADJ(n); \\\n                            assert(STACK_LEVEL() <= STACK_SIZE()); \\\n                        } while (0)\n#define STACK_SHRINK(n) do { \\\n                            assert(n >= 0); \\\n                            assert(STACK_LEVEL() >= n); \\\n                            BASIC_STACKADJ(-(n)); \\\n                        } while (0)\n#else\n#define PUSH(v)                BASIC_PUSH(v)\n#define POP()                  BASIC_POP()\n#define STACK_GROW(n)          BASIC_STACKADJ(n)\n#define STACK_SHRINK(n)        BASIC_STACKADJ(-(n))\n#endif\n\n/* Local variable macros */\n\n#define GETLOCAL(i)     (frame->localsplus[i])\n\n/* The SETLOCAL() macro must not DECREF the local variable in-place and\n   then store the new value; it must copy the old value to a temporary\n   value, then store the new value, and then DECREF the temporary value.\n   This is because it is possible that during the DECREF the frame is\n   accessed by other code (e.g. a __del__ method or gc.collect()) and the\n   variable would be pointing to already-freed memory. */\n#define SETLOCAL(i, value)      do { PyObject *tmp = GETLOCAL(i); \\\n                                     GETLOCAL(i) = value; \\\n                                     Py_XDECREF(tmp); } while (0)\n\n#define GO_TO_INSTRUCTION(op) goto PREDICT_ID(op)\n\n#ifdef Py_STATS\n#define UPDATE_MISS_STATS(INSTNAME)                              \\\n    do {                                                         \\\n        STAT_INC(opcode, miss);                                  \\\n        STAT_INC((INSTNAME), miss);                              \\\n        /* The counter is always the first cache entry: */       \\\n        if (ADAPTIVE_COUNTER_IS_ZERO(next_instr->cache)) {       \\\n            STAT_INC((INSTNAME), deopt);                         \\\n        }                                                        \\\n        else {                                                   \\\n            /* This is about to be (incorrectly) incremented: */ \\\n            STAT_DEC((INSTNAME), deferred);                      \\\n        }                                                        \\\n    } while (0)\n#else\n#define UPDATE_MISS_STATS(INSTNAME) ((void)0)\n#endif\n\n#define DEOPT_IF(COND, INSTNAME)                            \\\n    if ((COND)) {                                           \\\n        /* This is only a single jump on release builds! */ \\\n        UPDATE_MISS_STATS((INSTNAME));                      \\\n        assert(_PyOpcode_Deopt[opcode] == (INSTNAME));      \\\n        GO_TO_INSTRUCTION(INSTNAME);                        \\\n    }\n\n\n#define GLOBALS() frame->f_globals\n#define BUILTINS() frame->f_builtins\n#define LOCALS() frame->f_locals\n\n#define DTRACE_FUNCTION_ENTRY()  \\\n    if (PyDTrace_FUNCTION_ENTRY_ENABLED()) { \\\n        dtrace_function_entry(frame); \\\n    }\n\n#define ADAPTIVE_COUNTER_IS_ZERO(COUNTER) \\\n    (((COUNTER) >> ADAPTIVE_BACKOFF_BITS) == 0)\n\n#define ADAPTIVE_COUNTER_IS_MAX(COUNTER) \\\n    (((COUNTER) >> ADAPTIVE_BACKOFF_BITS) == ((1 << MAX_BACKOFF_VALUE) - 1))\n\n#define DECREMENT_ADAPTIVE_COUNTER(COUNTER)           \\\n    do {                                              \\\n        assert(!ADAPTIVE_COUNTER_IS_ZERO((COUNTER))); \\\n        (COUNTER) -= (1 << ADAPTIVE_BACKOFF_BITS);    \\\n    } while (0);\n\n#define INCREMENT_ADAPTIVE_COUNTER(COUNTER)          \\\n    do {                                             \\\n        (COUNTER) += (1 << ADAPTIVE_BACKOFF_BITS);   \\\n    } while (0);\n\n#define NAME_ERROR_MSG \"name '%.200s' is not defined\"\n\n#define KWNAMES_LEN() \\\n    (kwnames == NULL ? 0 : ((int)PyTuple_GET_SIZE(kwnames)))\n\n#define DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dval, result) \\\ndo { \\\n    if (Py_REFCNT(left) == 1) { \\\n        ((PyFloatObject *)left)->ob_fval = (dval); \\\n        _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);\\\n        result = (left); \\\n    } \\\n    else if (Py_REFCNT(right) == 1)  {\\\n        ((PyFloatObject *)right)->ob_fval = (dval); \\\n        _Py_DECREF_NO_DEALLOC(left); \\\n        result = (right); \\\n    }\\\n    else { \\\n        result = PyFloat_FromDouble(dval); \\\n        if ((result) == NULL) goto error; \\\n        _Py_DECREF_NO_DEALLOC(left); \\\n        _Py_DECREF_NO_DEALLOC(right); \\\n    } \\\n} while (0)\n\n// If a trace function sets a new f_lineno and\n// *then* raises, we use the destination when searching\n// for an exception handler, displaying the traceback, and so on\n#define INSTRUMENTED_JUMP(src, dest, event) \\\ndo { \\\n    _PyFrame_SetStackPointer(frame, stack_pointer); \\\n    next_instr = _Py_call_instrumentation_jump(tstate, event, frame, src, dest); \\\n    stack_pointer = _PyFrame_GetStackPointer(frame); \\\n    if (next_instr == NULL) { \\\n        next_instr = (dest)+1; \\\n        goto error; \\\n    } \\\n} while (0);\n"
  },
  {
    "path": "Clinic/Python-tokenize.c.h",
    "content": "/*[clinic input]\npreserve\n[clinic start generated code]*/\n\n#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n#  include \"pycore_gc.h\"            // PyGC_Head\n#  include \"pycore_runtime.h\"       // _Py_ID()\n#endif\n\n\nstatic PyObject *\ntokenizeriter_new_impl(PyTypeObject *type, PyObject *readline,\n                       int extra_tokens, const char *encoding);\n\nstatic PyObject *\ntokenizeriter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 2\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(extra_tokens), &_Py_ID(encoding), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"\", \"extra_tokens\", \"encoding\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"tokenizeriter\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[3];\n    PyObject * const *fastargs;\n    Py_ssize_t nargs = PyTuple_GET_SIZE(args);\n    Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 2;\n    PyObject *readline;\n    int extra_tokens;\n    const char *encoding = NULL;\n\n    fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 1, 1, 1, argsbuf);\n    if (!fastargs) {\n        goto exit;\n    }\n    readline = fastargs[0];\n    extra_tokens = PyObject_IsTrue(fastargs[1]);\n    if (extra_tokens < 0) {\n        goto exit;\n    }\n    if (!noptargs) {\n        goto skip_optional_kwonly;\n    }\n    if (!PyUnicode_Check(fastargs[2])) {\n        _PyArg_BadArgument(\"tokenizeriter\", \"argument 'encoding'\", \"str\", fastargs[2]);\n        goto exit;\n    }\n    Py_ssize_t encoding_length;\n    encoding = PyUnicode_AsUTF8AndSize(fastargs[2], &encoding_length);\n    if (encoding == NULL) {\n        goto exit;\n    }\n    if (strlen(encoding) != (size_t)encoding_length) {\n        PyErr_SetString(PyExc_ValueError, \"embedded null character\");\n        goto exit;\n    }\nskip_optional_kwonly:\n    return_value = tokenizeriter_new_impl(type, readline, extra_tokens, encoding);\n\nexit:\n    return return_value;\n}\n/*[clinic end generated code: output=48be65a2808bdfa6 input=a9049054013a1b77]*/\n"
  },
  {
    "path": "Clinic/_warnings.c.h",
    "content": "/*[clinic input]\npreserve\n[clinic start generated code]*/\n\n#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n#  include \"pycore_gc.h\"            // PyGC_Head\n#  include \"pycore_runtime.h\"       // _Py_ID()\n#endif\n\n\nPyDoc_STRVAR(warnings_warn__doc__,\n\"warn($module, /, message, category=None, stacklevel=1, source=None, *,\\n\"\n\"     skip_file_prefixes=<unrepresentable>)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Issue a warning, or maybe ignore it or raise an exception.\\n\"\n\"\\n\"\n\"  message\\n\"\n\"    Text of the warning message.\\n\"\n\"  category\\n\"\n\"    The Warning category subclass. Defaults to UserWarning.\\n\"\n\"  stacklevel\\n\"\n\"    How far up the call stack to make this warning appear. A value of 2 for\\n\"\n\"    example attributes the warning to the caller of the code calling warn().\\n\"\n\"  source\\n\"\n\"    If supplied, the destroyed object which emitted a ResourceWarning\\n\"\n\"  skip_file_prefixes\\n\"\n\"    An optional tuple of module filename prefixes indicating frames to skip\\n\"\n\"    during stacklevel computations for stack frame attribution.\");\n\n#define WARNINGS_WARN_METHODDEF    \\\n    {\"warn\", _PyCFunction_CAST(warnings_warn), METH_FASTCALL|METH_KEYWORDS, warnings_warn__doc__},\n\nstatic PyObject *\nwarnings_warn_impl(PyObject *module, PyObject *message, PyObject *category,\n                   Py_ssize_t stacklevel, PyObject *source,\n                   PyTupleObject *skip_file_prefixes);\n\nstatic PyObject *\nwarnings_warn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 5\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(message), &_Py_ID(category), &_Py_ID(stacklevel), &_Py_ID(source), &_Py_ID(skip_file_prefixes), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"message\", \"category\", \"stacklevel\", \"source\", \"skip_file_prefixes\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"warn\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[5];\n    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;\n    PyObject *message;\n    PyObject *category = Py_None;\n    Py_ssize_t stacklevel = 1;\n    PyObject *source = Py_None;\n    PyTupleObject *skip_file_prefixes = NULL;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 4, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    message = args[0];\n    if (!noptargs) {\n        goto skip_optional_pos;\n    }\n    if (args[1]) {\n        category = args[1];\n        if (!--noptargs) {\n            goto skip_optional_pos;\n        }\n    }\n    if (args[2]) {\n        {\n            Py_ssize_t ival = -1;\n            PyObject *iobj = _PyNumber_Index(args[2]);\n            if (iobj != NULL) {\n                ival = PyLong_AsSsize_t(iobj);\n                Py_DECREF(iobj);\n            }\n            if (ival == -1 && PyErr_Occurred()) {\n                goto exit;\n            }\n            stacklevel = ival;\n        }\n        if (!--noptargs) {\n            goto skip_optional_pos;\n        }\n    }\n    if (args[3]) {\n        source = args[3];\n        if (!--noptargs) {\n            goto skip_optional_pos;\n        }\n    }\nskip_optional_pos:\n    if (!noptargs) {\n        goto skip_optional_kwonly;\n    }\n    if (!PyTuple_Check(args[4])) {\n        _PyArg_BadArgument(\"warn\", \"argument 'skip_file_prefixes'\", \"tuple\", args[4]);\n        goto exit;\n    }\n    skip_file_prefixes = (PyTupleObject *)args[4];\nskip_optional_kwonly:\n    return_value = warnings_warn_impl(module, message, category, stacklevel, source, skip_file_prefixes);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(warnings_warn_explicit__doc__,\n\"warn_explicit($module, /, message, category, filename, lineno,\\n\"\n\"              module=<unrepresentable>, registry=None,\\n\"\n\"              module_globals=None, source=None)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Issue a warning, or maybe ignore it or raise an exception.\");\n\n#define WARNINGS_WARN_EXPLICIT_METHODDEF    \\\n    {\"warn_explicit\", _PyCFunction_CAST(warnings_warn_explicit), METH_FASTCALL|METH_KEYWORDS, warnings_warn_explicit__doc__},\n\nstatic PyObject *\nwarnings_warn_explicit_impl(PyObject *module, PyObject *message,\n                            PyObject *category, PyObject *filename,\n                            int lineno, PyObject *mod, PyObject *registry,\n                            PyObject *module_globals, PyObject *sourceobj);\n\nstatic PyObject *\nwarnings_warn_explicit(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 8\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(message), &_Py_ID(category), &_Py_ID(filename), &_Py_ID(lineno), &_Py_ID(module), &_Py_ID(registry), &_Py_ID(module_globals), &_Py_ID(source), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"message\", \"category\", \"filename\", \"lineno\", \"module\", \"registry\", \"module_globals\", \"source\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"warn_explicit\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[8];\n    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 4;\n    PyObject *message;\n    PyObject *category;\n    PyObject *filename;\n    int lineno;\n    PyObject *mod = NULL;\n    PyObject *registry = Py_None;\n    PyObject *module_globals = Py_None;\n    PyObject *sourceobj = Py_None;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 4, 8, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    message = args[0];\n    category = args[1];\n    if (!PyUnicode_Check(args[2])) {\n        _PyArg_BadArgument(\"warn_explicit\", \"argument 'filename'\", \"str\", args[2]);\n        goto exit;\n    }\n    filename = args[2];\n    lineno = _PyLong_AsInt(args[3]);\n    if (lineno == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    if (!noptargs) {\n        goto skip_optional_pos;\n    }\n    if (args[4]) {\n        mod = args[4];\n        if (!--noptargs) {\n            goto skip_optional_pos;\n        }\n    }\n    if (args[5]) {\n        registry = args[5];\n        if (!--noptargs) {\n            goto skip_optional_pos;\n        }\n    }\n    if (args[6]) {\n        module_globals = args[6];\n        if (!--noptargs) {\n            goto skip_optional_pos;\n        }\n    }\n    sourceobj = args[7];\nskip_optional_pos:\n    return_value = warnings_warn_explicit_impl(module, message, category, filename, lineno, mod, registry, module_globals, sourceobj);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(warnings_filters_mutated__doc__,\n\"_filters_mutated($module, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define WARNINGS_FILTERS_MUTATED_METHODDEF    \\\n    {\"_filters_mutated\", (PyCFunction)warnings_filters_mutated, METH_NOARGS, warnings_filters_mutated__doc__},\n\nstatic PyObject *\nwarnings_filters_mutated_impl(PyObject *module);\n\nstatic PyObject *\nwarnings_filters_mutated(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return warnings_filters_mutated_impl(module);\n}\n/*[clinic end generated code: output=f8d67e0f75771c36 input=a9049054013a1b77]*/\n"
  },
  {
    "path": "Clinic/bltinmodule.c.h",
    "content": "/*[clinic input]\npreserve\n[clinic start generated code]*/\n\n#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n#  include \"pycore_gc.h\"            // PyGC_Head\n#  include \"pycore_runtime.h\"       // _Py_ID()\n#endif\n\n\nPyDoc_STRVAR(builtin___import____doc__,\n\"__import__($module, /, name, globals=None, locals=None, fromlist=(),\\n\"\n\"           level=0)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Import a module.\\n\"\n\"\\n\"\n\"Because this function is meant for use by the Python\\n\"\n\"interpreter and not for general use, it is better to use\\n\"\n\"importlib.import_module() to programmatically import a module.\\n\"\n\"\\n\"\n\"The globals argument is only used to determine the context;\\n\"\n\"they are not modified.  The locals argument is unused.  The fromlist\\n\"\n\"should be a list of names to emulate ``from name import ...``, or an\\n\"\n\"empty list to emulate ``import name``.\\n\"\n\"When importing a module from a package, note that __import__(\\'A.B\\', ...)\\n\"\n\"returns package A when fromlist is empty, but its submodule B when\\n\"\n\"fromlist is not empty.  The level argument is used to determine whether to\\n\"\n\"perform absolute or relative imports: 0 is absolute, while a positive number\\n\"\n\"is the number of parent directories to search relative to the current module.\");\n\n#define BUILTIN___IMPORT___METHODDEF    \\\n    {\"__import__\", _PyCFunction_CAST(builtin___import__), METH_FASTCALL|METH_KEYWORDS, builtin___import____doc__},\n\nstatic PyObject *\nbuiltin___import___impl(PyObject *module, PyObject *name, PyObject *globals,\n                        PyObject *locals, PyObject *fromlist, int level);\n\nstatic PyObject *\nbuiltin___import__(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 5\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(name), &_Py_ID(globals), &_Py_ID(locals), &_Py_ID(fromlist), &_Py_ID(level), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"name\", \"globals\", \"locals\", \"fromlist\", \"level\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"__import__\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[5];\n    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;\n    PyObject *name;\n    PyObject *globals = NULL;\n    PyObject *locals = NULL;\n    PyObject *fromlist = NULL;\n    int level = 0;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 5, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    name = args[0];\n    if (!noptargs) {\n        goto skip_optional_pos;\n    }\n    if (args[1]) {\n        globals = args[1];\n        if (!--noptargs) {\n            goto skip_optional_pos;\n        }\n    }\n    if (args[2]) {\n        locals = args[2];\n        if (!--noptargs) {\n            goto skip_optional_pos;\n        }\n    }\n    if (args[3]) {\n        fromlist = args[3];\n        if (!--noptargs) {\n            goto skip_optional_pos;\n        }\n    }\n    level = _PyLong_AsInt(args[4]);\n    if (level == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\nskip_optional_pos:\n    return_value = builtin___import___impl(module, name, globals, locals, fromlist, level);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_abs__doc__,\n\"abs($module, x, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the absolute value of the argument.\");\n\n#define BUILTIN_ABS_METHODDEF    \\\n    {\"abs\", (PyCFunction)builtin_abs, METH_O, builtin_abs__doc__},\n\nPyDoc_STRVAR(builtin_all__doc__,\n\"all($module, iterable, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return True if bool(x) is True for all values x in the iterable.\\n\"\n\"\\n\"\n\"If the iterable is empty, return True.\");\n\n#define BUILTIN_ALL_METHODDEF    \\\n    {\"all\", (PyCFunction)builtin_all, METH_O, builtin_all__doc__},\n\nPyDoc_STRVAR(builtin_any__doc__,\n\"any($module, iterable, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return True if bool(x) is True for any x in the iterable.\\n\"\n\"\\n\"\n\"If the iterable is empty, return False.\");\n\n#define BUILTIN_ANY_METHODDEF    \\\n    {\"any\", (PyCFunction)builtin_any, METH_O, builtin_any__doc__},\n\nPyDoc_STRVAR(builtin_ascii__doc__,\n\"ascii($module, obj, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return an ASCII-only representation of an object.\\n\"\n\"\\n\"\n\"As repr(), return a string containing a printable representation of an\\n\"\n\"object, but escape the non-ASCII characters in the string returned by\\n\"\n\"repr() using \\\\\\\\x, \\\\\\\\u or \\\\\\\\U escapes. This generates a string similar\\n\"\n\"to that returned by repr() in Python 2.\");\n\n#define BUILTIN_ASCII_METHODDEF    \\\n    {\"ascii\", (PyCFunction)builtin_ascii, METH_O, builtin_ascii__doc__},\n\nPyDoc_STRVAR(builtin_bin__doc__,\n\"bin($module, number, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the binary representation of an integer.\\n\"\n\"\\n\"\n\"   >>> bin(2796202)\\n\"\n\"   \\'0b1010101010101010101010\\'\");\n\n#define BUILTIN_BIN_METHODDEF    \\\n    {\"bin\", (PyCFunction)builtin_bin, METH_O, builtin_bin__doc__},\n\nPyDoc_STRVAR(builtin_callable__doc__,\n\"callable($module, obj, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return whether the object is callable (i.e., some kind of function).\\n\"\n\"\\n\"\n\"Note that classes are callable, as are instances of classes with a\\n\"\n\"__call__() method.\");\n\n#define BUILTIN_CALLABLE_METHODDEF    \\\n    {\"callable\", (PyCFunction)builtin_callable, METH_O, builtin_callable__doc__},\n\nPyDoc_STRVAR(builtin_format__doc__,\n\"format($module, value, format_spec=\\'\\', /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return type(value).__format__(value, format_spec)\\n\"\n\"\\n\"\n\"Many built-in types implement format_spec according to the\\n\"\n\"Format Specification Mini-language. See help(\\'FORMATTING\\').\\n\"\n\"\\n\"\n\"If type(value) does not supply a method named __format__\\n\"\n\"and format_spec is empty, then str(value) is returned.\\n\"\n\"See also help(\\'SPECIALMETHODS\\').\");\n\n#define BUILTIN_FORMAT_METHODDEF    \\\n    {\"format\", _PyCFunction_CAST(builtin_format), METH_FASTCALL, builtin_format__doc__},\n\nstatic PyObject *\nbuiltin_format_impl(PyObject *module, PyObject *value, PyObject *format_spec);\n\nstatic PyObject *\nbuiltin_format(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *value;\n    PyObject *format_spec = NULL;\n\n    if (!_PyArg_CheckPositional(\"format\", nargs, 1, 2)) {\n        goto exit;\n    }\n    value = args[0];\n    if (nargs < 2) {\n        goto skip_optional;\n    }\n    if (!PyUnicode_Check(args[1])) {\n        _PyArg_BadArgument(\"format\", \"argument 2\", \"str\", args[1]);\n        goto exit;\n    }\n    format_spec = args[1];\nskip_optional:\n    return_value = builtin_format_impl(module, value, format_spec);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_chr__doc__,\n\"chr($module, i, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.\");\n\n#define BUILTIN_CHR_METHODDEF    \\\n    {\"chr\", (PyCFunction)builtin_chr, METH_O, builtin_chr__doc__},\n\nstatic PyObject *\nbuiltin_chr_impl(PyObject *module, int i);\n\nstatic PyObject *\nbuiltin_chr(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    int i;\n\n    i = _PyLong_AsInt(arg);\n    if (i == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = builtin_chr_impl(module, i);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_compile__doc__,\n\"compile($module, /, source, filename, mode, flags=0,\\n\"\n\"        dont_inherit=False, optimize=-1, *, _feature_version=-1)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Compile source into a code object that can be executed by exec() or eval().\\n\"\n\"\\n\"\n\"The source code may represent a Python module, statement or expression.\\n\"\n\"The filename will be used for run-time error messages.\\n\"\n\"The mode must be \\'exec\\' to compile a module, \\'single\\' to compile a\\n\"\n\"single (interactive) statement, or \\'eval\\' to compile an expression.\\n\"\n\"The flags argument, if present, controls which future statements influence\\n\"\n\"the compilation of the code.\\n\"\n\"The dont_inherit argument, if true, stops the compilation inheriting\\n\"\n\"the effects of any future statements in effect in the code calling\\n\"\n\"compile; if absent or false these statements do influence the compilation,\\n\"\n\"in addition to any features explicitly specified.\");\n\n#define BUILTIN_COMPILE_METHODDEF    \\\n    {\"compile\", _PyCFunction_CAST(builtin_compile), METH_FASTCALL|METH_KEYWORDS, builtin_compile__doc__},\n\nstatic PyObject *\nbuiltin_compile_impl(PyObject *module, PyObject *source, PyObject *filename,\n                     const char *mode, int flags, int dont_inherit,\n                     int optimize, int feature_version);\n\nstatic PyObject *\nbuiltin_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 7\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(source), &_Py_ID(filename), &_Py_ID(mode), &_Py_ID(flags), &_Py_ID(dont_inherit), &_Py_ID(optimize), &_Py_ID(_feature_version), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"source\", \"filename\", \"mode\", \"flags\", \"dont_inherit\", \"optimize\", \"_feature_version\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"compile\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[7];\n    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3;\n    PyObject *source;\n    PyObject *filename;\n    const char *mode;\n    int flags = 0;\n    int dont_inherit = 0;\n    int optimize = -1;\n    int feature_version = -1;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 6, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    source = args[0];\n    if (!PyUnicode_FSDecoder(args[1], &filename)) {\n        goto exit;\n    }\n    if (!PyUnicode_Check(args[2])) {\n        _PyArg_BadArgument(\"compile\", \"argument 'mode'\", \"str\", args[2]);\n        goto exit;\n    }\n    Py_ssize_t mode_length;\n    mode = PyUnicode_AsUTF8AndSize(args[2], &mode_length);\n    if (mode == NULL) {\n        goto exit;\n    }\n    if (strlen(mode) != (size_t)mode_length) {\n        PyErr_SetString(PyExc_ValueError, \"embedded null character\");\n        goto exit;\n    }\n    if (!noptargs) {\n        goto skip_optional_pos;\n    }\n    if (args[3]) {\n        flags = _PyLong_AsInt(args[3]);\n        if (flags == -1 && PyErr_Occurred()) {\n            goto exit;\n        }\n        if (!--noptargs) {\n            goto skip_optional_pos;\n        }\n    }\n    if (args[4]) {\n        dont_inherit = PyObject_IsTrue(args[4]);\n        if (dont_inherit < 0) {\n            goto exit;\n        }\n        if (!--noptargs) {\n            goto skip_optional_pos;\n        }\n    }\n    if (args[5]) {\n        optimize = _PyLong_AsInt(args[5]);\n        if (optimize == -1 && PyErr_Occurred()) {\n            goto exit;\n        }\n        if (!--noptargs) {\n            goto skip_optional_pos;\n        }\n    }\nskip_optional_pos:\n    if (!noptargs) {\n        goto skip_optional_kwonly;\n    }\n    feature_version = _PyLong_AsInt(args[6]);\n    if (feature_version == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\nskip_optional_kwonly:\n    return_value = builtin_compile_impl(module, source, filename, mode, flags, dont_inherit, optimize, feature_version);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_dir__doc__,\n\"dir($module, arg=<unrepresentable>, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Show attributes of an object.\\n\"\n\"\\n\"\n\"If called without an argument, return the names in the current scope.\\n\"\n\"Else, return an alphabetized list of names comprising (some of) the attributes\\n\"\n\"of the given object, and of attributes reachable from it.\\n\"\n\"If the object supplies a method named __dir__, it will be used; otherwise\\n\"\n\"the default dir() logic is used and returns:\\n\"\n\"  for a module object: the module\\'s attributes.\\n\"\n\"  for a class object:  its attributes, and recursively the attributes\\n\"\n\"    of its bases.\\n\"\n\"  for any other object: its attributes, its class\\'s attributes, and\\n\"\n\"    recursively the attributes of its class\\'s base classes.\");\n\n#define BUILTIN_DIR_METHODDEF    \\\n    {\"dir\", _PyCFunction_CAST(builtin_dir), METH_FASTCALL, builtin_dir__doc__},\n\nstatic PyObject *\nbuiltin_dir_impl(PyObject *module, PyObject *arg);\n\nstatic PyObject *\nbuiltin_dir(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *arg = NULL;\n\n    if (!_PyArg_CheckPositional(\"dir\", nargs, 0, 1)) {\n        goto exit;\n    }\n    if (nargs < 1) {\n        goto skip_optional;\n    }\n    arg = args[0];\nskip_optional:\n    return_value = builtin_dir_impl(module, arg);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_divmod__doc__,\n\"divmod($module, x, y, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the tuple (x//y, x%y).  Invariant: div*y + mod == x.\");\n\n#define BUILTIN_DIVMOD_METHODDEF    \\\n    {\"divmod\", _PyCFunction_CAST(builtin_divmod), METH_FASTCALL, builtin_divmod__doc__},\n\nstatic PyObject *\nbuiltin_divmod_impl(PyObject *module, PyObject *x, PyObject *y);\n\nstatic PyObject *\nbuiltin_divmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *x;\n    PyObject *y;\n\n    if (!_PyArg_CheckPositional(\"divmod\", nargs, 2, 2)) {\n        goto exit;\n    }\n    x = args[0];\n    y = args[1];\n    return_value = builtin_divmod_impl(module, x, y);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_eval__doc__,\n\"eval($module, source, globals=None, locals=None, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Evaluate the given source in the context of globals and locals.\\n\"\n\"\\n\"\n\"The source may be a string representing a Python expression\\n\"\n\"or a code object as returned by compile().\\n\"\n\"The globals must be a dictionary and locals can be any mapping,\\n\"\n\"defaulting to the current globals and locals.\\n\"\n\"If only globals is given, locals defaults to it.\");\n\n#define BUILTIN_EVAL_METHODDEF    \\\n    {\"eval\", _PyCFunction_CAST(builtin_eval), METH_FASTCALL, builtin_eval__doc__},\n\nstatic PyObject *\nbuiltin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,\n                  PyObject *locals);\n\nstatic PyObject *\nbuiltin_eval(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *source;\n    PyObject *globals = Py_None;\n    PyObject *locals = Py_None;\n\n    if (!_PyArg_CheckPositional(\"eval\", nargs, 1, 3)) {\n        goto exit;\n    }\n    source = args[0];\n    if (nargs < 2) {\n        goto skip_optional;\n    }\n    globals = args[1];\n    if (nargs < 3) {\n        goto skip_optional;\n    }\n    locals = args[2];\nskip_optional:\n    return_value = builtin_eval_impl(module, source, globals, locals);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_exec__doc__,\n\"exec($module, source, globals=None, locals=None, /, *, closure=None)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Execute the given source in the context of globals and locals.\\n\"\n\"\\n\"\n\"The source may be a string representing one or more Python statements\\n\"\n\"or a code object as returned by compile().\\n\"\n\"The globals must be a dictionary and locals can be any mapping,\\n\"\n\"defaulting to the current globals and locals.\\n\"\n\"If only globals is given, locals defaults to it.\\n\"\n\"The closure must be a tuple of cellvars, and can only be used\\n\"\n\"when source is a code object requiring exactly that many cellvars.\");\n\n#define BUILTIN_EXEC_METHODDEF    \\\n    {\"exec\", _PyCFunction_CAST(builtin_exec), METH_FASTCALL|METH_KEYWORDS, builtin_exec__doc__},\n\nstatic PyObject *\nbuiltin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,\n                  PyObject *locals, PyObject *closure);\n\nstatic PyObject *\nbuiltin_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 1\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(closure), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"\", \"\", \"\", \"closure\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"exec\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[4];\n    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;\n    PyObject *source;\n    PyObject *globals = Py_None;\n    PyObject *locals = Py_None;\n    PyObject *closure = NULL;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    source = args[0];\n    if (nargs < 2) {\n        goto skip_optional_posonly;\n    }\n    noptargs--;\n    globals = args[1];\n    if (nargs < 3) {\n        goto skip_optional_posonly;\n    }\n    noptargs--;\n    locals = args[2];\nskip_optional_posonly:\n    if (!noptargs) {\n        goto skip_optional_kwonly;\n    }\n    closure = args[3];\nskip_optional_kwonly:\n    return_value = builtin_exec_impl(module, source, globals, locals, closure);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_getattr__doc__,\n\"getattr($module, object, name, default=<unrepresentable>, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Get a named attribute from an object.\\n\"\n\"\\n\"\n\"getattr(x, \\'y\\') is equivalent to x.y\\n\"\n\"When a default argument is given, it is returned when the attribute doesn\\'t\\n\"\n\"exist; without it, an exception is raised in that case.\");\n\n#define BUILTIN_GETATTR_METHODDEF    \\\n    {\"getattr\", _PyCFunction_CAST(builtin_getattr), METH_FASTCALL, builtin_getattr__doc__},\n\nstatic PyObject *\nbuiltin_getattr_impl(PyObject *module, PyObject *object, PyObject *name,\n                     PyObject *default_value);\n\nstatic PyObject *\nbuiltin_getattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *object;\n    PyObject *name;\n    PyObject *default_value = NULL;\n\n    if (!_PyArg_CheckPositional(\"getattr\", nargs, 2, 3)) {\n        goto exit;\n    }\n    object = args[0];\n    name = args[1];\n    if (nargs < 3) {\n        goto skip_optional;\n    }\n    default_value = args[2];\nskip_optional:\n    return_value = builtin_getattr_impl(module, object, name, default_value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_globals__doc__,\n\"globals($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the dictionary containing the current scope\\'s global variables.\\n\"\n\"\\n\"\n\"NOTE: Updates to this dictionary *will* affect name lookups in the current\\n\"\n\"global scope and vice-versa.\");\n\n#define BUILTIN_GLOBALS_METHODDEF    \\\n    {\"globals\", (PyCFunction)builtin_globals, METH_NOARGS, builtin_globals__doc__},\n\nstatic PyObject *\nbuiltin_globals_impl(PyObject *module);\n\nstatic PyObject *\nbuiltin_globals(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return builtin_globals_impl(module);\n}\n\nPyDoc_STRVAR(builtin_hasattr__doc__,\n\"hasattr($module, obj, name, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return whether the object has an attribute with the given name.\\n\"\n\"\\n\"\n\"This is done by calling getattr(obj, name) and catching AttributeError.\");\n\n#define BUILTIN_HASATTR_METHODDEF    \\\n    {\"hasattr\", _PyCFunction_CAST(builtin_hasattr), METH_FASTCALL, builtin_hasattr__doc__},\n\nstatic PyObject *\nbuiltin_hasattr_impl(PyObject *module, PyObject *obj, PyObject *name);\n\nstatic PyObject *\nbuiltin_hasattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *obj;\n    PyObject *name;\n\n    if (!_PyArg_CheckPositional(\"hasattr\", nargs, 2, 2)) {\n        goto exit;\n    }\n    obj = args[0];\n    name = args[1];\n    return_value = builtin_hasattr_impl(module, obj, name);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_id__doc__,\n\"id($module, obj, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the identity of an object.\\n\"\n\"\\n\"\n\"This is guaranteed to be unique among simultaneously existing objects.\\n\"\n\"(CPython uses the object\\'s memory address.)\");\n\n#define BUILTIN_ID_METHODDEF    \\\n    {\"id\", (PyCFunction)builtin_id, METH_O, builtin_id__doc__},\n\nPyDoc_STRVAR(builtin_next__doc__,\n\"next($module, iterator, default=<unrepresentable>, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the next item from the iterator.\\n\"\n\"\\n\"\n\"If default is given and the iterator is exhausted,\\n\"\n\"it is returned instead of raising StopIteration.\");\n\n#define BUILTIN_NEXT_METHODDEF    \\\n    {\"next\", _PyCFunction_CAST(builtin_next), METH_FASTCALL, builtin_next__doc__},\n\nstatic PyObject *\nbuiltin_next_impl(PyObject *module, PyObject *iterator,\n                  PyObject *default_value);\n\nstatic PyObject *\nbuiltin_next(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *iterator;\n    PyObject *default_value = NULL;\n\n    if (!_PyArg_CheckPositional(\"next\", nargs, 1, 2)) {\n        goto exit;\n    }\n    iterator = args[0];\n    if (nargs < 2) {\n        goto skip_optional;\n    }\n    default_value = args[1];\nskip_optional:\n    return_value = builtin_next_impl(module, iterator, default_value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_setattr__doc__,\n\"setattr($module, obj, name, value, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Sets the named attribute on the given object to the specified value.\\n\"\n\"\\n\"\n\"setattr(x, \\'y\\', v) is equivalent to ``x.y = v``\");\n\n#define BUILTIN_SETATTR_METHODDEF    \\\n    {\"setattr\", _PyCFunction_CAST(builtin_setattr), METH_FASTCALL, builtin_setattr__doc__},\n\nstatic PyObject *\nbuiltin_setattr_impl(PyObject *module, PyObject *obj, PyObject *name,\n                     PyObject *value);\n\nstatic PyObject *\nbuiltin_setattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *obj;\n    PyObject *name;\n    PyObject *value;\n\n    if (!_PyArg_CheckPositional(\"setattr\", nargs, 3, 3)) {\n        goto exit;\n    }\n    obj = args[0];\n    name = args[1];\n    value = args[2];\n    return_value = builtin_setattr_impl(module, obj, name, value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_delattr__doc__,\n\"delattr($module, obj, name, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Deletes the named attribute from the given object.\\n\"\n\"\\n\"\n\"delattr(x, \\'y\\') is equivalent to ``del x.y``\");\n\n#define BUILTIN_DELATTR_METHODDEF    \\\n    {\"delattr\", _PyCFunction_CAST(builtin_delattr), METH_FASTCALL, builtin_delattr__doc__},\n\nstatic PyObject *\nbuiltin_delattr_impl(PyObject *module, PyObject *obj, PyObject *name);\n\nstatic PyObject *\nbuiltin_delattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *obj;\n    PyObject *name;\n\n    if (!_PyArg_CheckPositional(\"delattr\", nargs, 2, 2)) {\n        goto exit;\n    }\n    obj = args[0];\n    name = args[1];\n    return_value = builtin_delattr_impl(module, obj, name);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_hash__doc__,\n\"hash($module, obj, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the hash value for the given object.\\n\"\n\"\\n\"\n\"Two objects that compare equal must also have the same hash value, but the\\n\"\n\"reverse is not necessarily true.\");\n\n#define BUILTIN_HASH_METHODDEF    \\\n    {\"hash\", (PyCFunction)builtin_hash, METH_O, builtin_hash__doc__},\n\nPyDoc_STRVAR(builtin_hex__doc__,\n\"hex($module, number, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the hexadecimal representation of an integer.\\n\"\n\"\\n\"\n\"   >>> hex(12648430)\\n\"\n\"   \\'0xc0ffee\\'\");\n\n#define BUILTIN_HEX_METHODDEF    \\\n    {\"hex\", (PyCFunction)builtin_hex, METH_O, builtin_hex__doc__},\n\nPyDoc_STRVAR(builtin_iter__doc__,\n\"iter($module, object, sentinel=<unrepresentable>, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Get an iterator from an object.\\n\"\n\"\\n\"\n\"In the first form, the argument must supply its own iterator, or be a sequence.\\n\"\n\"In the second form, the callable is called until it returns the sentinel.\");\n\n#define BUILTIN_ITER_METHODDEF    \\\n    {\"iter\", _PyCFunction_CAST(builtin_iter), METH_FASTCALL, builtin_iter__doc__},\n\nstatic PyObject *\nbuiltin_iter_impl(PyObject *module, PyObject *object, PyObject *sentinel);\n\nstatic PyObject *\nbuiltin_iter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *object;\n    PyObject *sentinel = NULL;\n\n    if (!_PyArg_CheckPositional(\"iter\", nargs, 1, 2)) {\n        goto exit;\n    }\n    object = args[0];\n    if (nargs < 2) {\n        goto skip_optional;\n    }\n    sentinel = args[1];\nskip_optional:\n    return_value = builtin_iter_impl(module, object, sentinel);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_aiter__doc__,\n\"aiter($module, async_iterable, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return an AsyncIterator for an AsyncIterable object.\");\n\n#define BUILTIN_AITER_METHODDEF    \\\n    {\"aiter\", (PyCFunction)builtin_aiter, METH_O, builtin_aiter__doc__},\n\nPyDoc_STRVAR(builtin_anext__doc__,\n\"anext($module, aiterator, default=<unrepresentable>, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"async anext(aiterator[, default])\\n\"\n\"\\n\"\n\"Return the next item from the async iterator.  If default is given and the async\\n\"\n\"iterator is exhausted, it is returned instead of raising StopAsyncIteration.\");\n\n#define BUILTIN_ANEXT_METHODDEF    \\\n    {\"anext\", _PyCFunction_CAST(builtin_anext), METH_FASTCALL, builtin_anext__doc__},\n\nstatic PyObject *\nbuiltin_anext_impl(PyObject *module, PyObject *aiterator,\n                   PyObject *default_value);\n\nstatic PyObject *\nbuiltin_anext(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *aiterator;\n    PyObject *default_value = NULL;\n\n    if (!_PyArg_CheckPositional(\"anext\", nargs, 1, 2)) {\n        goto exit;\n    }\n    aiterator = args[0];\n    if (nargs < 2) {\n        goto skip_optional;\n    }\n    default_value = args[1];\nskip_optional:\n    return_value = builtin_anext_impl(module, aiterator, default_value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_len__doc__,\n\"len($module, obj, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the number of items in a container.\");\n\n#define BUILTIN_LEN_METHODDEF    \\\n    {\"len\", (PyCFunction)builtin_len, METH_O, builtin_len__doc__},\n\nPyDoc_STRVAR(builtin_locals__doc__,\n\"locals($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return a dictionary containing the current scope\\'s local variables.\\n\"\n\"\\n\"\n\"NOTE: Whether or not updates to this dictionary will affect name lookups in\\n\"\n\"the local scope and vice-versa is *implementation dependent* and not\\n\"\n\"covered by any backwards compatibility guarantees.\");\n\n#define BUILTIN_LOCALS_METHODDEF    \\\n    {\"locals\", (PyCFunction)builtin_locals, METH_NOARGS, builtin_locals__doc__},\n\nstatic PyObject *\nbuiltin_locals_impl(PyObject *module);\n\nstatic PyObject *\nbuiltin_locals(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return builtin_locals_impl(module);\n}\n\nPyDoc_STRVAR(builtin_oct__doc__,\n\"oct($module, number, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the octal representation of an integer.\\n\"\n\"\\n\"\n\"   >>> oct(342391)\\n\"\n\"   \\'0o1234567\\'\");\n\n#define BUILTIN_OCT_METHODDEF    \\\n    {\"oct\", (PyCFunction)builtin_oct, METH_O, builtin_oct__doc__},\n\nPyDoc_STRVAR(builtin_ord__doc__,\n\"ord($module, c, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the Unicode code point for a one-character string.\");\n\n#define BUILTIN_ORD_METHODDEF    \\\n    {\"ord\", (PyCFunction)builtin_ord, METH_O, builtin_ord__doc__},\n\nPyDoc_STRVAR(builtin_pow__doc__,\n\"pow($module, /, base, exp, mod=None)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Equivalent to base**exp with 2 arguments or base**exp % mod with 3 arguments\\n\"\n\"\\n\"\n\"Some types, such as ints, are able to use a more efficient algorithm when\\n\"\n\"invoked using the three argument form.\");\n\n#define BUILTIN_POW_METHODDEF    \\\n    {\"pow\", _PyCFunction_CAST(builtin_pow), METH_FASTCALL|METH_KEYWORDS, builtin_pow__doc__},\n\nstatic PyObject *\nbuiltin_pow_impl(PyObject *module, PyObject *base, PyObject *exp,\n                 PyObject *mod);\n\nstatic PyObject *\nbuiltin_pow(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 3\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(base), &_Py_ID(exp), &_Py_ID(mod), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"base\", \"exp\", \"mod\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"pow\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[3];\n    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;\n    PyObject *base;\n    PyObject *exp;\n    PyObject *mod = Py_None;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    base = args[0];\n    exp = args[1];\n    if (!noptargs) {\n        goto skip_optional_pos;\n    }\n    mod = args[2];\nskip_optional_pos:\n    return_value = builtin_pow_impl(module, base, exp, mod);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_print__doc__,\n\"print($module, /, *args, sep=\\' \\', end=\\'\\\\n\\', file=None, flush=False)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Prints the values to a stream, or to sys.stdout by default.\\n\"\n\"\\n\"\n\"  sep\\n\"\n\"    string inserted between values, default a space.\\n\"\n\"  end\\n\"\n\"    string appended after the last value, default a newline.\\n\"\n\"  file\\n\"\n\"    a file-like object (stream); defaults to the current sys.stdout.\\n\"\n\"  flush\\n\"\n\"    whether to forcibly flush the stream.\");\n\n#define BUILTIN_PRINT_METHODDEF    \\\n    {\"print\", _PyCFunction_CAST(builtin_print), METH_FASTCALL|METH_KEYWORDS, builtin_print__doc__},\n\nstatic PyObject *\nbuiltin_print_impl(PyObject *module, PyObject *args, PyObject *sep,\n                   PyObject *end, PyObject *file, int flush);\n\nstatic PyObject *\nbuiltin_print(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 4\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(sep), &_Py_ID(end), &_Py_ID(file), &_Py_ID(flush), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"sep\", \"end\", \"file\", \"flush\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"print\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[5];\n    Py_ssize_t noptargs = 0 + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;\n    PyObject *__clinic_args = NULL;\n    PyObject *sep = Py_None;\n    PyObject *end = Py_None;\n    PyObject *file = Py_None;\n    int flush = 0;\n\n    args = _PyArg_UnpackKeywordsWithVararg(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    __clinic_args = args[0];\n    if (!noptargs) {\n        goto skip_optional_kwonly;\n    }\n    if (args[1]) {\n        sep = args[1];\n        if (!--noptargs) {\n            goto skip_optional_kwonly;\n        }\n    }\n    if (args[2]) {\n        end = args[2];\n        if (!--noptargs) {\n            goto skip_optional_kwonly;\n        }\n    }\n    if (args[3]) {\n        file = args[3];\n        if (!--noptargs) {\n            goto skip_optional_kwonly;\n        }\n    }\n    flush = PyObject_IsTrue(args[4]);\n    if (flush < 0) {\n        goto exit;\n    }\nskip_optional_kwonly:\n    return_value = builtin_print_impl(module, __clinic_args, sep, end, file, flush);\n\nexit:\n    Py_XDECREF(__clinic_args);\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_input__doc__,\n\"input($module, prompt=\\'\\', /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Read a string from standard input.  The trailing newline is stripped.\\n\"\n\"\\n\"\n\"The prompt string, if given, is printed to standard output without a\\n\"\n\"trailing newline before reading input.\\n\"\n\"\\n\"\n\"If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.\\n\"\n\"On *nix systems, readline is used if available.\");\n\n#define BUILTIN_INPUT_METHODDEF    \\\n    {\"input\", _PyCFunction_CAST(builtin_input), METH_FASTCALL, builtin_input__doc__},\n\nstatic PyObject *\nbuiltin_input_impl(PyObject *module, PyObject *prompt);\n\nstatic PyObject *\nbuiltin_input(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *prompt = NULL;\n\n    if (!_PyArg_CheckPositional(\"input\", nargs, 0, 1)) {\n        goto exit;\n    }\n    if (nargs < 1) {\n        goto skip_optional;\n    }\n    prompt = args[0];\nskip_optional:\n    return_value = builtin_input_impl(module, prompt);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_repr__doc__,\n\"repr($module, obj, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the canonical string representation of the object.\\n\"\n\"\\n\"\n\"For many object types, including most builtins, eval(repr(obj)) == obj.\");\n\n#define BUILTIN_REPR_METHODDEF    \\\n    {\"repr\", (PyCFunction)builtin_repr, METH_O, builtin_repr__doc__},\n\nPyDoc_STRVAR(builtin_round__doc__,\n\"round($module, /, number, ndigits=None)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Round a number to a given precision in decimal digits.\\n\"\n\"\\n\"\n\"The return value is an integer if ndigits is omitted or None.  Otherwise\\n\"\n\"the return value has the same type as the number.  ndigits may be negative.\");\n\n#define BUILTIN_ROUND_METHODDEF    \\\n    {\"round\", _PyCFunction_CAST(builtin_round), METH_FASTCALL|METH_KEYWORDS, builtin_round__doc__},\n\nstatic PyObject *\nbuiltin_round_impl(PyObject *module, PyObject *number, PyObject *ndigits);\n\nstatic PyObject *\nbuiltin_round(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 2\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(number), &_Py_ID(ndigits), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"number\", \"ndigits\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"round\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[2];\n    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;\n    PyObject *number;\n    PyObject *ndigits = Py_None;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    number = args[0];\n    if (!noptargs) {\n        goto skip_optional_pos;\n    }\n    ndigits = args[1];\nskip_optional_pos:\n    return_value = builtin_round_impl(module, number, ndigits);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_vars__doc__,\n\"vars($module, object=<unrepresentable>, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Show vars.\\n\"\n\"\\n\"\n\"Without arguments, equivalent to locals().\\n\"\n\"With an argument, equivalent to object.__dict__.\");\n\n#define BUILTIN_VARS_METHODDEF    \\\n    {\"vars\", _PyCFunction_CAST(builtin_vars), METH_FASTCALL, builtin_vars__doc__},\n\nstatic PyObject *\nbuiltin_vars_impl(PyObject *module, PyObject *object);\n\nstatic PyObject *\nbuiltin_vars(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *object = NULL;\n\n    if (!_PyArg_CheckPositional(\"vars\", nargs, 0, 1)) {\n        goto exit;\n    }\n    if (nargs < 1) {\n        goto skip_optional;\n    }\n    object = args[0];\nskip_optional:\n    return_value = builtin_vars_impl(module, object);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_sum__doc__,\n\"sum($module, iterable, /, start=0)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the sum of a \\'start\\' value (default: 0) plus an iterable of numbers\\n\"\n\"\\n\"\n\"When the iterable is empty, return the start value.\\n\"\n\"This function is intended specifically for use with numeric values and may\\n\"\n\"reject non-numeric types.\");\n\n#define BUILTIN_SUM_METHODDEF    \\\n    {\"sum\", _PyCFunction_CAST(builtin_sum), METH_FASTCALL|METH_KEYWORDS, builtin_sum__doc__},\n\nstatic PyObject *\nbuiltin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start);\n\nstatic PyObject *\nbuiltin_sum(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 1\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(start), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"\", \"start\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"sum\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[2];\n    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;\n    PyObject *iterable;\n    PyObject *start = NULL;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    iterable = args[0];\n    if (!noptargs) {\n        goto skip_optional_pos;\n    }\n    start = args[1];\nskip_optional_pos:\n    return_value = builtin_sum_impl(module, iterable, start);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_isinstance__doc__,\n\"isinstance($module, obj, class_or_tuple, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return whether an object is an instance of a class or of a subclass thereof.\\n\"\n\"\\n\"\n\"A tuple, as in ``isinstance(x, (A, B, ...))``, may be given as the target to\\n\"\n\"check against. This is equivalent to ``isinstance(x, A) or isinstance(x, B)\\n\"\n\"or ...`` etc.\");\n\n#define BUILTIN_ISINSTANCE_METHODDEF    \\\n    {\"isinstance\", _PyCFunction_CAST(builtin_isinstance), METH_FASTCALL, builtin_isinstance__doc__},\n\nstatic PyObject *\nbuiltin_isinstance_impl(PyObject *module, PyObject *obj,\n                        PyObject *class_or_tuple);\n\nstatic PyObject *\nbuiltin_isinstance(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *obj;\n    PyObject *class_or_tuple;\n\n    if (!_PyArg_CheckPositional(\"isinstance\", nargs, 2, 2)) {\n        goto exit;\n    }\n    obj = args[0];\n    class_or_tuple = args[1];\n    return_value = builtin_isinstance_impl(module, obj, class_or_tuple);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(builtin_issubclass__doc__,\n\"issubclass($module, cls, class_or_tuple, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return whether \\'cls\\' is derived from another class or is the same class.\\n\"\n\"\\n\"\n\"A tuple, as in ``issubclass(x, (A, B, ...))``, may be given as the target to\\n\"\n\"check against. This is equivalent to ``issubclass(x, A) or issubclass(x, B)\\n\"\n\"or ...``.\");\n\n#define BUILTIN_ISSUBCLASS_METHODDEF    \\\n    {\"issubclass\", _PyCFunction_CAST(builtin_issubclass), METH_FASTCALL, builtin_issubclass__doc__},\n\nstatic PyObject *\nbuiltin_issubclass_impl(PyObject *module, PyObject *cls,\n                        PyObject *class_or_tuple);\n\nstatic PyObject *\nbuiltin_issubclass(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *cls;\n    PyObject *class_or_tuple;\n\n    if (!_PyArg_CheckPositional(\"issubclass\", nargs, 2, 2)) {\n        goto exit;\n    }\n    cls = args[0];\n    class_or_tuple = args[1];\n    return_value = builtin_issubclass_impl(module, cls, class_or_tuple);\n\nexit:\n    return return_value;\n}\n/*[clinic end generated code: output=ef2f16ece134d62d input=a9049054013a1b77]*/\n"
  },
  {
    "path": "Clinic/context.c.h",
    "content": "/*[clinic input]\npreserve\n[clinic start generated code]*/\n\n#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n#  include \"pycore_gc.h\"            // PyGC_Head\n#  include \"pycore_runtime.h\"       // _Py_ID()\n#endif\n\n\nPyDoc_STRVAR(_contextvars_Context_get__doc__,\n\"get($self, key, default=None, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the value for `key` if `key` has the value in the context object.\\n\"\n\"\\n\"\n\"If `key` does not exist, return `default`. If `default` is not given,\\n\"\n\"return None.\");\n\n#define _CONTEXTVARS_CONTEXT_GET_METHODDEF    \\\n    {\"get\", _PyCFunction_CAST(_contextvars_Context_get), METH_FASTCALL, _contextvars_Context_get__doc__},\n\nstatic PyObject *\n_contextvars_Context_get_impl(PyContext *self, PyObject *key,\n                              PyObject *default_value);\n\nstatic PyObject *\n_contextvars_Context_get(PyContext *self, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *key;\n    PyObject *default_value = Py_None;\n\n    if (!_PyArg_CheckPositional(\"get\", nargs, 1, 2)) {\n        goto exit;\n    }\n    key = args[0];\n    if (nargs < 2) {\n        goto skip_optional;\n    }\n    default_value = args[1];\nskip_optional:\n    return_value = _contextvars_Context_get_impl(self, key, default_value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(_contextvars_Context_items__doc__,\n\"items($self, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return all variables and their values in the context object.\\n\"\n\"\\n\"\n\"The result is returned as a list of 2-tuples (variable, value).\");\n\n#define _CONTEXTVARS_CONTEXT_ITEMS_METHODDEF    \\\n    {\"items\", (PyCFunction)_contextvars_Context_items, METH_NOARGS, _contextvars_Context_items__doc__},\n\nstatic PyObject *\n_contextvars_Context_items_impl(PyContext *self);\n\nstatic PyObject *\n_contextvars_Context_items(PyContext *self, PyObject *Py_UNUSED(ignored))\n{\n    return _contextvars_Context_items_impl(self);\n}\n\nPyDoc_STRVAR(_contextvars_Context_keys__doc__,\n\"keys($self, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return a list of all variables in the context object.\");\n\n#define _CONTEXTVARS_CONTEXT_KEYS_METHODDEF    \\\n    {\"keys\", (PyCFunction)_contextvars_Context_keys, METH_NOARGS, _contextvars_Context_keys__doc__},\n\nstatic PyObject *\n_contextvars_Context_keys_impl(PyContext *self);\n\nstatic PyObject *\n_contextvars_Context_keys(PyContext *self, PyObject *Py_UNUSED(ignored))\n{\n    return _contextvars_Context_keys_impl(self);\n}\n\nPyDoc_STRVAR(_contextvars_Context_values__doc__,\n\"values($self, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return a list of all variables\\' values in the context object.\");\n\n#define _CONTEXTVARS_CONTEXT_VALUES_METHODDEF    \\\n    {\"values\", (PyCFunction)_contextvars_Context_values, METH_NOARGS, _contextvars_Context_values__doc__},\n\nstatic PyObject *\n_contextvars_Context_values_impl(PyContext *self);\n\nstatic PyObject *\n_contextvars_Context_values(PyContext *self, PyObject *Py_UNUSED(ignored))\n{\n    return _contextvars_Context_values_impl(self);\n}\n\nPyDoc_STRVAR(_contextvars_Context_copy__doc__,\n\"copy($self, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return a shallow copy of the context object.\");\n\n#define _CONTEXTVARS_CONTEXT_COPY_METHODDEF    \\\n    {\"copy\", (PyCFunction)_contextvars_Context_copy, METH_NOARGS, _contextvars_Context_copy__doc__},\n\nstatic PyObject *\n_contextvars_Context_copy_impl(PyContext *self);\n\nstatic PyObject *\n_contextvars_Context_copy(PyContext *self, PyObject *Py_UNUSED(ignored))\n{\n    return _contextvars_Context_copy_impl(self);\n}\n\nPyDoc_STRVAR(_contextvars_ContextVar_get__doc__,\n\"get($self, default=<unrepresentable>, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return a value for the context variable for the current context.\\n\"\n\"\\n\"\n\"If there is no value for the variable in the current context, the method will:\\n\"\n\" * return the value of the default argument of the method, if provided; or\\n\"\n\" * return the default value for the context variable, if it was created\\n\"\n\"   with one; or\\n\"\n\" * raise a LookupError.\");\n\n#define _CONTEXTVARS_CONTEXTVAR_GET_METHODDEF    \\\n    {\"get\", _PyCFunction_CAST(_contextvars_ContextVar_get), METH_FASTCALL, _contextvars_ContextVar_get__doc__},\n\nstatic PyObject *\n_contextvars_ContextVar_get_impl(PyContextVar *self, PyObject *default_value);\n\nstatic PyObject *\n_contextvars_ContextVar_get(PyContextVar *self, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *default_value = NULL;\n\n    if (!_PyArg_CheckPositional(\"get\", nargs, 0, 1)) {\n        goto exit;\n    }\n    if (nargs < 1) {\n        goto skip_optional;\n    }\n    default_value = args[0];\nskip_optional:\n    return_value = _contextvars_ContextVar_get_impl(self, default_value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(_contextvars_ContextVar_set__doc__,\n\"set($self, value, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Call to set a new value for the context variable in the current context.\\n\"\n\"\\n\"\n\"The required value argument is the new value for the context variable.\\n\"\n\"\\n\"\n\"Returns a Token object that can be used to restore the variable to its previous\\n\"\n\"value via the `ContextVar.reset()` method.\");\n\n#define _CONTEXTVARS_CONTEXTVAR_SET_METHODDEF    \\\n    {\"set\", (PyCFunction)_contextvars_ContextVar_set, METH_O, _contextvars_ContextVar_set__doc__},\n\nPyDoc_STRVAR(_contextvars_ContextVar_reset__doc__,\n\"reset($self, token, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Reset the context variable.\\n\"\n\"\\n\"\n\"The variable is reset to the value it had before the `ContextVar.set()` that\\n\"\n\"created the token was used.\");\n\n#define _CONTEXTVARS_CONTEXTVAR_RESET_METHODDEF    \\\n    {\"reset\", (PyCFunction)_contextvars_ContextVar_reset, METH_O, _contextvars_ContextVar_reset__doc__},\n/*[clinic end generated code: output=0c94d4b919500438 input=a9049054013a1b77]*/\n"
  },
  {
    "path": "Clinic/import.c.h",
    "content": "/*[clinic input]\npreserve\n[clinic start generated code]*/\n\n#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n#  include \"pycore_gc.h\"            // PyGC_Head\n#  include \"pycore_runtime.h\"       // _Py_ID()\n#endif\n\n\nPyDoc_STRVAR(_imp_lock_held__doc__,\n\"lock_held($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return True if the import lock is currently held, else False.\\n\"\n\"\\n\"\n\"On platforms without threads, return False.\");\n\n#define _IMP_LOCK_HELD_METHODDEF    \\\n    {\"lock_held\", (PyCFunction)_imp_lock_held, METH_NOARGS, _imp_lock_held__doc__},\n\nstatic PyObject *\n_imp_lock_held_impl(PyObject *module);\n\nstatic PyObject *\n_imp_lock_held(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return _imp_lock_held_impl(module);\n}\n\nPyDoc_STRVAR(_imp_acquire_lock__doc__,\n\"acquire_lock($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Acquires the interpreter\\'s import lock for the current thread.\\n\"\n\"\\n\"\n\"This lock should be used by import hooks to ensure thread-safety when importing\\n\"\n\"modules. On platforms without threads, this function does nothing.\");\n\n#define _IMP_ACQUIRE_LOCK_METHODDEF    \\\n    {\"acquire_lock\", (PyCFunction)_imp_acquire_lock, METH_NOARGS, _imp_acquire_lock__doc__},\n\nstatic PyObject *\n_imp_acquire_lock_impl(PyObject *module);\n\nstatic PyObject *\n_imp_acquire_lock(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return _imp_acquire_lock_impl(module);\n}\n\nPyDoc_STRVAR(_imp_release_lock__doc__,\n\"release_lock($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Release the interpreter\\'s import lock.\\n\"\n\"\\n\"\n\"On platforms without threads, this function does nothing.\");\n\n#define _IMP_RELEASE_LOCK_METHODDEF    \\\n    {\"release_lock\", (PyCFunction)_imp_release_lock, METH_NOARGS, _imp_release_lock__doc__},\n\nstatic PyObject *\n_imp_release_lock_impl(PyObject *module);\n\nstatic PyObject *\n_imp_release_lock(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return _imp_release_lock_impl(module);\n}\n\nPyDoc_STRVAR(_imp__fix_co_filename__doc__,\n\"_fix_co_filename($module, code, path, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Changes code.co_filename to specify the passed-in file path.\\n\"\n\"\\n\"\n\"  code\\n\"\n\"    Code object to change.\\n\"\n\"  path\\n\"\n\"    File path to use.\");\n\n#define _IMP__FIX_CO_FILENAME_METHODDEF    \\\n    {\"_fix_co_filename\", _PyCFunction_CAST(_imp__fix_co_filename), METH_FASTCALL, _imp__fix_co_filename__doc__},\n\nstatic PyObject *\n_imp__fix_co_filename_impl(PyObject *module, PyCodeObject *code,\n                           PyObject *path);\n\nstatic PyObject *\n_imp__fix_co_filename(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyCodeObject *code;\n    PyObject *path;\n\n    if (!_PyArg_CheckPositional(\"_fix_co_filename\", nargs, 2, 2)) {\n        goto exit;\n    }\n    if (!PyObject_TypeCheck(args[0], &PyCode_Type)) {\n        _PyArg_BadArgument(\"_fix_co_filename\", \"argument 1\", (&PyCode_Type)->tp_name, args[0]);\n        goto exit;\n    }\n    code = (PyCodeObject *)args[0];\n    if (!PyUnicode_Check(args[1])) {\n        _PyArg_BadArgument(\"_fix_co_filename\", \"argument 2\", \"str\", args[1]);\n        goto exit;\n    }\n    path = args[1];\n    return_value = _imp__fix_co_filename_impl(module, code, path);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(_imp_create_builtin__doc__,\n\"create_builtin($module, spec, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Create an extension module.\");\n\n#define _IMP_CREATE_BUILTIN_METHODDEF    \\\n    {\"create_builtin\", (PyCFunction)_imp_create_builtin, METH_O, _imp_create_builtin__doc__},\n\nPyDoc_STRVAR(_imp_extension_suffixes__doc__,\n\"extension_suffixes($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Returns the list of file suffixes used to identify extension modules.\");\n\n#define _IMP_EXTENSION_SUFFIXES_METHODDEF    \\\n    {\"extension_suffixes\", (PyCFunction)_imp_extension_suffixes, METH_NOARGS, _imp_extension_suffixes__doc__},\n\nstatic PyObject *\n_imp_extension_suffixes_impl(PyObject *module);\n\nstatic PyObject *\n_imp_extension_suffixes(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return _imp_extension_suffixes_impl(module);\n}\n\nPyDoc_STRVAR(_imp_init_frozen__doc__,\n\"init_frozen($module, name, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Initializes a frozen module.\");\n\n#define _IMP_INIT_FROZEN_METHODDEF    \\\n    {\"init_frozen\", (PyCFunction)_imp_init_frozen, METH_O, _imp_init_frozen__doc__},\n\nstatic PyObject *\n_imp_init_frozen_impl(PyObject *module, PyObject *name);\n\nstatic PyObject *\n_imp_init_frozen(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    PyObject *name;\n\n    if (!PyUnicode_Check(arg)) {\n        _PyArg_BadArgument(\"init_frozen\", \"argument\", \"str\", arg);\n        goto exit;\n    }\n    name = arg;\n    return_value = _imp_init_frozen_impl(module, name);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(_imp_find_frozen__doc__,\n\"find_frozen($module, name, /, *, withdata=False)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return info about the corresponding frozen module (if there is one) or None.\\n\"\n\"\\n\"\n\"The returned info (a 2-tuple):\\n\"\n\"\\n\"\n\" * data         the raw marshalled bytes\\n\"\n\" * is_package   whether or not it is a package\\n\"\n\" * origname     the originally frozen module\\'s name, or None if not\\n\"\n\"                a stdlib module (this will usually be the same as\\n\"\n\"                the module\\'s current name)\");\n\n#define _IMP_FIND_FROZEN_METHODDEF    \\\n    {\"find_frozen\", _PyCFunction_CAST(_imp_find_frozen), METH_FASTCALL|METH_KEYWORDS, _imp_find_frozen__doc__},\n\nstatic PyObject *\n_imp_find_frozen_impl(PyObject *module, PyObject *name, int withdata);\n\nstatic PyObject *\n_imp_find_frozen(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 1\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(withdata), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"\", \"withdata\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"find_frozen\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[2];\n    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;\n    PyObject *name;\n    int withdata = 0;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    if (!PyUnicode_Check(args[0])) {\n        _PyArg_BadArgument(\"find_frozen\", \"argument 1\", \"str\", args[0]);\n        goto exit;\n    }\n    name = args[0];\n    if (!noptargs) {\n        goto skip_optional_kwonly;\n    }\n    withdata = PyObject_IsTrue(args[1]);\n    if (withdata < 0) {\n        goto exit;\n    }\nskip_optional_kwonly:\n    return_value = _imp_find_frozen_impl(module, name, withdata);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(_imp_get_frozen_object__doc__,\n\"get_frozen_object($module, name, data=None, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Create a code object for a frozen module.\");\n\n#define _IMP_GET_FROZEN_OBJECT_METHODDEF    \\\n    {\"get_frozen_object\", _PyCFunction_CAST(_imp_get_frozen_object), METH_FASTCALL, _imp_get_frozen_object__doc__},\n\nstatic PyObject *\n_imp_get_frozen_object_impl(PyObject *module, PyObject *name,\n                            PyObject *dataobj);\n\nstatic PyObject *\n_imp_get_frozen_object(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *name;\n    PyObject *dataobj = Py_None;\n\n    if (!_PyArg_CheckPositional(\"get_frozen_object\", nargs, 1, 2)) {\n        goto exit;\n    }\n    if (!PyUnicode_Check(args[0])) {\n        _PyArg_BadArgument(\"get_frozen_object\", \"argument 1\", \"str\", args[0]);\n        goto exit;\n    }\n    name = args[0];\n    if (nargs < 2) {\n        goto skip_optional;\n    }\n    dataobj = args[1];\nskip_optional:\n    return_value = _imp_get_frozen_object_impl(module, name, dataobj);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(_imp_is_frozen_package__doc__,\n\"is_frozen_package($module, name, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Returns True if the module name is of a frozen package.\");\n\n#define _IMP_IS_FROZEN_PACKAGE_METHODDEF    \\\n    {\"is_frozen_package\", (PyCFunction)_imp_is_frozen_package, METH_O, _imp_is_frozen_package__doc__},\n\nstatic PyObject *\n_imp_is_frozen_package_impl(PyObject *module, PyObject *name);\n\nstatic PyObject *\n_imp_is_frozen_package(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    PyObject *name;\n\n    if (!PyUnicode_Check(arg)) {\n        _PyArg_BadArgument(\"is_frozen_package\", \"argument\", \"str\", arg);\n        goto exit;\n    }\n    name = arg;\n    return_value = _imp_is_frozen_package_impl(module, name);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(_imp_is_builtin__doc__,\n\"is_builtin($module, name, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Returns True if the module name corresponds to a built-in module.\");\n\n#define _IMP_IS_BUILTIN_METHODDEF    \\\n    {\"is_builtin\", (PyCFunction)_imp_is_builtin, METH_O, _imp_is_builtin__doc__},\n\nstatic PyObject *\n_imp_is_builtin_impl(PyObject *module, PyObject *name);\n\nstatic PyObject *\n_imp_is_builtin(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    PyObject *name;\n\n    if (!PyUnicode_Check(arg)) {\n        _PyArg_BadArgument(\"is_builtin\", \"argument\", \"str\", arg);\n        goto exit;\n    }\n    name = arg;\n    return_value = _imp_is_builtin_impl(module, name);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(_imp_is_frozen__doc__,\n\"is_frozen($module, name, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Returns True if the module name corresponds to a frozen module.\");\n\n#define _IMP_IS_FROZEN_METHODDEF    \\\n    {\"is_frozen\", (PyCFunction)_imp_is_frozen, METH_O, _imp_is_frozen__doc__},\n\nstatic PyObject *\n_imp_is_frozen_impl(PyObject *module, PyObject *name);\n\nstatic PyObject *\n_imp_is_frozen(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    PyObject *name;\n\n    if (!PyUnicode_Check(arg)) {\n        _PyArg_BadArgument(\"is_frozen\", \"argument\", \"str\", arg);\n        goto exit;\n    }\n    name = arg;\n    return_value = _imp_is_frozen_impl(module, name);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(_imp__frozen_module_names__doc__,\n\"_frozen_module_names($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Returns the list of available frozen modules.\");\n\n#define _IMP__FROZEN_MODULE_NAMES_METHODDEF    \\\n    {\"_frozen_module_names\", (PyCFunction)_imp__frozen_module_names, METH_NOARGS, _imp__frozen_module_names__doc__},\n\nstatic PyObject *\n_imp__frozen_module_names_impl(PyObject *module);\n\nstatic PyObject *\n_imp__frozen_module_names(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return _imp__frozen_module_names_impl(module);\n}\n\nPyDoc_STRVAR(_imp__override_frozen_modules_for_tests__doc__,\n\"_override_frozen_modules_for_tests($module, override, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"(internal-only) Override PyConfig.use_frozen_modules.\\n\"\n\"\\n\"\n\"(-1: \\\"off\\\", 1: \\\"on\\\", 0: no override)\\n\"\n\"See frozen_modules() in Lib/test/support/import_helper.py.\");\n\n#define _IMP__OVERRIDE_FROZEN_MODULES_FOR_TESTS_METHODDEF    \\\n    {\"_override_frozen_modules_for_tests\", (PyCFunction)_imp__override_frozen_modules_for_tests, METH_O, _imp__override_frozen_modules_for_tests__doc__},\n\nstatic PyObject *\n_imp__override_frozen_modules_for_tests_impl(PyObject *module, int override);\n\nstatic PyObject *\n_imp__override_frozen_modules_for_tests(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    int override;\n\n    override = _PyLong_AsInt(arg);\n    if (override == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = _imp__override_frozen_modules_for_tests_impl(module, override);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(_imp__override_multi_interp_extensions_check__doc__,\n\"_override_multi_interp_extensions_check($module, override, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"(internal-only) Override PyInterpreterConfig.check_multi_interp_extensions.\\n\"\n\"\\n\"\n\"(-1: \\\"never\\\", 1: \\\"always\\\", 0: no override)\");\n\n#define _IMP__OVERRIDE_MULTI_INTERP_EXTENSIONS_CHECK_METHODDEF    \\\n    {\"_override_multi_interp_extensions_check\", (PyCFunction)_imp__override_multi_interp_extensions_check, METH_O, _imp__override_multi_interp_extensions_check__doc__},\n\nstatic PyObject *\n_imp__override_multi_interp_extensions_check_impl(PyObject *module,\n                                                  int override);\n\nstatic PyObject *\n_imp__override_multi_interp_extensions_check(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    int override;\n\n    override = _PyLong_AsInt(arg);\n    if (override == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = _imp__override_multi_interp_extensions_check_impl(module, override);\n\nexit:\n    return return_value;\n}\n\n#if defined(HAVE_DYNAMIC_LOADING)\n\nPyDoc_STRVAR(_imp_create_dynamic__doc__,\n\"create_dynamic($module, spec, file=<unrepresentable>, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Create an extension module.\");\n\n#define _IMP_CREATE_DYNAMIC_METHODDEF    \\\n    {\"create_dynamic\", _PyCFunction_CAST(_imp_create_dynamic), METH_FASTCALL, _imp_create_dynamic__doc__},\n\nstatic PyObject *\n_imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file);\n\nstatic PyObject *\n_imp_create_dynamic(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *spec;\n    PyObject *file = NULL;\n\n    if (!_PyArg_CheckPositional(\"create_dynamic\", nargs, 1, 2)) {\n        goto exit;\n    }\n    spec = args[0];\n    if (nargs < 2) {\n        goto skip_optional;\n    }\n    file = args[1];\nskip_optional:\n    return_value = _imp_create_dynamic_impl(module, spec, file);\n\nexit:\n    return return_value;\n}\n\n#endif /* defined(HAVE_DYNAMIC_LOADING) */\n\n#if defined(HAVE_DYNAMIC_LOADING)\n\nPyDoc_STRVAR(_imp_exec_dynamic__doc__,\n\"exec_dynamic($module, mod, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Initialize an extension module.\");\n\n#define _IMP_EXEC_DYNAMIC_METHODDEF    \\\n    {\"exec_dynamic\", (PyCFunction)_imp_exec_dynamic, METH_O, _imp_exec_dynamic__doc__},\n\nstatic int\n_imp_exec_dynamic_impl(PyObject *module, PyObject *mod);\n\nstatic PyObject *\n_imp_exec_dynamic(PyObject *module, PyObject *mod)\n{\n    PyObject *return_value = NULL;\n    int _return_value;\n\n    _return_value = _imp_exec_dynamic_impl(module, mod);\n    if ((_return_value == -1) && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = PyLong_FromLong((long)_return_value);\n\nexit:\n    return return_value;\n}\n\n#endif /* defined(HAVE_DYNAMIC_LOADING) */\n\nPyDoc_STRVAR(_imp_exec_builtin__doc__,\n\"exec_builtin($module, mod, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Initialize a built-in module.\");\n\n#define _IMP_EXEC_BUILTIN_METHODDEF    \\\n    {\"exec_builtin\", (PyCFunction)_imp_exec_builtin, METH_O, _imp_exec_builtin__doc__},\n\nstatic int\n_imp_exec_builtin_impl(PyObject *module, PyObject *mod);\n\nstatic PyObject *\n_imp_exec_builtin(PyObject *module, PyObject *mod)\n{\n    PyObject *return_value = NULL;\n    int _return_value;\n\n    _return_value = _imp_exec_builtin_impl(module, mod);\n    if ((_return_value == -1) && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = PyLong_FromLong((long)_return_value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(_imp_source_hash__doc__,\n\"source_hash($module, /, key, source)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define _IMP_SOURCE_HASH_METHODDEF    \\\n    {\"source_hash\", _PyCFunction_CAST(_imp_source_hash), METH_FASTCALL|METH_KEYWORDS, _imp_source_hash__doc__},\n\nstatic PyObject *\n_imp_source_hash_impl(PyObject *module, long key, Py_buffer *source);\n\nstatic PyObject *\n_imp_source_hash(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 2\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(key), &_Py_ID(source), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"key\", \"source\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"source_hash\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[2];\n    long key;\n    Py_buffer source = {NULL, NULL};\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    key = PyLong_AsLong(args[0]);\n    if (key == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    if (PyObject_GetBuffer(args[1], &source, PyBUF_SIMPLE) != 0) {\n        goto exit;\n    }\n    if (!PyBuffer_IsContiguous(&source, 'C')) {\n        _PyArg_BadArgument(\"source_hash\", \"argument 'source'\", \"contiguous buffer\", args[1]);\n        goto exit;\n    }\n    return_value = _imp_source_hash_impl(module, key, &source);\n\nexit:\n    /* Cleanup for source */\n    if (source.obj) {\n       PyBuffer_Release(&source);\n    }\n\n    return return_value;\n}\n\n#ifndef _IMP_CREATE_DYNAMIC_METHODDEF\n    #define _IMP_CREATE_DYNAMIC_METHODDEF\n#endif /* !defined(_IMP_CREATE_DYNAMIC_METHODDEF) */\n\n#ifndef _IMP_EXEC_DYNAMIC_METHODDEF\n    #define _IMP_EXEC_DYNAMIC_METHODDEF\n#endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */\n/*[clinic end generated code: output=a95ec234672280a2 input=a9049054013a1b77]*/\n"
  },
  {
    "path": "Clinic/instrumentation.c.h",
    "content": "/*[clinic input]\npreserve\n[clinic start generated code]*/\n\n#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n#  include \"pycore_gc.h\"            // PyGC_Head\n#  include \"pycore_runtime.h\"       // _Py_ID()\n#endif\n\n\nPyDoc_STRVAR(monitoring_use_tool_id__doc__,\n\"use_tool_id($module, tool_id, name, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define MONITORING_USE_TOOL_ID_METHODDEF    \\\n    {\"use_tool_id\", _PyCFunction_CAST(monitoring_use_tool_id), METH_FASTCALL, monitoring_use_tool_id__doc__},\n\nstatic PyObject *\nmonitoring_use_tool_id_impl(PyObject *module, int tool_id, PyObject *name);\n\nstatic PyObject *\nmonitoring_use_tool_id(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    int tool_id;\n    PyObject *name;\n\n    if (!_PyArg_CheckPositional(\"use_tool_id\", nargs, 2, 2)) {\n        goto exit;\n    }\n    tool_id = _PyLong_AsInt(args[0]);\n    if (tool_id == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    name = args[1];\n    return_value = monitoring_use_tool_id_impl(module, tool_id, name);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(monitoring_free_tool_id__doc__,\n\"free_tool_id($module, tool_id, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define MONITORING_FREE_TOOL_ID_METHODDEF    \\\n    {\"free_tool_id\", (PyCFunction)monitoring_free_tool_id, METH_O, monitoring_free_tool_id__doc__},\n\nstatic PyObject *\nmonitoring_free_tool_id_impl(PyObject *module, int tool_id);\n\nstatic PyObject *\nmonitoring_free_tool_id(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    int tool_id;\n\n    tool_id = _PyLong_AsInt(arg);\n    if (tool_id == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = monitoring_free_tool_id_impl(module, tool_id);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(monitoring_get_tool__doc__,\n\"get_tool($module, tool_id, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define MONITORING_GET_TOOL_METHODDEF    \\\n    {\"get_tool\", (PyCFunction)monitoring_get_tool, METH_O, monitoring_get_tool__doc__},\n\nstatic PyObject *\nmonitoring_get_tool_impl(PyObject *module, int tool_id);\n\nstatic PyObject *\nmonitoring_get_tool(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    int tool_id;\n\n    tool_id = _PyLong_AsInt(arg);\n    if (tool_id == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = monitoring_get_tool_impl(module, tool_id);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(monitoring_register_callback__doc__,\n\"register_callback($module, tool_id, event, func, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define MONITORING_REGISTER_CALLBACK_METHODDEF    \\\n    {\"register_callback\", _PyCFunction_CAST(monitoring_register_callback), METH_FASTCALL, monitoring_register_callback__doc__},\n\nstatic PyObject *\nmonitoring_register_callback_impl(PyObject *module, int tool_id, int event,\n                                  PyObject *func);\n\nstatic PyObject *\nmonitoring_register_callback(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    int tool_id;\n    int event;\n    PyObject *func;\n\n    if (!_PyArg_CheckPositional(\"register_callback\", nargs, 3, 3)) {\n        goto exit;\n    }\n    tool_id = _PyLong_AsInt(args[0]);\n    if (tool_id == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    event = _PyLong_AsInt(args[1]);\n    if (event == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    func = args[2];\n    return_value = monitoring_register_callback_impl(module, tool_id, event, func);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(monitoring_get_events__doc__,\n\"get_events($module, tool_id, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define MONITORING_GET_EVENTS_METHODDEF    \\\n    {\"get_events\", (PyCFunction)monitoring_get_events, METH_O, monitoring_get_events__doc__},\n\nstatic int\nmonitoring_get_events_impl(PyObject *module, int tool_id);\n\nstatic PyObject *\nmonitoring_get_events(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    int tool_id;\n    int _return_value;\n\n    tool_id = _PyLong_AsInt(arg);\n    if (tool_id == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    _return_value = monitoring_get_events_impl(module, tool_id);\n    if ((_return_value == -1) && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = PyLong_FromLong((long)_return_value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(monitoring_set_events__doc__,\n\"set_events($module, tool_id, event_set, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define MONITORING_SET_EVENTS_METHODDEF    \\\n    {\"set_events\", _PyCFunction_CAST(monitoring_set_events), METH_FASTCALL, monitoring_set_events__doc__},\n\nstatic PyObject *\nmonitoring_set_events_impl(PyObject *module, int tool_id, int event_set);\n\nstatic PyObject *\nmonitoring_set_events(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    int tool_id;\n    int event_set;\n\n    if (!_PyArg_CheckPositional(\"set_events\", nargs, 2, 2)) {\n        goto exit;\n    }\n    tool_id = _PyLong_AsInt(args[0]);\n    if (tool_id == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    event_set = _PyLong_AsInt(args[1]);\n    if (event_set == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = monitoring_set_events_impl(module, tool_id, event_set);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(monitoring_get_local_events__doc__,\n\"get_local_events($module, tool_id, code, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define MONITORING_GET_LOCAL_EVENTS_METHODDEF    \\\n    {\"get_local_events\", _PyCFunction_CAST(monitoring_get_local_events), METH_FASTCALL, monitoring_get_local_events__doc__},\n\nstatic int\nmonitoring_get_local_events_impl(PyObject *module, int tool_id,\n                                 PyObject *code);\n\nstatic PyObject *\nmonitoring_get_local_events(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    int tool_id;\n    PyObject *code;\n    int _return_value;\n\n    if (!_PyArg_CheckPositional(\"get_local_events\", nargs, 2, 2)) {\n        goto exit;\n    }\n    tool_id = _PyLong_AsInt(args[0]);\n    if (tool_id == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    code = args[1];\n    _return_value = monitoring_get_local_events_impl(module, tool_id, code);\n    if ((_return_value == -1) && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = PyLong_FromLong((long)_return_value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(monitoring_set_local_events__doc__,\n\"set_local_events($module, tool_id, code, event_set, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define MONITORING_SET_LOCAL_EVENTS_METHODDEF    \\\n    {\"set_local_events\", _PyCFunction_CAST(monitoring_set_local_events), METH_FASTCALL, monitoring_set_local_events__doc__},\n\nstatic PyObject *\nmonitoring_set_local_events_impl(PyObject *module, int tool_id,\n                                 PyObject *code, int event_set);\n\nstatic PyObject *\nmonitoring_set_local_events(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    int tool_id;\n    PyObject *code;\n    int event_set;\n\n    if (!_PyArg_CheckPositional(\"set_local_events\", nargs, 3, 3)) {\n        goto exit;\n    }\n    tool_id = _PyLong_AsInt(args[0]);\n    if (tool_id == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    code = args[1];\n    event_set = _PyLong_AsInt(args[2]);\n    if (event_set == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = monitoring_set_local_events_impl(module, tool_id, code, event_set);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(monitoring_restart_events__doc__,\n\"restart_events($module, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define MONITORING_RESTART_EVENTS_METHODDEF    \\\n    {\"restart_events\", (PyCFunction)monitoring_restart_events, METH_NOARGS, monitoring_restart_events__doc__},\n\nstatic PyObject *\nmonitoring_restart_events_impl(PyObject *module);\n\nstatic PyObject *\nmonitoring_restart_events(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return monitoring_restart_events_impl(module);\n}\n\nPyDoc_STRVAR(monitoring__all_events__doc__,\n\"_all_events($module, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define MONITORING__ALL_EVENTS_METHODDEF    \\\n    {\"_all_events\", (PyCFunction)monitoring__all_events, METH_NOARGS, monitoring__all_events__doc__},\n\nstatic PyObject *\nmonitoring__all_events_impl(PyObject *module);\n\nstatic PyObject *\nmonitoring__all_events(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return monitoring__all_events_impl(module);\n}\n/*[clinic end generated code: output=11cc0803875b3ffa input=a9049054013a1b77]*/\n"
  },
  {
    "path": "Clinic/marshal.c.h",
    "content": "/*[clinic input]\npreserve\n[clinic start generated code]*/\n\n#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n#  include \"pycore_gc.h\"            // PyGC_Head\n#  include \"pycore_runtime.h\"       // _Py_ID()\n#endif\n\n\nPyDoc_STRVAR(marshal_dump__doc__,\n\"dump($module, value, file, version=version, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Write the value on the open file.\\n\"\n\"\\n\"\n\"  value\\n\"\n\"    Must be a supported type.\\n\"\n\"  file\\n\"\n\"    Must be a writeable binary file.\\n\"\n\"  version\\n\"\n\"    Indicates the data format that dump should use.\\n\"\n\"\\n\"\n\"If the value has (or contains an object that has) an unsupported type, a\\n\"\n\"ValueError exception is raised - but garbage data will also be written\\n\"\n\"to the file. The object will not be properly read back by load().\");\n\n#define MARSHAL_DUMP_METHODDEF    \\\n    {\"dump\", _PyCFunction_CAST(marshal_dump), METH_FASTCALL, marshal_dump__doc__},\n\nstatic PyObject *\nmarshal_dump_impl(PyObject *module, PyObject *value, PyObject *file,\n                  int version);\n\nstatic PyObject *\nmarshal_dump(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *value;\n    PyObject *file;\n    int version = Py_MARSHAL_VERSION;\n\n    if (!_PyArg_CheckPositional(\"dump\", nargs, 2, 3)) {\n        goto exit;\n    }\n    value = args[0];\n    file = args[1];\n    if (nargs < 3) {\n        goto skip_optional;\n    }\n    version = _PyLong_AsInt(args[2]);\n    if (version == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\nskip_optional:\n    return_value = marshal_dump_impl(module, value, file, version);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(marshal_load__doc__,\n\"load($module, file, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Read one value from the open file and return it.\\n\"\n\"\\n\"\n\"  file\\n\"\n\"    Must be readable binary file.\\n\"\n\"\\n\"\n\"If no valid value is read (e.g. because the data has a different Python\\n\"\n\"version\\'s incompatible marshal format), raise EOFError, ValueError or\\n\"\n\"TypeError.\\n\"\n\"\\n\"\n\"Note: If an object containing an unsupported type was marshalled with\\n\"\n\"dump(), load() will substitute None for the unmarshallable type.\");\n\n#define MARSHAL_LOAD_METHODDEF    \\\n    {\"load\", (PyCFunction)marshal_load, METH_O, marshal_load__doc__},\n\nPyDoc_STRVAR(marshal_dumps__doc__,\n\"dumps($module, value, version=version, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the bytes object that would be written to a file by dump(value, file).\\n\"\n\"\\n\"\n\"  value\\n\"\n\"    Must be a supported type.\\n\"\n\"  version\\n\"\n\"    Indicates the data format that dumps should use.\\n\"\n\"\\n\"\n\"Raise a ValueError exception if value has (or contains an object that has) an\\n\"\n\"unsupported type.\");\n\n#define MARSHAL_DUMPS_METHODDEF    \\\n    {\"dumps\", _PyCFunction_CAST(marshal_dumps), METH_FASTCALL, marshal_dumps__doc__},\n\nstatic PyObject *\nmarshal_dumps_impl(PyObject *module, PyObject *value, int version);\n\nstatic PyObject *\nmarshal_dumps(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *value;\n    int version = Py_MARSHAL_VERSION;\n\n    if (!_PyArg_CheckPositional(\"dumps\", nargs, 1, 2)) {\n        goto exit;\n    }\n    value = args[0];\n    if (nargs < 2) {\n        goto skip_optional;\n    }\n    version = _PyLong_AsInt(args[1]);\n    if (version == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\nskip_optional:\n    return_value = marshal_dumps_impl(module, value, version);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(marshal_loads__doc__,\n\"loads($module, bytes, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Convert the bytes-like object to a value.\\n\"\n\"\\n\"\n\"If no valid value is found, raise EOFError, ValueError or TypeError.  Extra\\n\"\n\"bytes in the input are ignored.\");\n\n#define MARSHAL_LOADS_METHODDEF    \\\n    {\"loads\", (PyCFunction)marshal_loads, METH_O, marshal_loads__doc__},\n\nstatic PyObject *\nmarshal_loads_impl(PyObject *module, Py_buffer *bytes);\n\nstatic PyObject *\nmarshal_loads(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    Py_buffer bytes = {NULL, NULL};\n\n    if (PyObject_GetBuffer(arg, &bytes, PyBUF_SIMPLE) != 0) {\n        goto exit;\n    }\n    if (!PyBuffer_IsContiguous(&bytes, 'C')) {\n        _PyArg_BadArgument(\"loads\", \"argument\", \"contiguous buffer\", arg);\n        goto exit;\n    }\n    return_value = marshal_loads_impl(module, &bytes);\n\nexit:\n    /* Cleanup for bytes */\n    if (bytes.obj) {\n       PyBuffer_Release(&bytes);\n    }\n\n    return return_value;\n}\n/*[clinic end generated code: output=12082d61d2942473 input=a9049054013a1b77]*/\n"
  },
  {
    "path": "Clinic/sysmodule.c.h",
    "content": "/*[clinic input]\npreserve\n[clinic start generated code]*/\n\n#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n#  include \"pycore_gc.h\"            // PyGC_Head\n#  include \"pycore_runtime.h\"       // _Py_ID()\n#endif\n\n\nPyDoc_STRVAR(sys_addaudithook__doc__,\n\"addaudithook($module, /, hook)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Adds a new audit hook callback.\");\n\n#define SYS_ADDAUDITHOOK_METHODDEF    \\\n    {\"addaudithook\", _PyCFunction_CAST(sys_addaudithook), METH_FASTCALL|METH_KEYWORDS, sys_addaudithook__doc__},\n\nstatic PyObject *\nsys_addaudithook_impl(PyObject *module, PyObject *hook);\n\nstatic PyObject *\nsys_addaudithook(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 1\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(hook), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"hook\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"addaudithook\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[1];\n    PyObject *hook;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    hook = args[0];\n    return_value = sys_addaudithook_impl(module, hook);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys_displayhook__doc__,\n\"displayhook($module, object, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Print an object to sys.stdout and also save it in builtins._\");\n\n#define SYS_DISPLAYHOOK_METHODDEF    \\\n    {\"displayhook\", (PyCFunction)sys_displayhook, METH_O, sys_displayhook__doc__},\n\nPyDoc_STRVAR(sys_excepthook__doc__,\n\"excepthook($module, exctype, value, traceback, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Handle an exception by displaying it with a traceback on sys.stderr.\");\n\n#define SYS_EXCEPTHOOK_METHODDEF    \\\n    {\"excepthook\", _PyCFunction_CAST(sys_excepthook), METH_FASTCALL, sys_excepthook__doc__},\n\nstatic PyObject *\nsys_excepthook_impl(PyObject *module, PyObject *exctype, PyObject *value,\n                    PyObject *traceback);\n\nstatic PyObject *\nsys_excepthook(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *exctype;\n    PyObject *value;\n    PyObject *traceback;\n\n    if (!_PyArg_CheckPositional(\"excepthook\", nargs, 3, 3)) {\n        goto exit;\n    }\n    exctype = args[0];\n    value = args[1];\n    traceback = args[2];\n    return_value = sys_excepthook_impl(module, exctype, value, traceback);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys_exception__doc__,\n\"exception($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the current exception.\\n\"\n\"\\n\"\n\"Return the most recent exception caught by an except clause\\n\"\n\"in the current stack frame or in an older stack frame, or None\\n\"\n\"if no such exception exists.\");\n\n#define SYS_EXCEPTION_METHODDEF    \\\n    {\"exception\", (PyCFunction)sys_exception, METH_NOARGS, sys_exception__doc__},\n\nstatic PyObject *\nsys_exception_impl(PyObject *module);\n\nstatic PyObject *\nsys_exception(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_exception_impl(module);\n}\n\nPyDoc_STRVAR(sys_exc_info__doc__,\n\"exc_info($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return current exception information: (type, value, traceback).\\n\"\n\"\\n\"\n\"Return information about the most recent exception caught by an except\\n\"\n\"clause in the current stack frame or in an older stack frame.\");\n\n#define SYS_EXC_INFO_METHODDEF    \\\n    {\"exc_info\", (PyCFunction)sys_exc_info, METH_NOARGS, sys_exc_info__doc__},\n\nstatic PyObject *\nsys_exc_info_impl(PyObject *module);\n\nstatic PyObject *\nsys_exc_info(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_exc_info_impl(module);\n}\n\nPyDoc_STRVAR(sys_unraisablehook__doc__,\n\"unraisablehook($module, unraisable, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Handle an unraisable exception.\\n\"\n\"\\n\"\n\"The unraisable argument has the following attributes:\\n\"\n\"\\n\"\n\"* exc_type: Exception type.\\n\"\n\"* exc_value: Exception value, can be None.\\n\"\n\"* exc_traceback: Exception traceback, can be None.\\n\"\n\"* err_msg: Error message, can be None.\\n\"\n\"* object: Object causing the exception, can be None.\");\n\n#define SYS_UNRAISABLEHOOK_METHODDEF    \\\n    {\"unraisablehook\", (PyCFunction)sys_unraisablehook, METH_O, sys_unraisablehook__doc__},\n\nPyDoc_STRVAR(sys_exit__doc__,\n\"exit($module, status=None, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Exit the interpreter by raising SystemExit(status).\\n\"\n\"\\n\"\n\"If the status is omitted or None, it defaults to zero (i.e., success).\\n\"\n\"If the status is an integer, it will be used as the system exit status.\\n\"\n\"If it is another kind of object, it will be printed and the system\\n\"\n\"exit status will be one (i.e., failure).\");\n\n#define SYS_EXIT_METHODDEF    \\\n    {\"exit\", _PyCFunction_CAST(sys_exit), METH_FASTCALL, sys_exit__doc__},\n\nstatic PyObject *\nsys_exit_impl(PyObject *module, PyObject *status);\n\nstatic PyObject *\nsys_exit(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *status = Py_None;\n\n    if (!_PyArg_CheckPositional(\"exit\", nargs, 0, 1)) {\n        goto exit;\n    }\n    if (nargs < 1) {\n        goto skip_optional;\n    }\n    status = args[0];\nskip_optional:\n    return_value = sys_exit_impl(module, status);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys_getdefaultencoding__doc__,\n\"getdefaultencoding($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the current default encoding used by the Unicode implementation.\");\n\n#define SYS_GETDEFAULTENCODING_METHODDEF    \\\n    {\"getdefaultencoding\", (PyCFunction)sys_getdefaultencoding, METH_NOARGS, sys_getdefaultencoding__doc__},\n\nstatic PyObject *\nsys_getdefaultencoding_impl(PyObject *module);\n\nstatic PyObject *\nsys_getdefaultencoding(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_getdefaultencoding_impl(module);\n}\n\nPyDoc_STRVAR(sys_getfilesystemencoding__doc__,\n\"getfilesystemencoding($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the encoding used to convert Unicode filenames to OS filenames.\");\n\n#define SYS_GETFILESYSTEMENCODING_METHODDEF    \\\n    {\"getfilesystemencoding\", (PyCFunction)sys_getfilesystemencoding, METH_NOARGS, sys_getfilesystemencoding__doc__},\n\nstatic PyObject *\nsys_getfilesystemencoding_impl(PyObject *module);\n\nstatic PyObject *\nsys_getfilesystemencoding(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_getfilesystemencoding_impl(module);\n}\n\nPyDoc_STRVAR(sys_getfilesystemencodeerrors__doc__,\n\"getfilesystemencodeerrors($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the error mode used Unicode to OS filename conversion.\");\n\n#define SYS_GETFILESYSTEMENCODEERRORS_METHODDEF    \\\n    {\"getfilesystemencodeerrors\", (PyCFunction)sys_getfilesystemencodeerrors, METH_NOARGS, sys_getfilesystemencodeerrors__doc__},\n\nstatic PyObject *\nsys_getfilesystemencodeerrors_impl(PyObject *module);\n\nstatic PyObject *\nsys_getfilesystemencodeerrors(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_getfilesystemencodeerrors_impl(module);\n}\n\nPyDoc_STRVAR(sys_intern__doc__,\n\"intern($module, string, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"``Intern\\'\\' the given string.\\n\"\n\"\\n\"\n\"This enters the string in the (global) table of interned strings whose\\n\"\n\"purpose is to speed up dictionary lookups. Return the string itself or\\n\"\n\"the previously interned string object with the same value.\");\n\n#define SYS_INTERN_METHODDEF    \\\n    {\"intern\", (PyCFunction)sys_intern, METH_O, sys_intern__doc__},\n\nstatic PyObject *\nsys_intern_impl(PyObject *module, PyObject *s);\n\nstatic PyObject *\nsys_intern(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    PyObject *s;\n\n    if (!PyUnicode_Check(arg)) {\n        _PyArg_BadArgument(\"intern\", \"argument\", \"str\", arg);\n        goto exit;\n    }\n    s = arg;\n    return_value = sys_intern_impl(module, s);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys__settraceallthreads__doc__,\n\"_settraceallthreads($module, arg, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Set the global debug tracing function in all running threads belonging to the current interpreter.\\n\"\n\"\\n\"\n\"It will be called on each function call. See the debugger chapter\\n\"\n\"in the library manual.\");\n\n#define SYS__SETTRACEALLTHREADS_METHODDEF    \\\n    {\"_settraceallthreads\", (PyCFunction)sys__settraceallthreads, METH_O, sys__settraceallthreads__doc__},\n\nPyDoc_STRVAR(sys_gettrace__doc__,\n\"gettrace($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the global debug tracing function set with sys.settrace.\\n\"\n\"\\n\"\n\"See the debugger chapter in the library manual.\");\n\n#define SYS_GETTRACE_METHODDEF    \\\n    {\"gettrace\", (PyCFunction)sys_gettrace, METH_NOARGS, sys_gettrace__doc__},\n\nstatic PyObject *\nsys_gettrace_impl(PyObject *module);\n\nstatic PyObject *\nsys_gettrace(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_gettrace_impl(module);\n}\n\nPyDoc_STRVAR(sys__setprofileallthreads__doc__,\n\"_setprofileallthreads($module, arg, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Set the profiling function in all running threads belonging to the current interpreter.\\n\"\n\"\\n\"\n\"It will be called on each function call and return.  See the profiler chapter\\n\"\n\"in the library manual.\");\n\n#define SYS__SETPROFILEALLTHREADS_METHODDEF    \\\n    {\"_setprofileallthreads\", (PyCFunction)sys__setprofileallthreads, METH_O, sys__setprofileallthreads__doc__},\n\nPyDoc_STRVAR(sys_getprofile__doc__,\n\"getprofile($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the profiling function set with sys.setprofile.\\n\"\n\"\\n\"\n\"See the profiler chapter in the library manual.\");\n\n#define SYS_GETPROFILE_METHODDEF    \\\n    {\"getprofile\", (PyCFunction)sys_getprofile, METH_NOARGS, sys_getprofile__doc__},\n\nstatic PyObject *\nsys_getprofile_impl(PyObject *module);\n\nstatic PyObject *\nsys_getprofile(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_getprofile_impl(module);\n}\n\nPyDoc_STRVAR(sys_setswitchinterval__doc__,\n\"setswitchinterval($module, interval, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Set the ideal thread switching delay inside the Python interpreter.\\n\"\n\"\\n\"\n\"The actual frequency of switching threads can be lower if the\\n\"\n\"interpreter executes long sequences of uninterruptible code\\n\"\n\"(this is implementation-specific and workload-dependent).\\n\"\n\"\\n\"\n\"The parameter must represent the desired switching delay in seconds\\n\"\n\"A typical value is 0.005 (5 milliseconds).\");\n\n#define SYS_SETSWITCHINTERVAL_METHODDEF    \\\n    {\"setswitchinterval\", (PyCFunction)sys_setswitchinterval, METH_O, sys_setswitchinterval__doc__},\n\nstatic PyObject *\nsys_setswitchinterval_impl(PyObject *module, double interval);\n\nstatic PyObject *\nsys_setswitchinterval(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    double interval;\n\n    if (PyFloat_CheckExact(arg)) {\n        interval = PyFloat_AS_DOUBLE(arg);\n    }\n    else\n    {\n        interval = PyFloat_AsDouble(arg);\n        if (interval == -1.0 && PyErr_Occurred()) {\n            goto exit;\n        }\n    }\n    return_value = sys_setswitchinterval_impl(module, interval);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys_getswitchinterval__doc__,\n\"getswitchinterval($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the current thread switch interval; see sys.setswitchinterval().\");\n\n#define SYS_GETSWITCHINTERVAL_METHODDEF    \\\n    {\"getswitchinterval\", (PyCFunction)sys_getswitchinterval, METH_NOARGS, sys_getswitchinterval__doc__},\n\nstatic double\nsys_getswitchinterval_impl(PyObject *module);\n\nstatic PyObject *\nsys_getswitchinterval(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    PyObject *return_value = NULL;\n    double _return_value;\n\n    _return_value = sys_getswitchinterval_impl(module);\n    if ((_return_value == -1.0) && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = PyFloat_FromDouble(_return_value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys_setrecursionlimit__doc__,\n\"setrecursionlimit($module, limit, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Set the maximum depth of the Python interpreter stack to n.\\n\"\n\"\\n\"\n\"This limit prevents infinite recursion from causing an overflow of the C\\n\"\n\"stack and crashing Python.  The highest possible limit is platform-\\n\"\n\"dependent.\");\n\n#define SYS_SETRECURSIONLIMIT_METHODDEF    \\\n    {\"setrecursionlimit\", (PyCFunction)sys_setrecursionlimit, METH_O, sys_setrecursionlimit__doc__},\n\nstatic PyObject *\nsys_setrecursionlimit_impl(PyObject *module, int new_limit);\n\nstatic PyObject *\nsys_setrecursionlimit(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    int new_limit;\n\n    new_limit = _PyLong_AsInt(arg);\n    if (new_limit == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = sys_setrecursionlimit_impl(module, new_limit);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys_set_coroutine_origin_tracking_depth__doc__,\n\"set_coroutine_origin_tracking_depth($module, /, depth)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Enable or disable origin tracking for coroutine objects in this thread.\\n\"\n\"\\n\"\n\"Coroutine objects will track \\'depth\\' frames of traceback information\\n\"\n\"about where they came from, available in their cr_origin attribute.\\n\"\n\"\\n\"\n\"Set a depth of 0 to disable.\");\n\n#define SYS_SET_COROUTINE_ORIGIN_TRACKING_DEPTH_METHODDEF    \\\n    {\"set_coroutine_origin_tracking_depth\", _PyCFunction_CAST(sys_set_coroutine_origin_tracking_depth), METH_FASTCALL|METH_KEYWORDS, sys_set_coroutine_origin_tracking_depth__doc__},\n\nstatic PyObject *\nsys_set_coroutine_origin_tracking_depth_impl(PyObject *module, int depth);\n\nstatic PyObject *\nsys_set_coroutine_origin_tracking_depth(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 1\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(depth), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"depth\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"set_coroutine_origin_tracking_depth\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[1];\n    int depth;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    depth = _PyLong_AsInt(args[0]);\n    if (depth == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = sys_set_coroutine_origin_tracking_depth_impl(module, depth);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys_get_coroutine_origin_tracking_depth__doc__,\n\"get_coroutine_origin_tracking_depth($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Check status of origin tracking for coroutine objects in this thread.\");\n\n#define SYS_GET_COROUTINE_ORIGIN_TRACKING_DEPTH_METHODDEF    \\\n    {\"get_coroutine_origin_tracking_depth\", (PyCFunction)sys_get_coroutine_origin_tracking_depth, METH_NOARGS, sys_get_coroutine_origin_tracking_depth__doc__},\n\nstatic int\nsys_get_coroutine_origin_tracking_depth_impl(PyObject *module);\n\nstatic PyObject *\nsys_get_coroutine_origin_tracking_depth(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    PyObject *return_value = NULL;\n    int _return_value;\n\n    _return_value = sys_get_coroutine_origin_tracking_depth_impl(module);\n    if ((_return_value == -1) && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = PyLong_FromLong((long)_return_value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys_get_asyncgen_hooks__doc__,\n\"get_asyncgen_hooks($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the installed asynchronous generators hooks.\\n\"\n\"\\n\"\n\"This returns a namedtuple of the form (firstiter, finalizer).\");\n\n#define SYS_GET_ASYNCGEN_HOOKS_METHODDEF    \\\n    {\"get_asyncgen_hooks\", (PyCFunction)sys_get_asyncgen_hooks, METH_NOARGS, sys_get_asyncgen_hooks__doc__},\n\nstatic PyObject *\nsys_get_asyncgen_hooks_impl(PyObject *module);\n\nstatic PyObject *\nsys_get_asyncgen_hooks(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_get_asyncgen_hooks_impl(module);\n}\n\nPyDoc_STRVAR(sys_getrecursionlimit__doc__,\n\"getrecursionlimit($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the current value of the recursion limit.\\n\"\n\"\\n\"\n\"The recursion limit is the maximum depth of the Python interpreter\\n\"\n\"stack.  This limit prevents infinite recursion from causing an overflow\\n\"\n\"of the C stack and crashing Python.\");\n\n#define SYS_GETRECURSIONLIMIT_METHODDEF    \\\n    {\"getrecursionlimit\", (PyCFunction)sys_getrecursionlimit, METH_NOARGS, sys_getrecursionlimit__doc__},\n\nstatic PyObject *\nsys_getrecursionlimit_impl(PyObject *module);\n\nstatic PyObject *\nsys_getrecursionlimit(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_getrecursionlimit_impl(module);\n}\n\n#if defined(MS_WINDOWS)\n\nPyDoc_STRVAR(sys_getwindowsversion__doc__,\n\"getwindowsversion($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return info about the running version of Windows as a named tuple.\\n\"\n\"\\n\"\n\"The members are named: major, minor, build, platform, service_pack,\\n\"\n\"service_pack_major, service_pack_minor, suite_mask, product_type and\\n\"\n\"platform_version. For backward compatibility, only the first 5 items\\n\"\n\"are available by indexing. All elements are numbers, except\\n\"\n\"service_pack and platform_type which are strings, and platform_version\\n\"\n\"which is a 3-tuple. Platform is always 2. Product_type may be 1 for a\\n\"\n\"workstation, 2 for a domain controller, 3 for a server.\\n\"\n\"Platform_version is a 3-tuple containing a version number that is\\n\"\n\"intended for identifying the OS rather than feature detection.\");\n\n#define SYS_GETWINDOWSVERSION_METHODDEF    \\\n    {\"getwindowsversion\", (PyCFunction)sys_getwindowsversion, METH_NOARGS, sys_getwindowsversion__doc__},\n\nstatic PyObject *\nsys_getwindowsversion_impl(PyObject *module);\n\nstatic PyObject *\nsys_getwindowsversion(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_getwindowsversion_impl(module);\n}\n\n#endif /* defined(MS_WINDOWS) */\n\n#if defined(MS_WINDOWS)\n\nPyDoc_STRVAR(sys__enablelegacywindowsfsencoding__doc__,\n\"_enablelegacywindowsfsencoding($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Changes the default filesystem encoding to mbcs:replace.\\n\"\n\"\\n\"\n\"This is done for consistency with earlier versions of Python. See PEP\\n\"\n\"529 for more information.\\n\"\n\"\\n\"\n\"This is equivalent to defining the PYTHONLEGACYWINDOWSFSENCODING\\n\"\n\"environment variable before launching Python.\");\n\n#define SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF    \\\n    {\"_enablelegacywindowsfsencoding\", (PyCFunction)sys__enablelegacywindowsfsencoding, METH_NOARGS, sys__enablelegacywindowsfsencoding__doc__},\n\nstatic PyObject *\nsys__enablelegacywindowsfsencoding_impl(PyObject *module);\n\nstatic PyObject *\nsys__enablelegacywindowsfsencoding(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys__enablelegacywindowsfsencoding_impl(module);\n}\n\n#endif /* defined(MS_WINDOWS) */\n\n#if defined(HAVE_DLOPEN)\n\nPyDoc_STRVAR(sys_setdlopenflags__doc__,\n\"setdlopenflags($module, flags, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Set the flags used by the interpreter for dlopen calls.\\n\"\n\"\\n\"\n\"This is used, for example, when the interpreter loads extension\\n\"\n\"modules. Among other things, this will enable a lazy resolving of\\n\"\n\"symbols when importing a module, if called as sys.setdlopenflags(0).\\n\"\n\"To share symbols across extension modules, call as\\n\"\n\"sys.setdlopenflags(os.RTLD_GLOBAL).  Symbolic names for the flag\\n\"\n\"modules can be found in the os module (RTLD_xxx constants, e.g.\\n\"\n\"os.RTLD_LAZY).\");\n\n#define SYS_SETDLOPENFLAGS_METHODDEF    \\\n    {\"setdlopenflags\", (PyCFunction)sys_setdlopenflags, METH_O, sys_setdlopenflags__doc__},\n\nstatic PyObject *\nsys_setdlopenflags_impl(PyObject *module, int new_val);\n\nstatic PyObject *\nsys_setdlopenflags(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    int new_val;\n\n    new_val = _PyLong_AsInt(arg);\n    if (new_val == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = sys_setdlopenflags_impl(module, new_val);\n\nexit:\n    return return_value;\n}\n\n#endif /* defined(HAVE_DLOPEN) */\n\n#if defined(HAVE_DLOPEN)\n\nPyDoc_STRVAR(sys_getdlopenflags__doc__,\n\"getdlopenflags($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the current value of the flags that are used for dlopen calls.\\n\"\n\"\\n\"\n\"The flag constants are defined in the os module.\");\n\n#define SYS_GETDLOPENFLAGS_METHODDEF    \\\n    {\"getdlopenflags\", (PyCFunction)sys_getdlopenflags, METH_NOARGS, sys_getdlopenflags__doc__},\n\nstatic PyObject *\nsys_getdlopenflags_impl(PyObject *module);\n\nstatic PyObject *\nsys_getdlopenflags(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_getdlopenflags_impl(module);\n}\n\n#endif /* defined(HAVE_DLOPEN) */\n\n#if defined(USE_MALLOPT)\n\nPyDoc_STRVAR(sys_mdebug__doc__,\n\"mdebug($module, flag, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define SYS_MDEBUG_METHODDEF    \\\n    {\"mdebug\", (PyCFunction)sys_mdebug, METH_O, sys_mdebug__doc__},\n\nstatic PyObject *\nsys_mdebug_impl(PyObject *module, int flag);\n\nstatic PyObject *\nsys_mdebug(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    int flag;\n\n    flag = _PyLong_AsInt(arg);\n    if (flag == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = sys_mdebug_impl(module, flag);\n\nexit:\n    return return_value;\n}\n\n#endif /* defined(USE_MALLOPT) */\n\nPyDoc_STRVAR(sys_get_int_max_str_digits__doc__,\n\"get_int_max_str_digits($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the maximum string digits limit for non-binary int<->str conversions.\");\n\n#define SYS_GET_INT_MAX_STR_DIGITS_METHODDEF    \\\n    {\"get_int_max_str_digits\", (PyCFunction)sys_get_int_max_str_digits, METH_NOARGS, sys_get_int_max_str_digits__doc__},\n\nstatic PyObject *\nsys_get_int_max_str_digits_impl(PyObject *module);\n\nstatic PyObject *\nsys_get_int_max_str_digits(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_get_int_max_str_digits_impl(module);\n}\n\nPyDoc_STRVAR(sys_set_int_max_str_digits__doc__,\n\"set_int_max_str_digits($module, /, maxdigits)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Set the maximum string digits limit for non-binary int<->str conversions.\");\n\n#define SYS_SET_INT_MAX_STR_DIGITS_METHODDEF    \\\n    {\"set_int_max_str_digits\", _PyCFunction_CAST(sys_set_int_max_str_digits), METH_FASTCALL|METH_KEYWORDS, sys_set_int_max_str_digits__doc__},\n\nstatic PyObject *\nsys_set_int_max_str_digits_impl(PyObject *module, int maxdigits);\n\nstatic PyObject *\nsys_set_int_max_str_digits(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 1\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(maxdigits), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"maxdigits\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"set_int_max_str_digits\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[1];\n    int maxdigits;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    maxdigits = _PyLong_AsInt(args[0]);\n    if (maxdigits == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = sys_set_int_max_str_digits_impl(module, maxdigits);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys_getrefcount__doc__,\n\"getrefcount($module, object, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the reference count of object.\\n\"\n\"\\n\"\n\"The count returned is generally one higher than you might expect,\\n\"\n\"because it includes the (temporary) reference as an argument to\\n\"\n\"getrefcount().\");\n\n#define SYS_GETREFCOUNT_METHODDEF    \\\n    {\"getrefcount\", (PyCFunction)sys_getrefcount, METH_O, sys_getrefcount__doc__},\n\nstatic Py_ssize_t\nsys_getrefcount_impl(PyObject *module, PyObject *object);\n\nstatic PyObject *\nsys_getrefcount(PyObject *module, PyObject *object)\n{\n    PyObject *return_value = NULL;\n    Py_ssize_t _return_value;\n\n    _return_value = sys_getrefcount_impl(module, object);\n    if ((_return_value == -1) && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = PyLong_FromSsize_t(_return_value);\n\nexit:\n    return return_value;\n}\n\n#if defined(Py_REF_DEBUG)\n\nPyDoc_STRVAR(sys_gettotalrefcount__doc__,\n\"gettotalrefcount($module, /)\\n\"\n\"--\\n\"\n\"\\n\");\n\n#define SYS_GETTOTALREFCOUNT_METHODDEF    \\\n    {\"gettotalrefcount\", (PyCFunction)sys_gettotalrefcount, METH_NOARGS, sys_gettotalrefcount__doc__},\n\nstatic Py_ssize_t\nsys_gettotalrefcount_impl(PyObject *module);\n\nstatic PyObject *\nsys_gettotalrefcount(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    PyObject *return_value = NULL;\n    Py_ssize_t _return_value;\n\n    _return_value = sys_gettotalrefcount_impl(module);\n    if ((_return_value == -1) && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = PyLong_FromSsize_t(_return_value);\n\nexit:\n    return return_value;\n}\n\n#endif /* defined(Py_REF_DEBUG) */\n\nPyDoc_STRVAR(sys_getallocatedblocks__doc__,\n\"getallocatedblocks($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the number of memory blocks currently allocated.\");\n\n#define SYS_GETALLOCATEDBLOCKS_METHODDEF    \\\n    {\"getallocatedblocks\", (PyCFunction)sys_getallocatedblocks, METH_NOARGS, sys_getallocatedblocks__doc__},\n\nstatic Py_ssize_t\nsys_getallocatedblocks_impl(PyObject *module);\n\nstatic PyObject *\nsys_getallocatedblocks(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    PyObject *return_value = NULL;\n    Py_ssize_t _return_value;\n\n    _return_value = sys_getallocatedblocks_impl(module);\n    if ((_return_value == -1) && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = PyLong_FromSsize_t(_return_value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys_getunicodeinternedsize__doc__,\n\"getunicodeinternedsize($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the number of elements of the unicode interned dictionary\");\n\n#define SYS_GETUNICODEINTERNEDSIZE_METHODDEF    \\\n    {\"getunicodeinternedsize\", (PyCFunction)sys_getunicodeinternedsize, METH_NOARGS, sys_getunicodeinternedsize__doc__},\n\nstatic Py_ssize_t\nsys_getunicodeinternedsize_impl(PyObject *module);\n\nstatic PyObject *\nsys_getunicodeinternedsize(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    PyObject *return_value = NULL;\n    Py_ssize_t _return_value;\n\n    _return_value = sys_getunicodeinternedsize_impl(module);\n    if ((_return_value == -1) && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = PyLong_FromSsize_t(_return_value);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys__getframe__doc__,\n\"_getframe($module, depth=0, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return a frame object from the call stack.\\n\"\n\"\\n\"\n\"If optional integer depth is given, return the frame object that many\\n\"\n\"calls below the top of the stack.  If that is deeper than the call\\n\"\n\"stack, ValueError is raised.  The default for depth is zero, returning\\n\"\n\"the frame at the top of the call stack.\\n\"\n\"\\n\"\n\"This function should be used for internal and specialized purposes\\n\"\n\"only.\");\n\n#define SYS__GETFRAME_METHODDEF    \\\n    {\"_getframe\", _PyCFunction_CAST(sys__getframe), METH_FASTCALL, sys__getframe__doc__},\n\nstatic PyObject *\nsys__getframe_impl(PyObject *module, int depth);\n\nstatic PyObject *\nsys__getframe(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    int depth = 0;\n\n    if (!_PyArg_CheckPositional(\"_getframe\", nargs, 0, 1)) {\n        goto exit;\n    }\n    if (nargs < 1) {\n        goto skip_optional;\n    }\n    depth = _PyLong_AsInt(args[0]);\n    if (depth == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\nskip_optional:\n    return_value = sys__getframe_impl(module, depth);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys__current_frames__doc__,\n\"_current_frames($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return a dict mapping each thread\\'s thread id to its current stack frame.\\n\"\n\"\\n\"\n\"This function should be used for specialized purposes only.\");\n\n#define SYS__CURRENT_FRAMES_METHODDEF    \\\n    {\"_current_frames\", (PyCFunction)sys__current_frames, METH_NOARGS, sys__current_frames__doc__},\n\nstatic PyObject *\nsys__current_frames_impl(PyObject *module);\n\nstatic PyObject *\nsys__current_frames(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys__current_frames_impl(module);\n}\n\nPyDoc_STRVAR(sys__current_exceptions__doc__,\n\"_current_exceptions($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return a dict mapping each thread\\'s identifier to its current raised exception.\\n\"\n\"\\n\"\n\"This function should be used for specialized purposes only.\");\n\n#define SYS__CURRENT_EXCEPTIONS_METHODDEF    \\\n    {\"_current_exceptions\", (PyCFunction)sys__current_exceptions, METH_NOARGS, sys__current_exceptions__doc__},\n\nstatic PyObject *\nsys__current_exceptions_impl(PyObject *module);\n\nstatic PyObject *\nsys__current_exceptions(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys__current_exceptions_impl(module);\n}\n\nPyDoc_STRVAR(sys_call_tracing__doc__,\n\"call_tracing($module, func, args, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Call func(*args), while tracing is enabled.\\n\"\n\"\\n\"\n\"The tracing state is saved, and restored afterwards.  This is intended\\n\"\n\"to be called from a debugger from a checkpoint, to recursively debug\\n\"\n\"some other code.\");\n\n#define SYS_CALL_TRACING_METHODDEF    \\\n    {\"call_tracing\", _PyCFunction_CAST(sys_call_tracing), METH_FASTCALL, sys_call_tracing__doc__},\n\nstatic PyObject *\nsys_call_tracing_impl(PyObject *module, PyObject *func, PyObject *funcargs);\n\nstatic PyObject *\nsys_call_tracing(PyObject *module, PyObject *const *args, Py_ssize_t nargs)\n{\n    PyObject *return_value = NULL;\n    PyObject *func;\n    PyObject *funcargs;\n\n    if (!_PyArg_CheckPositional(\"call_tracing\", nargs, 2, 2)) {\n        goto exit;\n    }\n    func = args[0];\n    if (!PyTuple_Check(args[1])) {\n        _PyArg_BadArgument(\"call_tracing\", \"argument 2\", \"tuple\", args[1]);\n        goto exit;\n    }\n    funcargs = args[1];\n    return_value = sys_call_tracing_impl(module, func, funcargs);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys__debugmallocstats__doc__,\n\"_debugmallocstats($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Print summary info to stderr about the state of pymalloc\\'s structures.\\n\"\n\"\\n\"\n\"In Py_DEBUG mode, also perform some expensive internal consistency\\n\"\n\"checks.\");\n\n#define SYS__DEBUGMALLOCSTATS_METHODDEF    \\\n    {\"_debugmallocstats\", (PyCFunction)sys__debugmallocstats, METH_NOARGS, sys__debugmallocstats__doc__},\n\nstatic PyObject *\nsys__debugmallocstats_impl(PyObject *module);\n\nstatic PyObject *\nsys__debugmallocstats(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys__debugmallocstats_impl(module);\n}\n\nPyDoc_STRVAR(sys__clear_type_cache__doc__,\n\"_clear_type_cache($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Clear the internal type lookup cache.\");\n\n#define SYS__CLEAR_TYPE_CACHE_METHODDEF    \\\n    {\"_clear_type_cache\", (PyCFunction)sys__clear_type_cache, METH_NOARGS, sys__clear_type_cache__doc__},\n\nstatic PyObject *\nsys__clear_type_cache_impl(PyObject *module);\n\nstatic PyObject *\nsys__clear_type_cache(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys__clear_type_cache_impl(module);\n}\n\nPyDoc_STRVAR(sys_is_finalizing__doc__,\n\"is_finalizing($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return True if Python is exiting.\");\n\n#define SYS_IS_FINALIZING_METHODDEF    \\\n    {\"is_finalizing\", (PyCFunction)sys_is_finalizing, METH_NOARGS, sys_is_finalizing__doc__},\n\nstatic PyObject *\nsys_is_finalizing_impl(PyObject *module);\n\nstatic PyObject *\nsys_is_finalizing(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_is_finalizing_impl(module);\n}\n\n#if defined(Py_STATS)\n\nPyDoc_STRVAR(sys__stats_on__doc__,\n\"_stats_on($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Turns on stats gathering (stats gathering is on by default).\");\n\n#define SYS__STATS_ON_METHODDEF    \\\n    {\"_stats_on\", (PyCFunction)sys__stats_on, METH_NOARGS, sys__stats_on__doc__},\n\nstatic PyObject *\nsys__stats_on_impl(PyObject *module);\n\nstatic PyObject *\nsys__stats_on(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys__stats_on_impl(module);\n}\n\n#endif /* defined(Py_STATS) */\n\n#if defined(Py_STATS)\n\nPyDoc_STRVAR(sys__stats_off__doc__,\n\"_stats_off($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Turns off stats gathering (stats gathering is on by default).\");\n\n#define SYS__STATS_OFF_METHODDEF    \\\n    {\"_stats_off\", (PyCFunction)sys__stats_off, METH_NOARGS, sys__stats_off__doc__},\n\nstatic PyObject *\nsys__stats_off_impl(PyObject *module);\n\nstatic PyObject *\nsys__stats_off(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys__stats_off_impl(module);\n}\n\n#endif /* defined(Py_STATS) */\n\n#if defined(Py_STATS)\n\nPyDoc_STRVAR(sys__stats_clear__doc__,\n\"_stats_clear($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Clears the stats.\");\n\n#define SYS__STATS_CLEAR_METHODDEF    \\\n    {\"_stats_clear\", (PyCFunction)sys__stats_clear, METH_NOARGS, sys__stats_clear__doc__},\n\nstatic PyObject *\nsys__stats_clear_impl(PyObject *module);\n\nstatic PyObject *\nsys__stats_clear(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys__stats_clear_impl(module);\n}\n\n#endif /* defined(Py_STATS) */\n\n#if defined(Py_STATS)\n\nPyDoc_STRVAR(sys__stats_dump__doc__,\n\"_stats_dump($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Dump stats to file, and clears the stats.\");\n\n#define SYS__STATS_DUMP_METHODDEF    \\\n    {\"_stats_dump\", (PyCFunction)sys__stats_dump, METH_NOARGS, sys__stats_dump__doc__},\n\nstatic PyObject *\nsys__stats_dump_impl(PyObject *module);\n\nstatic PyObject *\nsys__stats_dump(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys__stats_dump_impl(module);\n}\n\n#endif /* defined(Py_STATS) */\n\n#if defined(ANDROID_API_LEVEL)\n\nPyDoc_STRVAR(sys_getandroidapilevel__doc__,\n\"getandroidapilevel($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the build time API version of Android as an integer.\");\n\n#define SYS_GETANDROIDAPILEVEL_METHODDEF    \\\n    {\"getandroidapilevel\", (PyCFunction)sys_getandroidapilevel, METH_NOARGS, sys_getandroidapilevel__doc__},\n\nstatic PyObject *\nsys_getandroidapilevel_impl(PyObject *module);\n\nstatic PyObject *\nsys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_getandroidapilevel_impl(module);\n}\n\n#endif /* defined(ANDROID_API_LEVEL) */\n\nPyDoc_STRVAR(sys_activate_stack_trampoline__doc__,\n\"activate_stack_trampoline($module, backend, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Activate stack profiler trampoline *backend*.\");\n\n#define SYS_ACTIVATE_STACK_TRAMPOLINE_METHODDEF    \\\n    {\"activate_stack_trampoline\", (PyCFunction)sys_activate_stack_trampoline, METH_O, sys_activate_stack_trampoline__doc__},\n\nstatic PyObject *\nsys_activate_stack_trampoline_impl(PyObject *module, const char *backend);\n\nstatic PyObject *\nsys_activate_stack_trampoline(PyObject *module, PyObject *arg)\n{\n    PyObject *return_value = NULL;\n    const char *backend;\n\n    if (!PyUnicode_Check(arg)) {\n        _PyArg_BadArgument(\"activate_stack_trampoline\", \"argument\", \"str\", arg);\n        goto exit;\n    }\n    Py_ssize_t backend_length;\n    backend = PyUnicode_AsUTF8AndSize(arg, &backend_length);\n    if (backend == NULL) {\n        goto exit;\n    }\n    if (strlen(backend) != (size_t)backend_length) {\n        PyErr_SetString(PyExc_ValueError, \"embedded null character\");\n        goto exit;\n    }\n    return_value = sys_activate_stack_trampoline_impl(module, backend);\n\nexit:\n    return return_value;\n}\n\nPyDoc_STRVAR(sys_deactivate_stack_trampoline__doc__,\n\"deactivate_stack_trampoline($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Deactivate the current stack profiler trampoline backend.\\n\"\n\"\\n\"\n\"If no stack profiler is activated, this function has no effect.\");\n\n#define SYS_DEACTIVATE_STACK_TRAMPOLINE_METHODDEF    \\\n    {\"deactivate_stack_trampoline\", (PyCFunction)sys_deactivate_stack_trampoline, METH_NOARGS, sys_deactivate_stack_trampoline__doc__},\n\nstatic PyObject *\nsys_deactivate_stack_trampoline_impl(PyObject *module);\n\nstatic PyObject *\nsys_deactivate_stack_trampoline(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_deactivate_stack_trampoline_impl(module);\n}\n\nPyDoc_STRVAR(sys_is_stack_trampoline_active__doc__,\n\"is_stack_trampoline_active($module, /)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return *True* if a stack profiler trampoline is active.\");\n\n#define SYS_IS_STACK_TRAMPOLINE_ACTIVE_METHODDEF    \\\n    {\"is_stack_trampoline_active\", (PyCFunction)sys_is_stack_trampoline_active, METH_NOARGS, sys_is_stack_trampoline_active__doc__},\n\nstatic PyObject *\nsys_is_stack_trampoline_active_impl(PyObject *module);\n\nstatic PyObject *\nsys_is_stack_trampoline_active(PyObject *module, PyObject *Py_UNUSED(ignored))\n{\n    return sys_is_stack_trampoline_active_impl(module);\n}\n\nPyDoc_STRVAR(sys__getframemodulename__doc__,\n\"_getframemodulename($module, /, depth=0)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Return the name of the module for a calling frame.\\n\"\n\"\\n\"\n\"The default depth returns the module containing the call to this API.\\n\"\n\"A more typical use in a library will pass a depth of 1 to get the user\\'s\\n\"\n\"module rather than the library module.\\n\"\n\"\\n\"\n\"If no frame, module, or name can be found, returns None.\");\n\n#define SYS__GETFRAMEMODULENAME_METHODDEF    \\\n    {\"_getframemodulename\", _PyCFunction_CAST(sys__getframemodulename), METH_FASTCALL|METH_KEYWORDS, sys__getframemodulename__doc__},\n\nstatic PyObject *\nsys__getframemodulename_impl(PyObject *module, int depth);\n\nstatic PyObject *\nsys__getframemodulename(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 1\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(depth), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"depth\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"_getframemodulename\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[1];\n    Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;\n    int depth = 0;\n\n    args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);\n    if (!args) {\n        goto exit;\n    }\n    if (!noptargs) {\n        goto skip_optional_pos;\n    }\n    depth = _PyLong_AsInt(args[0]);\n    if (depth == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\nskip_optional_pos:\n    return_value = sys__getframemodulename_impl(module, depth);\n\nexit:\n    return return_value;\n}\n\n#ifndef SYS_GETWINDOWSVERSION_METHODDEF\n    #define SYS_GETWINDOWSVERSION_METHODDEF\n#endif /* !defined(SYS_GETWINDOWSVERSION_METHODDEF) */\n\n#ifndef SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF\n    #define SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF\n#endif /* !defined(SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF) */\n\n#ifndef SYS_SETDLOPENFLAGS_METHODDEF\n    #define SYS_SETDLOPENFLAGS_METHODDEF\n#endif /* !defined(SYS_SETDLOPENFLAGS_METHODDEF) */\n\n#ifndef SYS_GETDLOPENFLAGS_METHODDEF\n    #define SYS_GETDLOPENFLAGS_METHODDEF\n#endif /* !defined(SYS_GETDLOPENFLAGS_METHODDEF) */\n\n#ifndef SYS_MDEBUG_METHODDEF\n    #define SYS_MDEBUG_METHODDEF\n#endif /* !defined(SYS_MDEBUG_METHODDEF) */\n\n#ifndef SYS_GETTOTALREFCOUNT_METHODDEF\n    #define SYS_GETTOTALREFCOUNT_METHODDEF\n#endif /* !defined(SYS_GETTOTALREFCOUNT_METHODDEF) */\n\n#ifndef SYS__STATS_ON_METHODDEF\n    #define SYS__STATS_ON_METHODDEF\n#endif /* !defined(SYS__STATS_ON_METHODDEF) */\n\n#ifndef SYS__STATS_OFF_METHODDEF\n    #define SYS__STATS_OFF_METHODDEF\n#endif /* !defined(SYS__STATS_OFF_METHODDEF) */\n\n#ifndef SYS__STATS_CLEAR_METHODDEF\n    #define SYS__STATS_CLEAR_METHODDEF\n#endif /* !defined(SYS__STATS_CLEAR_METHODDEF) */\n\n#ifndef SYS__STATS_DUMP_METHODDEF\n    #define SYS__STATS_DUMP_METHODDEF\n#endif /* !defined(SYS__STATS_DUMP_METHODDEF) */\n\n#ifndef SYS_GETANDROIDAPILEVEL_METHODDEF\n    #define SYS_GETANDROIDAPILEVEL_METHODDEF\n#endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */\n/*[clinic end generated code: output=41937e0843c68009 input=a9049054013a1b77]*/\n"
  },
  {
    "path": "Clinic/traceback.c.h",
    "content": "/*[clinic input]\npreserve\n[clinic start generated code]*/\n\n#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n#  include \"pycore_gc.h\"            // PyGC_Head\n#  include \"pycore_runtime.h\"       // _Py_ID()\n#endif\n\n\nPyDoc_STRVAR(tb_new__doc__,\n\"TracebackType(tb_next, tb_frame, tb_lasti, tb_lineno)\\n\"\n\"--\\n\"\n\"\\n\"\n\"Create a new traceback object.\");\n\nstatic PyObject *\ntb_new_impl(PyTypeObject *type, PyObject *tb_next, PyFrameObject *tb_frame,\n            int tb_lasti, int tb_lineno);\n\nstatic PyObject *\ntb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)\n{\n    PyObject *return_value = NULL;\n    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)\n\n    #define NUM_KEYWORDS 4\n    static struct {\n        PyGC_Head _this_is_not_used;\n        PyObject_VAR_HEAD\n        PyObject *ob_item[NUM_KEYWORDS];\n    } _kwtuple = {\n        .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)\n        .ob_item = { &_Py_ID(tb_next), &_Py_ID(tb_frame), &_Py_ID(tb_lasti), &_Py_ID(tb_lineno), },\n    };\n    #undef NUM_KEYWORDS\n    #define KWTUPLE (&_kwtuple.ob_base.ob_base)\n\n    #else  // !Py_BUILD_CORE\n    #  define KWTUPLE NULL\n    #endif  // !Py_BUILD_CORE\n\n    static const char * const _keywords[] = {\"tb_next\", \"tb_frame\", \"tb_lasti\", \"tb_lineno\", NULL};\n    static _PyArg_Parser _parser = {\n        .keywords = _keywords,\n        .fname = \"TracebackType\",\n        .kwtuple = KWTUPLE,\n    };\n    #undef KWTUPLE\n    PyObject *argsbuf[4];\n    PyObject * const *fastargs;\n    Py_ssize_t nargs = PyTuple_GET_SIZE(args);\n    PyObject *tb_next;\n    PyFrameObject *tb_frame;\n    int tb_lasti;\n    int tb_lineno;\n\n    fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 4, 4, 0, argsbuf);\n    if (!fastargs) {\n        goto exit;\n    }\n    tb_next = fastargs[0];\n    if (!PyObject_TypeCheck(fastargs[1], &PyFrame_Type)) {\n        _PyArg_BadArgument(\"TracebackType\", \"argument 'tb_frame'\", (&PyFrame_Type)->tp_name, fastargs[1]);\n        goto exit;\n    }\n    tb_frame = (PyFrameObject *)fastargs[1];\n    tb_lasti = _PyLong_AsInt(fastargs[2]);\n    if (tb_lasti == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    tb_lineno = _PyLong_AsInt(fastargs[3]);\n    if (tb_lineno == -1 && PyErr_Occurred()) {\n        goto exit;\n    }\n    return_value = tb_new_impl(type, tb_next, tb_frame, tb_lasti, tb_lineno);\n\nexit:\n    return return_value;\n}\n/*[clinic end generated code: output=7bc9927e362fdfb7 input=a9049054013a1b77]*/\n"
  },
  {
    "path": "CodeCS.c",
    "content": "\n#include \"Python.h\"\n#include \"pycore_call.h\"          // _PyObject_CallNoArgs()\n#include \"pycore_interp.h\"        // PyInterpreterState.codec_search_path\n#include \"pycore_pyerrors.h\"       // _PyErr_FormatNote()\n#include \"pycore_pystate.h\"       // _PyInterpreterState_GET()\n#include \"pycore_ucnhash.h\"       // _PyUnicode_Name_CAPI\n#include <ctype.h>\n\nconst char *Py_hexdigits = \"0123456789abcdef\";\n\n/* --- Codec Registry ----------------------------------------------------- */\n\n/* Import the standard encodings package which will register the first\n   codec search function.\n\n   This is done in a lazy way so that the Unicode implementation does\n   not downgrade startup time of scripts not needing it.\n\n   ImportErrors are silently ignored by this function. Only one try is\n   made.\n\n*/\n\nstatic int _PyCodecRegistry_Init(void); /* Forward */\n\nint PyCodec_Register(PyObject *search_function)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())\n        goto onError;\n    if (search_function == NULL) {\n        PyErr_BadArgument();\n        goto onError;\n    }\n    if (!PyCallable_Check(search_function)) {\n        PyErr_SetString(PyExc_TypeError, \"argument must be callable\");\n        goto onError;\n    }\n    return PyList_Append(interp->codec_search_path, search_function);\n\n onError:\n    return -1;\n}\n\nint\nPyCodec_Unregister(PyObject *search_function)\n{\n    PyInterpreterState *interp = PyInterpreterState_Get();\n    PyObject *codec_search_path = interp->codec_search_path;\n    /* Do nothing if codec_search_path is not created yet or was cleared. */\n    if (codec_search_path == NULL) {\n        return 0;\n    }\n\n    assert(PyList_CheckExact(codec_search_path));\n    Py_ssize_t n = PyList_GET_SIZE(codec_search_path);\n    for (Py_ssize_t i = 0; i < n; i++) {\n        PyObject *item = PyList_GET_ITEM(codec_search_path, i);\n        if (item == search_function) {\n            if (interp->codec_search_cache != NULL) {\n                assert(PyDict_CheckExact(interp->codec_search_cache));\n                PyDict_Clear(interp->codec_search_cache);\n            }\n            return PyList_SetSlice(codec_search_path, i, i+1, NULL);\n        }\n    }\n    return 0;\n}\n\nextern int _Py_normalize_encoding(const char *, char *, size_t);\n\n/* Convert a string to a normalized Python string(decoded from UTF-8): all characters are\n   converted to lower case, spaces and hyphens are replaced with underscores. */\n\nstatic\nPyObject *normalizestring(const char *string)\n{\n    size_t len = strlen(string);\n    char *encoding;\n    PyObject *v;\n\n    if (len > PY_SSIZE_T_MAX) {\n        PyErr_SetString(PyExc_OverflowError, \"string is too large\");\n        return NULL;\n    }\n\n    encoding = PyMem_Malloc(len + 1);\n    if (encoding == NULL)\n        return PyErr_NoMemory();\n\n    if (!_Py_normalize_encoding(string, encoding, len + 1))\n    {\n        PyErr_SetString(PyExc_RuntimeError, \"_Py_normalize_encoding() failed\");\n        PyMem_Free(encoding);\n        return NULL;\n    }\n\n    v = PyUnicode_FromString(encoding);\n    PyMem_Free(encoding);\n    return v;\n}\n\n/* Lookup the given encoding and return a tuple providing the codec\n   facilities.\n\n   The encoding string is looked up converted to all lower-case\n   characters. This makes encodings looked up through this mechanism\n   effectively case-insensitive.\n\n   If no codec is found, a LookupError is set and NULL returned.\n\n   As side effect, this tries to load the encodings package, if not\n   yet done. This is part of the lazy load strategy for the encodings\n   package.\n\n*/\n\nPyObject *_PyCodec_Lookup(const char *encoding)\n{\n    if (encoding == NULL) {\n        PyErr_BadArgument();\n        return NULL;\n    }\n\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) {\n        return NULL;\n    }\n\n    /* Convert the encoding to a normalized Python string: all\n       characters are converted to lower case, spaces and hyphens are\n       replaced with underscores. */\n    PyObject *v = normalizestring(encoding);\n    if (v == NULL) {\n        return NULL;\n    }\n    PyUnicode_InternInPlace(&v);\n\n    /* First, try to lookup the name in the registry dictionary */\n    PyObject *result = PyDict_GetItemWithError(interp->codec_search_cache, v);\n    if (result != NULL) {\n        Py_INCREF(result);\n        Py_DECREF(v);\n        return result;\n    }\n    else if (PyErr_Occurred()) {\n        goto onError;\n    }\n\n    /* Next, scan the search functions in order of registration */\n    const Py_ssize_t len = PyList_Size(interp->codec_search_path);\n    if (len < 0)\n        goto onError;\n    if (len == 0) {\n        PyErr_SetString(PyExc_LookupError,\n                        \"no codec search functions registered: \"\n                        \"can't find encoding\");\n        goto onError;\n    }\n\n    Py_ssize_t i;\n    for (i = 0; i < len; i++) {\n        PyObject *func;\n\n        func = PyList_GetItem(interp->codec_search_path, i);\n        if (func == NULL)\n            goto onError;\n        result = PyObject_CallOneArg(func, v);\n        if (result == NULL)\n            goto onError;\n        if (result == Py_None) {\n            Py_DECREF(result);\n            continue;\n        }\n        if (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != 4) {\n            PyErr_SetString(PyExc_TypeError,\n                            \"codec search functions must return 4-tuples\");\n            Py_DECREF(result);\n            goto onError;\n        }\n        break;\n    }\n    if (i == len) {\n        /* XXX Perhaps we should cache misses too ? */\n        PyErr_Format(PyExc_LookupError,\n                     \"unknown encoding: %s\", encoding);\n        goto onError;\n    }\n\n    /* Cache and return the result */\n    if (PyDict_SetItem(interp->codec_search_cache, v, result) < 0) {\n        Py_DECREF(result);\n        goto onError;\n    }\n    Py_DECREF(v);\n    return result;\n\n onError:\n    Py_DECREF(v);\n    return NULL;\n}\n\n/* Codec registry encoding check API. */\n\nint PyCodec_KnownEncoding(const char *encoding)\n{\n    PyObject *codecs;\n\n    codecs = _PyCodec_Lookup(encoding);\n    if (!codecs) {\n        PyErr_Clear();\n        return 0;\n    }\n    else {\n        Py_DECREF(codecs);\n        return 1;\n    }\n}\n\nstatic\nPyObject *args_tuple(PyObject *object,\n                     const char *errors)\n{\n    PyObject *args;\n\n    args = PyTuple_New(1 + (errors != NULL));\n    if (args == NULL)\n        return NULL;\n    PyTuple_SET_ITEM(args, 0, Py_NewRef(object));\n    if (errors) {\n        PyObject *v;\n\n        v = PyUnicode_FromString(errors);\n        if (v == NULL) {\n            Py_DECREF(args);\n            return NULL;\n        }\n        PyTuple_SET_ITEM(args, 1, v);\n    }\n    return args;\n}\n\n/* Helper function to get a codec item */\n\nstatic\nPyObject *codec_getitem(const char *encoding, int index)\n{\n    PyObject *codecs;\n    PyObject *v;\n\n    codecs = _PyCodec_Lookup(encoding);\n    if (codecs == NULL)\n        return NULL;\n    v = PyTuple_GET_ITEM(codecs, index);\n    Py_DECREF(codecs);\n    return Py_NewRef(v);\n}\n\n/* Helper functions to create an incremental codec. */\nstatic\nPyObject *codec_makeincrementalcodec(PyObject *codec_info,\n                                     const char *errors,\n                                     const char *attrname)\n{\n    PyObject *ret, *inccodec;\n\n    inccodec = PyObject_GetAttrString(codec_info, attrname);\n    if (inccodec == NULL)\n        return NULL;\n    if (errors)\n        ret = PyObject_CallFunction(inccodec, \"s\", errors);\n    else\n        ret = _PyObject_CallNoArgs(inccodec);\n    Py_DECREF(inccodec);\n    return ret;\n}\n\nstatic\nPyObject *codec_getincrementalcodec(const char *encoding,\n                                    const char *errors,\n                                    const char *attrname)\n{\n    PyObject *codec_info, *ret;\n\n    codec_info = _PyCodec_Lookup(encoding);\n    if (codec_info == NULL)\n        return NULL;\n    ret = codec_makeincrementalcodec(codec_info, errors, attrname);\n    Py_DECREF(codec_info);\n    return ret;\n}\n\n/* Helper function to create a stream codec. */\n\nstatic\nPyObject *codec_getstreamcodec(const char *encoding,\n                               PyObject *stream,\n                               const char *errors,\n                               const int index)\n{\n    PyObject *codecs, *streamcodec, *codeccls;\n\n    codecs = _PyCodec_Lookup(encoding);\n    if (codecs == NULL)\n        return NULL;\n\n    codeccls = PyTuple_GET_ITEM(codecs, index);\n    if (errors != NULL)\n        streamcodec = PyObject_CallFunction(codeccls, \"Os\", stream, errors);\n    else\n        streamcodec = PyObject_CallOneArg(codeccls, stream);\n    Py_DECREF(codecs);\n    return streamcodec;\n}\n\n/* Helpers to work with the result of _PyCodec_Lookup\n\n */\nPyObject *_PyCodecInfo_GetIncrementalDecoder(PyObject *codec_info,\n                                             const char *errors)\n{\n    return codec_makeincrementalcodec(codec_info, errors,\n                                      \"incrementaldecoder\");\n}\n\nPyObject *_PyCodecInfo_GetIncrementalEncoder(PyObject *codec_info,\n                                             const char *errors)\n{\n    return codec_makeincrementalcodec(codec_info, errors,\n                                      \"incrementalencoder\");\n}\n\n\n/* Convenience APIs to query the Codec registry.\n\n   All APIs return a codec object with incremented refcount.\n\n */\n\nPyObject *PyCodec_Encoder(const char *encoding)\n{\n    return codec_getitem(encoding, 0);\n}\n\nPyObject *PyCodec_Decoder(const char *encoding)\n{\n    return codec_getitem(encoding, 1);\n}\n\nPyObject *PyCodec_IncrementalEncoder(const char *encoding,\n                                     const char *errors)\n{\n    return codec_getincrementalcodec(encoding, errors, \"incrementalencoder\");\n}\n\nPyObject *PyCodec_IncrementalDecoder(const char *encoding,\n                                     const char *errors)\n{\n    return codec_getincrementalcodec(encoding, errors, \"incrementaldecoder\");\n}\n\nPyObject *PyCodec_StreamReader(const char *encoding,\n                               PyObject *stream,\n                               const char *errors)\n{\n    return codec_getstreamcodec(encoding, stream, errors, 2);\n}\n\nPyObject *PyCodec_StreamWriter(const char *encoding,\n                               PyObject *stream,\n                               const char *errors)\n{\n    return codec_getstreamcodec(encoding, stream, errors, 3);\n}\n\n/* Encode an object (e.g. a Unicode object) using the given encoding\n   and return the resulting encoded object (usually a Python string).\n\n   errors is passed to the encoder factory as argument if non-NULL. */\n\nstatic PyObject *\n_PyCodec_EncodeInternal(PyObject *object,\n                        PyObject *encoder,\n                        const char *encoding,\n                        const char *errors)\n{\n    PyObject *args = NULL, *result = NULL;\n    PyObject *v = NULL;\n\n    args = args_tuple(object, errors);\n    if (args == NULL)\n        goto onError;\n\n    result = PyObject_Call(encoder, args, NULL);\n    if (result == NULL) {\n        _PyErr_FormatNote(\"%s with '%s' codec failed\", \"encoding\", encoding);\n        goto onError;\n    }\n\n    if (!PyTuple_Check(result) ||\n        PyTuple_GET_SIZE(result) != 2) {\n        PyErr_SetString(PyExc_TypeError,\n                        \"encoder must return a tuple (object, integer)\");\n        goto onError;\n    }\n    v = Py_NewRef(PyTuple_GET_ITEM(result,0));\n    /* We don't check or use the second (integer) entry. */\n\n    Py_DECREF(args);\n    Py_DECREF(encoder);\n    Py_DECREF(result);\n    return v;\n\n onError:\n    Py_XDECREF(result);\n    Py_XDECREF(args);\n    Py_XDECREF(encoder);\n    return NULL;\n}\n\n/* Decode an object (usually a Python string) using the given encoding\n   and return an equivalent object (e.g. a Unicode object).\n\n   errors is passed to the decoder factory as argument if non-NULL. */\n\nstatic PyObject *\n_PyCodec_DecodeInternal(PyObject *object,\n                        PyObject *decoder,\n                        const char *encoding,\n                        const char *errors)\n{\n    PyObject *args = NULL, *result = NULL;\n    PyObject *v;\n\n    args = args_tuple(object, errors);\n    if (args == NULL)\n        goto onError;\n\n    result = PyObject_Call(decoder, args, NULL);\n    if (result == NULL) {\n        _PyErr_FormatNote(\"%s with '%s' codec failed\", \"decoding\", encoding);\n        goto onError;\n    }\n    if (!PyTuple_Check(result) ||\n        PyTuple_GET_SIZE(result) != 2) {\n        PyErr_SetString(PyExc_TypeError,\n                        \"decoder must return a tuple (object,integer)\");\n        goto onError;\n    }\n    v = Py_NewRef(PyTuple_GET_ITEM(result,0));\n    /* We don't check or use the second (integer) entry. */\n\n    Py_DECREF(args);\n    Py_DECREF(decoder);\n    Py_DECREF(result);\n    return v;\n\n onError:\n    Py_XDECREF(args);\n    Py_XDECREF(decoder);\n    Py_XDECREF(result);\n    return NULL;\n}\n\n/* Generic encoding/decoding API */\nPyObject *PyCodec_Encode(PyObject *object,\n                         const char *encoding,\n                         const char *errors)\n{\n    PyObject *encoder;\n\n    encoder = PyCodec_Encoder(encoding);\n    if (encoder == NULL)\n        return NULL;\n\n    return _PyCodec_EncodeInternal(object, encoder, encoding, errors);\n}\n\nPyObject *PyCodec_Decode(PyObject *object,\n                         const char *encoding,\n                         const char *errors)\n{\n    PyObject *decoder;\n\n    decoder = PyCodec_Decoder(encoding);\n    if (decoder == NULL)\n        return NULL;\n\n    return _PyCodec_DecodeInternal(object, decoder, encoding, errors);\n}\n\n/* Text encoding/decoding API */\nPyObject * _PyCodec_LookupTextEncoding(const char *encoding,\n                                       const char *alternate_command)\n{\n    PyObject *codec;\n    PyObject *attr;\n    int is_text_codec;\n\n    codec = _PyCodec_Lookup(encoding);\n    if (codec == NULL)\n        return NULL;\n\n    /* Backwards compatibility: assume any raw tuple describes a text\n     * encoding, and the same for anything lacking the private\n     * attribute.\n     */\n    if (!PyTuple_CheckExact(codec)) {\n        if (_PyObject_LookupAttr(codec, &_Py_ID(_is_text_encoding), &attr) < 0) {\n            Py_DECREF(codec);\n            return NULL;\n        }\n        if (attr != NULL) {\n            is_text_codec = PyObject_IsTrue(attr);\n            Py_DECREF(attr);\n            if (is_text_codec <= 0) {\n                Py_DECREF(codec);\n                if (!is_text_codec)\n                    PyErr_Format(PyExc_LookupError,\n                                 \"'%.400s' is not a text encoding; \"\n                                 \"use %s to handle arbitrary codecs\",\n                                 encoding, alternate_command);\n                return NULL;\n            }\n        }\n    }\n\n    /* This appears to be a valid text encoding */\n    return codec;\n}\n\n\nstatic\nPyObject *codec_getitem_checked(const char *encoding,\n                                const char *alternate_command,\n                                int index)\n{\n    PyObject *codec;\n    PyObject *v;\n\n    codec = _PyCodec_LookupTextEncoding(encoding, alternate_command);\n    if (codec == NULL)\n        return NULL;\n\n    v = Py_NewRef(PyTuple_GET_ITEM(codec, index));\n    Py_DECREF(codec);\n    return v;\n}\n\nstatic PyObject * _PyCodec_TextEncoder(const char *encoding)\n{\n    return codec_getitem_checked(encoding, \"codecs.encode()\", 0);\n}\n\nstatic PyObject * _PyCodec_TextDecoder(const char *encoding)\n{\n    return codec_getitem_checked(encoding, \"codecs.decode()\", 1);\n}\n\nPyObject *_PyCodec_EncodeText(PyObject *object,\n                              const char *encoding,\n                              const char *errors)\n{\n    PyObject *encoder;\n\n    encoder = _PyCodec_TextEncoder(encoding);\n    if (encoder == NULL)\n        return NULL;\n\n    return _PyCodec_EncodeInternal(object, encoder, encoding, errors);\n}\n\nPyObject *_PyCodec_DecodeText(PyObject *object,\n                              const char *encoding,\n                              const char *errors)\n{\n    PyObject *decoder;\n\n    decoder = _PyCodec_TextDecoder(encoding);\n    if (decoder == NULL)\n        return NULL;\n\n    return _PyCodec_DecodeInternal(object, decoder, encoding, errors);\n}\n\n/* Register the error handling callback function error under the name\n   name. This function will be called by the codec when it encounters\n   an unencodable characters/undecodable bytes and doesn't know the\n   callback name, when name is specified as the error parameter\n   in the call to the encode/decode function.\n   Return 0 on success, -1 on error */\nint PyCodec_RegisterError(const char *name, PyObject *error)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())\n        return -1;\n    if (!PyCallable_Check(error)) {\n        PyErr_SetString(PyExc_TypeError, \"handler must be callable\");\n        return -1;\n    }\n    return PyDict_SetItemString(interp->codec_error_registry,\n                                name, error);\n}\n\n/* Lookup the error handling callback function registered under the\n   name error. As a special case NULL can be passed, in which case\n   the error handling callback for strict encoding will be returned. */\nPyObject *PyCodec_LookupError(const char *name)\n{\n    PyObject *handler = NULL;\n\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())\n        return NULL;\n\n    if (name==NULL)\n        name = \"strict\";\n    handler = _PyDict_GetItemStringWithError(interp->codec_error_registry, name);\n    if (handler) {\n        Py_INCREF(handler);\n    }\n    else if (!PyErr_Occurred()) {\n        PyErr_Format(PyExc_LookupError, \"unknown error handler name '%.400s'\", name);\n    }\n    return handler;\n}\n\nstatic void wrong_exception_type(PyObject *exc)\n{\n    PyErr_Format(PyExc_TypeError,\n                 \"don't know how to handle %.200s in error callback\",\n                 Py_TYPE(exc)->tp_name);\n}\n\nPyObject *PyCodec_StrictErrors(PyObject *exc)\n{\n    if (PyExceptionInstance_Check(exc))\n        PyErr_SetObject(PyExceptionInstance_Class(exc), exc);\n    else\n        PyErr_SetString(PyExc_TypeError, \"codec must pass exception instance\");\n    return NULL;\n}\n\n\nPyObject *PyCodec_IgnoreErrors(PyObject *exc)\n{\n    Py_ssize_t end;\n\n    if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {\n        if (PyUnicodeEncodeError_GetEnd(exc, &end))\n            return NULL;\n    }\n    else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {\n        if (PyUnicodeDecodeError_GetEnd(exc, &end))\n            return NULL;\n    }\n    else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) {\n        if (PyUnicodeTranslateError_GetEnd(exc, &end))\n            return NULL;\n    }\n    else {\n        wrong_exception_type(exc);\n        return NULL;\n    }\n    return Py_BuildValue(\"(Nn)\", PyUnicode_New(0, 0), end);\n}\n\n\nPyObject *PyCodec_ReplaceErrors(PyObject *exc)\n{\n    Py_ssize_t start, end, i, len;\n\n    if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {\n        PyObject *res;\n        Py_UCS1 *outp;\n        if (PyUnicodeEncodeError_GetStart(exc, &start))\n            return NULL;\n        if (PyUnicodeEncodeError_GetEnd(exc, &end))\n            return NULL;\n        len = end - start;\n        res = PyUnicode_New(len, '?');\n        if (res == NULL)\n            return NULL;\n        assert(PyUnicode_KIND(res) == PyUnicode_1BYTE_KIND);\n        outp = PyUnicode_1BYTE_DATA(res);\n        for (i = 0; i < len; ++i)\n            outp[i] = '?';\n        assert(_PyUnicode_CheckConsistency(res, 1));\n        return Py_BuildValue(\"(Nn)\", res, end);\n    }\n    else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {\n        if (PyUnicodeDecodeError_GetEnd(exc, &end))\n            return NULL;\n        return Py_BuildValue(\"(Cn)\",\n                             (int)Py_UNICODE_REPLACEMENT_CHARACTER,\n                             end);\n    }\n    else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) {\n        PyObject *res;\n        Py_UCS2 *outp;\n        if (PyUnicodeTranslateError_GetStart(exc, &start))\n            return NULL;\n        if (PyUnicodeTranslateError_GetEnd(exc, &end))\n            return NULL;\n        len = end - start;\n        res = PyUnicode_New(len, Py_UNICODE_REPLACEMENT_CHARACTER);\n        if (res == NULL)\n            return NULL;\n        assert(PyUnicode_KIND(res) == PyUnicode_2BYTE_KIND);\n        outp = PyUnicode_2BYTE_DATA(res);\n        for (i = 0; i < len; i++)\n            outp[i] = Py_UNICODE_REPLACEMENT_CHARACTER;\n        assert(_PyUnicode_CheckConsistency(res, 1));\n        return Py_BuildValue(\"(Nn)\", res, end);\n    }\n    else {\n        wrong_exception_type(exc);\n        return NULL;\n    }\n}\n\nPyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc)\n{\n    if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {\n        PyObject *restuple;\n        PyObject *object;\n        Py_ssize_t i;\n        Py_ssize_t start;\n        Py_ssize_t end;\n        PyObject *res;\n        Py_UCS1 *outp;\n        Py_ssize_t ressize;\n        Py_UCS4 ch;\n        if (PyUnicodeEncodeError_GetStart(exc, &start))\n            return NULL;\n        if (PyUnicodeEncodeError_GetEnd(exc, &end))\n            return NULL;\n        if (!(object = PyUnicodeEncodeError_GetObject(exc)))\n            return NULL;\n        if (end - start > PY_SSIZE_T_MAX / (2+7+1))\n            end = start + PY_SSIZE_T_MAX / (2+7+1);\n        for (i = start, ressize = 0; i < end; ++i) {\n            /* object is guaranteed to be \"ready\" */\n            ch = PyUnicode_READ_CHAR(object, i);\n            if (ch<10)\n                ressize += 2+1+1;\n            else if (ch<100)\n                ressize += 2+2+1;\n            else if (ch<1000)\n                ressize += 2+3+1;\n            else if (ch<10000)\n                ressize += 2+4+1;\n            else if (ch<100000)\n                ressize += 2+5+1;\n            else if (ch<1000000)\n                ressize += 2+6+1;\n            else\n                ressize += 2+7+1;\n        }\n        /* allocate replacement */\n        res = PyUnicode_New(ressize, 127);\n        if (res == NULL) {\n            Py_DECREF(object);\n            return NULL;\n        }\n        outp = PyUnicode_1BYTE_DATA(res);\n        /* generate replacement */\n        for (i = start; i < end; ++i) {\n            int digits;\n            int base;\n            ch = PyUnicode_READ_CHAR(object, i);\n            *outp++ = '&';\n            *outp++ = '#';\n            if (ch<10) {\n                digits = 1;\n                base = 1;\n            }\n            else if (ch<100) {\n                digits = 2;\n                base = 10;\n            }\n            else if (ch<1000) {\n                digits = 3;\n                base = 100;\n            }\n            else if (ch<10000) {\n                digits = 4;\n                base = 1000;\n            }\n            else if (ch<100000) {\n                digits = 5;\n                base = 10000;\n            }\n            else if (ch<1000000) {\n                digits = 6;\n                base = 100000;\n            }\n            else {\n                digits = 7;\n                base = 1000000;\n            }\n            while (digits-->0) {\n                *outp++ = '0' + ch/base;\n                ch %= base;\n                base /= 10;\n            }\n            *outp++ = ';';\n        }\n        assert(_PyUnicode_CheckConsistency(res, 1));\n        restuple = Py_BuildValue(\"(Nn)\", res, end);\n        Py_DECREF(object);\n        return restuple;\n    }\n    else {\n        wrong_exception_type(exc);\n        return NULL;\n    }\n}\n\nPyObject *PyCodec_BackslashReplaceErrors(PyObject *exc)\n{\n    PyObject *object;\n    Py_ssize_t i;\n    Py_ssize_t start;\n    Py_ssize_t end;\n    PyObject *res;\n    Py_UCS1 *outp;\n    int ressize;\n    Py_UCS4 c;\n\n    if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {\n        const unsigned char *p;\n        if (PyUnicodeDecodeError_GetStart(exc, &start))\n            return NULL;\n        if (PyUnicodeDecodeError_GetEnd(exc, &end))\n            return NULL;\n        if (!(object = PyUnicodeDecodeError_GetObject(exc)))\n            return NULL;\n        p = (const unsigned char*)PyBytes_AS_STRING(object);\n        res = PyUnicode_New(4 * (end - start), 127);\n        if (res == NULL) {\n            Py_DECREF(object);\n            return NULL;\n        }\n        outp = PyUnicode_1BYTE_DATA(res);\n        for (i = start; i < end; i++, outp += 4) {\n            unsigned char c = p[i];\n            outp[0] = '\\\\';\n            outp[1] = 'x';\n            outp[2] = Py_hexdigits[(c>>4)&0xf];\n            outp[3] = Py_hexdigits[c&0xf];\n        }\n\n        assert(_PyUnicode_CheckConsistency(res, 1));\n        Py_DECREF(object);\n        return Py_BuildValue(\"(Nn)\", res, end);\n    }\n    if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {\n        if (PyUnicodeEncodeError_GetStart(exc, &start))\n            return NULL;\n        if (PyUnicodeEncodeError_GetEnd(exc, &end))\n            return NULL;\n        if (!(object = PyUnicodeEncodeError_GetObject(exc)))\n            return NULL;\n    }\n    else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeTranslateError)) {\n        if (PyUnicodeTranslateError_GetStart(exc, &start))\n            return NULL;\n        if (PyUnicodeTranslateError_GetEnd(exc, &end))\n            return NULL;\n        if (!(object = PyUnicodeTranslateError_GetObject(exc)))\n            return NULL;\n    }\n    else {\n        wrong_exception_type(exc);\n        return NULL;\n    }\n\n    if (end - start > PY_SSIZE_T_MAX / (1+1+8))\n        end = start + PY_SSIZE_T_MAX / (1+1+8);\n    for (i = start, ressize = 0; i < end; ++i) {\n        /* object is guaranteed to be \"ready\" */\n        c = PyUnicode_READ_CHAR(object, i);\n        if (c >= 0x10000) {\n            ressize += 1+1+8;\n        }\n        else if (c >= 0x100) {\n            ressize += 1+1+4;\n        }\n        else\n            ressize += 1+1+2;\n    }\n    res = PyUnicode_New(ressize, 127);\n    if (res == NULL) {\n        Py_DECREF(object);\n        return NULL;\n    }\n    outp = PyUnicode_1BYTE_DATA(res);\n    for (i = start; i < end; ++i) {\n        c = PyUnicode_READ_CHAR(object, i);\n        *outp++ = '\\\\';\n        if (c >= 0x00010000) {\n            *outp++ = 'U';\n            *outp++ = Py_hexdigits[(c>>28)&0xf];\n            *outp++ = Py_hexdigits[(c>>24)&0xf];\n            *outp++ = Py_hexdigits[(c>>20)&0xf];\n            *outp++ = Py_hexdigits[(c>>16)&0xf];\n            *outp++ = Py_hexdigits[(c>>12)&0xf];\n            *outp++ = Py_hexdigits[(c>>8)&0xf];\n        }\n        else if (c >= 0x100) {\n            *outp++ = 'u';\n            *outp++ = Py_hexdigits[(c>>12)&0xf];\n            *outp++ = Py_hexdigits[(c>>8)&0xf];\n        }\n        else\n            *outp++ = 'x';\n        *outp++ = Py_hexdigits[(c>>4)&0xf];\n        *outp++ = Py_hexdigits[c&0xf];\n    }\n\n    assert(_PyUnicode_CheckConsistency(res, 1));\n    Py_DECREF(object);\n    return Py_BuildValue(\"(Nn)\", res, end);\n}\n\nstatic _PyUnicode_Name_CAPI *ucnhash_capi = NULL;\n\nPyObject *PyCodec_NameReplaceErrors(PyObject *exc)\n{\n    if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {\n        PyObject *restuple;\n        PyObject *object;\n        Py_ssize_t i;\n        Py_ssize_t start;\n        Py_ssize_t end;\n        PyObject *res;\n        Py_UCS1 *outp;\n        Py_ssize_t ressize;\n        int replsize;\n        Py_UCS4 c;\n        char buffer[256]; /* NAME_MAXLEN */\n        if (PyUnicodeEncodeError_GetStart(exc, &start))\n            return NULL;\n        if (PyUnicodeEncodeError_GetEnd(exc, &end))\n            return NULL;\n        if (!(object = PyUnicodeEncodeError_GetObject(exc)))\n            return NULL;\n        if (!ucnhash_capi) {\n            /* load the unicode data module */\n            ucnhash_capi = (_PyUnicode_Name_CAPI *)PyCapsule_Import(\n                                            PyUnicodeData_CAPSULE_NAME, 1);\n            if (!ucnhash_capi) {\n                return NULL;\n            }\n        }\n        for (i = start, ressize = 0; i < end; ++i) {\n            /* object is guaranteed to be \"ready\" */\n            c = PyUnicode_READ_CHAR(object, i);\n            if (ucnhash_capi->getname(c, buffer, sizeof(buffer), 1)) {\n                replsize = 1+1+1+(int)strlen(buffer)+1;\n            }\n            else if (c >= 0x10000) {\n                replsize = 1+1+8;\n            }\n            else if (c >= 0x100) {\n                replsize = 1+1+4;\n            }\n            else\n                replsize = 1+1+2;\n            if (ressize > PY_SSIZE_T_MAX - replsize)\n                break;\n            ressize += replsize;\n        }\n        end = i;\n        res = PyUnicode_New(ressize, 127);\n        if (res==NULL)\n            return NULL;\n        for (i = start, outp = PyUnicode_1BYTE_DATA(res);\n            i < end; ++i) {\n            c = PyUnicode_READ_CHAR(object, i);\n            *outp++ = '\\\\';\n            if (ucnhash_capi->getname(c, buffer, sizeof(buffer), 1)) {\n                *outp++ = 'N';\n                *outp++ = '{';\n                strcpy((char *)outp, buffer);\n                outp += strlen(buffer);\n                *outp++ = '}';\n                continue;\n            }\n            if (c >= 0x00010000) {\n                *outp++ = 'U';\n                *outp++ = Py_hexdigits[(c>>28)&0xf];\n                *outp++ = Py_hexdigits[(c>>24)&0xf];\n                *outp++ = Py_hexdigits[(c>>20)&0xf];\n                *outp++ = Py_hexdigits[(c>>16)&0xf];\n                *outp++ = Py_hexdigits[(c>>12)&0xf];\n                *outp++ = Py_hexdigits[(c>>8)&0xf];\n            }\n            else if (c >= 0x100) {\n                *outp++ = 'u';\n                *outp++ = Py_hexdigits[(c>>12)&0xf];\n                *outp++ = Py_hexdigits[(c>>8)&0xf];\n            }\n            else\n                *outp++ = 'x';\n            *outp++ = Py_hexdigits[(c>>4)&0xf];\n            *outp++ = Py_hexdigits[c&0xf];\n        }\n\n        assert(outp == PyUnicode_1BYTE_DATA(res) + ressize);\n        assert(_PyUnicode_CheckConsistency(res, 1));\n        restuple = Py_BuildValue(\"(Nn)\", res, end);\n        Py_DECREF(object);\n        return restuple;\n    }\n    else {\n        wrong_exception_type(exc);\n        return NULL;\n    }\n}\n\n#define ENC_UNKNOWN     -1\n#define ENC_UTF8        0\n#define ENC_UTF16BE     1\n#define ENC_UTF16LE     2\n#define ENC_UTF32BE     3\n#define ENC_UTF32LE     4\n\nstatic int\nget_standard_encoding(const char *encoding, int *bytelength)\n{\n    if (Py_TOLOWER(encoding[0]) == 'u' &&\n        Py_TOLOWER(encoding[1]) == 't' &&\n        Py_TOLOWER(encoding[2]) == 'f') {\n        encoding += 3;\n        if (*encoding == '-' || *encoding == '_' )\n            encoding++;\n        if (encoding[0] == '8' && encoding[1] == '\\0') {\n            *bytelength = 3;\n            return ENC_UTF8;\n        }\n        else if (encoding[0] == '1' && encoding[1] == '6') {\n            encoding += 2;\n            *bytelength = 2;\n            if (*encoding == '\\0') {\n#ifdef WORDS_BIGENDIAN\n                return ENC_UTF16BE;\n#else\n                return ENC_UTF16LE;\n#endif\n            }\n            if (*encoding == '-' || *encoding == '_' )\n                encoding++;\n            if (Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\\0') {\n                if (Py_TOLOWER(encoding[0]) == 'b')\n                    return ENC_UTF16BE;\n                if (Py_TOLOWER(encoding[0]) == 'l')\n                    return ENC_UTF16LE;\n            }\n        }\n        else if (encoding[0] == '3' && encoding[1] == '2') {\n            encoding += 2;\n            *bytelength = 4;\n            if (*encoding == '\\0') {\n#ifdef WORDS_BIGENDIAN\n                return ENC_UTF32BE;\n#else\n                return ENC_UTF32LE;\n#endif\n            }\n            if (*encoding == '-' || *encoding == '_' )\n                encoding++;\n            if (Py_TOLOWER(encoding[1]) == 'e' && encoding[2] == '\\0') {\n                if (Py_TOLOWER(encoding[0]) == 'b')\n                    return ENC_UTF32BE;\n                if (Py_TOLOWER(encoding[0]) == 'l')\n                    return ENC_UTF32LE;\n            }\n        }\n    }\n    else if (strcmp(encoding, \"CP_UTF8\") == 0) {\n        *bytelength = 3;\n        return ENC_UTF8;\n    }\n    return ENC_UNKNOWN;\n}\n\n/* This handler is declared static until someone demonstrates\n   a need to call it directly. */\nstatic PyObject *\nPyCodec_SurrogatePassErrors(PyObject *exc)\n{\n    PyObject *restuple;\n    PyObject *object;\n    PyObject *encode;\n    const char *encoding;\n    int code;\n    int bytelength;\n    Py_ssize_t i;\n    Py_ssize_t start;\n    Py_ssize_t end;\n    PyObject *res;\n\n    if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {\n        unsigned char *outp;\n        if (PyUnicodeEncodeError_GetStart(exc, &start))\n            return NULL;\n        if (PyUnicodeEncodeError_GetEnd(exc, &end))\n            return NULL;\n        if (!(object = PyUnicodeEncodeError_GetObject(exc)))\n            return NULL;\n        if (!(encode = PyUnicodeEncodeError_GetEncoding(exc))) {\n            Py_DECREF(object);\n            return NULL;\n        }\n        if (!(encoding = PyUnicode_AsUTF8(encode))) {\n            Py_DECREF(object);\n            Py_DECREF(encode);\n            return NULL;\n        }\n        code = get_standard_encoding(encoding, &bytelength);\n        Py_DECREF(encode);\n        if (code == ENC_UNKNOWN) {\n            /* Not supported, fail with original exception */\n            PyErr_SetObject(PyExceptionInstance_Class(exc), exc);\n            Py_DECREF(object);\n            return NULL;\n        }\n\n        if (end - start > PY_SSIZE_T_MAX / bytelength)\n            end = start + PY_SSIZE_T_MAX / bytelength;\n        res = PyBytes_FromStringAndSize(NULL, bytelength*(end-start));\n        if (!res) {\n            Py_DECREF(object);\n            return NULL;\n        }\n        outp = (unsigned char*)PyBytes_AsString(res);\n        for (i = start; i < end; i++) {\n            /* object is guaranteed to be \"ready\" */\n            Py_UCS4 ch = PyUnicode_READ_CHAR(object, i);\n            if (!Py_UNICODE_IS_SURROGATE(ch)) {\n                /* Not a surrogate, fail with original exception */\n                PyErr_SetObject(PyExceptionInstance_Class(exc), exc);\n                Py_DECREF(res);\n                Py_DECREF(object);\n                return NULL;\n            }\n            switch (code) {\n            case ENC_UTF8:\n                *outp++ = (unsigned char)(0xe0 | (ch >> 12));\n                *outp++ = (unsigned char)(0x80 | ((ch >> 6) & 0x3f));\n                *outp++ = (unsigned char)(0x80 | (ch & 0x3f));\n                break;\n            case ENC_UTF16LE:\n                *outp++ = (unsigned char) ch;\n                *outp++ = (unsigned char)(ch >> 8);\n                break;\n            case ENC_UTF16BE:\n                *outp++ = (unsigned char)(ch >> 8);\n                *outp++ = (unsigned char) ch;\n                break;\n            case ENC_UTF32LE:\n                *outp++ = (unsigned char) ch;\n                *outp++ = (unsigned char)(ch >> 8);\n                *outp++ = (unsigned char)(ch >> 16);\n                *outp++ = (unsigned char)(ch >> 24);\n                break;\n            case ENC_UTF32BE:\n                *outp++ = (unsigned char)(ch >> 24);\n                *outp++ = (unsigned char)(ch >> 16);\n                *outp++ = (unsigned char)(ch >> 8);\n                *outp++ = (unsigned char) ch;\n                break;\n            }\n        }\n        restuple = Py_BuildValue(\"(On)\", res, end);\n        Py_DECREF(res);\n        Py_DECREF(object);\n        return restuple;\n    }\n    else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {\n        const unsigned char *p;\n        Py_UCS4 ch = 0;\n        if (PyUnicodeDecodeError_GetStart(exc, &start))\n            return NULL;\n        if (PyUnicodeDecodeError_GetEnd(exc, &end))\n            return NULL;\n        if (!(object = PyUnicodeDecodeError_GetObject(exc)))\n            return NULL;\n        p = (const unsigned char*)PyBytes_AS_STRING(object);\n        if (!(encode = PyUnicodeDecodeError_GetEncoding(exc))) {\n            Py_DECREF(object);\n            return NULL;\n        }\n        if (!(encoding = PyUnicode_AsUTF8(encode))) {\n            Py_DECREF(object);\n            Py_DECREF(encode);\n            return NULL;\n        }\n        code = get_standard_encoding(encoding, &bytelength);\n        Py_DECREF(encode);\n        if (code == ENC_UNKNOWN) {\n            /* Not supported, fail with original exception */\n            PyErr_SetObject(PyExceptionInstance_Class(exc), exc);\n            Py_DECREF(object);\n            return NULL;\n        }\n\n        /* Try decoding a single surrogate character. If\n           there are more, let the codec call us again. */\n        p += start;\n        if (PyBytes_GET_SIZE(object) - start >= bytelength) {\n            switch (code) {\n            case ENC_UTF8:\n                if ((p[0] & 0xf0) == 0xe0 &&\n                    (p[1] & 0xc0) == 0x80 &&\n                    (p[2] & 0xc0) == 0x80) {\n                    /* it's a three-byte code */\n                    ch = ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f);\n                }\n                break;\n            case ENC_UTF16LE:\n                ch = p[1] << 8 | p[0];\n                break;\n            case ENC_UTF16BE:\n                ch = p[0] << 8 | p[1];\n                break;\n            case ENC_UTF32LE:\n                ch = (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];\n                break;\n            case ENC_UTF32BE:\n                ch = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];\n                break;\n            }\n        }\n\n        Py_DECREF(object);\n        if (!Py_UNICODE_IS_SURROGATE(ch)) {\n            /* it's not a surrogate - fail */\n            PyErr_SetObject(PyExceptionInstance_Class(exc), exc);\n            return NULL;\n        }\n        res = PyUnicode_FromOrdinal(ch);\n        if (res == NULL)\n            return NULL;\n        return Py_BuildValue(\"(Nn)\", res, start + bytelength);\n    }\n    else {\n        wrong_exception_type(exc);\n        return NULL;\n    }\n}\n\nstatic PyObject *\nPyCodec_SurrogateEscapeErrors(PyObject *exc)\n{\n    PyObject *restuple;\n    PyObject *object;\n    Py_ssize_t i;\n    Py_ssize_t start;\n    Py_ssize_t end;\n    PyObject *res;\n\n    if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeEncodeError)) {\n        char *outp;\n        if (PyUnicodeEncodeError_GetStart(exc, &start))\n            return NULL;\n        if (PyUnicodeEncodeError_GetEnd(exc, &end))\n            return NULL;\n        if (!(object = PyUnicodeEncodeError_GetObject(exc)))\n            return NULL;\n        res = PyBytes_FromStringAndSize(NULL, end-start);\n        if (!res) {\n            Py_DECREF(object);\n            return NULL;\n        }\n        outp = PyBytes_AsString(res);\n        for (i = start; i < end; i++) {\n            /* object is guaranteed to be \"ready\" */\n            Py_UCS4 ch = PyUnicode_READ_CHAR(object, i);\n            if (ch < 0xdc80 || ch > 0xdcff) {\n                /* Not a UTF-8b surrogate, fail with original exception */\n                PyErr_SetObject(PyExceptionInstance_Class(exc), exc);\n                Py_DECREF(res);\n                Py_DECREF(object);\n                return NULL;\n            }\n            *outp++ = ch - 0xdc00;\n        }\n        restuple = Py_BuildValue(\"(On)\", res, end);\n        Py_DECREF(res);\n        Py_DECREF(object);\n        return restuple;\n    }\n    else if (PyObject_TypeCheck(exc, (PyTypeObject *)PyExc_UnicodeDecodeError)) {\n        PyObject *str;\n        const unsigned char *p;\n        Py_UCS2 ch[4]; /* decode up to 4 bad bytes. */\n        int consumed = 0;\n        if (PyUnicodeDecodeError_GetStart(exc, &start))\n            return NULL;\n        if (PyUnicodeDecodeError_GetEnd(exc, &end))\n            return NULL;\n        if (!(object = PyUnicodeDecodeError_GetObject(exc)))\n            return NULL;\n        p = (const unsigned char*)PyBytes_AS_STRING(object);\n        while (consumed < 4 && consumed < end-start) {\n            /* Refuse to escape ASCII bytes. */\n            if (p[start+consumed] < 128)\n                break;\n            ch[consumed] = 0xdc00 + p[start+consumed];\n            consumed++;\n        }\n        Py_DECREF(object);\n        if (!consumed) {\n            /* codec complained about ASCII byte. */\n            PyErr_SetObject(PyExceptionInstance_Class(exc), exc);\n            return NULL;\n        }\n        str = PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, ch, consumed);\n        if (str == NULL)\n            return NULL;\n        return Py_BuildValue(\"(Nn)\", str, start+consumed);\n    }\n    else {\n        wrong_exception_type(exc);\n        return NULL;\n    }\n}\n\n\nstatic PyObject *strict_errors(PyObject *self, PyObject *exc)\n{\n    return PyCodec_StrictErrors(exc);\n}\n\n\nstatic PyObject *ignore_errors(PyObject *self, PyObject *exc)\n{\n    return PyCodec_IgnoreErrors(exc);\n}\n\n\nstatic PyObject *replace_errors(PyObject *self, PyObject *exc)\n{\n    return PyCodec_ReplaceErrors(exc);\n}\n\n\nstatic PyObject *xmlcharrefreplace_errors(PyObject *self, PyObject *exc)\n{\n    return PyCodec_XMLCharRefReplaceErrors(exc);\n}\n\n\nstatic PyObject *backslashreplace_errors(PyObject *self, PyObject *exc)\n{\n    return PyCodec_BackslashReplaceErrors(exc);\n}\n\nstatic PyObject *namereplace_errors(PyObject *self, PyObject *exc)\n{\n    return PyCodec_NameReplaceErrors(exc);\n}\n\nstatic PyObject *surrogatepass_errors(PyObject *self, PyObject *exc)\n{\n    return PyCodec_SurrogatePassErrors(exc);\n}\n\nstatic PyObject *surrogateescape_errors(PyObject *self, PyObject *exc)\n{\n    return PyCodec_SurrogateEscapeErrors(exc);\n}\n\nstatic int _PyCodecRegistry_Init(void)\n{\n    static struct {\n        const char *name;\n        PyMethodDef def;\n    } methods[] =\n    {\n        {\n            \"strict\",\n            {\n                \"strict_errors\",\n                strict_errors,\n                METH_O,\n                PyDoc_STR(\"Implements the 'strict' error handling, which \"\n                          \"raises a UnicodeError on coding errors.\")\n            }\n        },\n        {\n            \"ignore\",\n            {\n                \"ignore_errors\",\n                ignore_errors,\n                METH_O,\n                PyDoc_STR(\"Implements the 'ignore' error handling, which \"\n                          \"ignores malformed data and continues.\")\n            }\n        },\n        {\n            \"replace\",\n            {\n                \"replace_errors\",\n                replace_errors,\n                METH_O,\n                PyDoc_STR(\"Implements the 'replace' error handling, which \"\n                          \"replaces malformed data with a replacement marker.\")\n            }\n        },\n        {\n            \"xmlcharrefreplace\",\n            {\n                \"xmlcharrefreplace_errors\",\n                xmlcharrefreplace_errors,\n                METH_O,\n                PyDoc_STR(\"Implements the 'xmlcharrefreplace' error handling, \"\n                          \"which replaces an unencodable character with the \"\n                          \"appropriate XML character reference.\")\n            }\n        },\n        {\n            \"backslashreplace\",\n            {\n                \"backslashreplace_errors\",\n                backslashreplace_errors,\n                METH_O,\n                PyDoc_STR(\"Implements the 'backslashreplace' error handling, \"\n                          \"which replaces malformed data with a backslashed \"\n                          \"escape sequence.\")\n            }\n        },\n        {\n            \"namereplace\",\n            {\n                \"namereplace_errors\",\n                namereplace_errors,\n                METH_O,\n                PyDoc_STR(\"Implements the 'namereplace' error handling, \"\n                          \"which replaces an unencodable character with a \"\n                          \"\\\\N{...} escape sequence.\")\n            }\n        },\n        {\n            \"surrogatepass\",\n            {\n                \"surrogatepass\",\n                surrogatepass_errors,\n                METH_O\n            }\n        },\n        {\n            \"surrogateescape\",\n            {\n                \"surrogateescape\",\n                surrogateescape_errors,\n                METH_O\n            }\n        }\n    };\n\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    PyObject *mod;\n\n    if (interp->codec_search_path != NULL)\n        return 0;\n\n    interp->codec_search_path = PyList_New(0);\n    if (interp->codec_search_path == NULL) {\n        return -1;\n    }\n\n    interp->codec_search_cache = PyDict_New();\n    if (interp->codec_search_cache == NULL) {\n        return -1;\n    }\n\n    interp->codec_error_registry = PyDict_New();\n    if (interp->codec_error_registry == NULL) {\n        return -1;\n    }\n\n    for (size_t i = 0; i < Py_ARRAY_LENGTH(methods); ++i) {\n        PyObject *func = PyCFunction_NewEx(&methods[i].def, NULL, NULL);\n        if (!func) {\n            return -1;\n        }\n\n        int res = PyCodec_RegisterError(methods[i].name, func);\n        Py_DECREF(func);\n        if (res) {\n            return -1;\n        }\n    }\n\n    mod = PyImport_ImportModule(\"encodings\");\n    if (mod == NULL) {\n        return -1;\n    }\n    Py_DECREF(mod);\n    interp->codecs_initialized = 1;\n    return 0;\n}\n"
  },
  {
    "path": "Compile.c",
    "content": "#include <stdbool.h>\n\n#include \"Python.h\"\n#include \"pycore_ast.h\"           // _PyAST_GetDocString()\n#define NEED_OPCODE_TABLES\n#include \"pycore_opcode_utils.h\"\n#undef NEED_OPCODE_TABLES\n#include \"pycore_flowgraph.h\"\n#include \"pycore_code.h\"          // _PyCode_New()\n#include \"pycore_compile.h\"\n#include \"pycore_intrinsics.h\"\n#include \"pycore_long.h\"          // _PyLong_GetZero()\n#include \"pycore_symtable.h\"      // PySTEntryObject, _PyFuture_FromAST()\n\n#include \"opcode_metadata.h\"      // _PyOpcode_opcode_metadata, _PyOpcode_num_popped/pushed\n\n#define COMP_GENEXP   0\n#define COMP_LISTCOMP 1\n#define COMP_SETCOMP  2\n#define COMP_DICTCOMP 3\n\n/* A soft limit for stack use, to avoid excessive\n * memory use for large constants, etc.\n *\n * The value 30 is plucked out of thin air.\n * Code that could use more stack than this is\n * rare, so the exact value is unimportant.\n */\n#define STACK_USE_GUIDELINE 30\n\n#undef SUCCESS\n#undef ERROR\n#define SUCCESS 0\n#define ERROR -1\n\n#define RETURN_IF_ERROR(X)  \\\n    if ((X) == -1) {        \\\n        return ERROR;       \\\n    }\n\n#define IS_TOP_LEVEL_AWAIT(C) ( \\\n        ((C)->c_flags.cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \\\n        && ((C)->u->u_ste->ste_type == ModuleBlock))\n\ntypedef _PyCompilerSrcLocation location;\ntypedef _PyCfgInstruction cfg_instr;\ntypedef _PyCfgBasicblock basicblock;\ntypedef _PyCfgBuilder cfg_builder;\n\n#define LOCATION(LNO, END_LNO, COL, END_COL) \\\n    ((const _PyCompilerSrcLocation){(LNO), (END_LNO), (COL), (END_COL)})\n\n/* Return true if loc1 starts after loc2 ends. */\nstatic inline bool\nlocation_is_after(location loc1, location loc2) {\n    return (loc1.lineno > loc2.end_lineno) ||\n            ((loc1.lineno == loc2.end_lineno) &&\n             (loc1.col_offset > loc2.end_col_offset));\n}\n\n#define LOC(x) SRC_LOCATION_FROM_AST(x)\n\ntypedef _PyCfgJumpTargetLabel jump_target_label;\n\nstatic jump_target_label NO_LABEL = {-1};\n\n#define SAME_LABEL(L1, L2) ((L1).id == (L2).id)\n#define IS_LABEL(L) (!SAME_LABEL((L), (NO_LABEL)))\n\n#define NEW_JUMP_TARGET_LABEL(C, NAME) \\\n    jump_target_label NAME = instr_sequence_new_label(INSTR_SEQUENCE(C)); \\\n    if (!IS_LABEL(NAME)) { \\\n        return ERROR; \\\n    }\n\n#define USE_LABEL(C, LBL) \\\n    RETURN_IF_ERROR(instr_sequence_use_label(INSTR_SEQUENCE(C), (LBL).id))\n\n\n/* fblockinfo tracks the current frame block.\n\nA frame block is used to handle loops, try/except, and try/finally.\nIt's called a frame block to distinguish it from a basic block in the\ncompiler IR.\n*/\n\nenum fblocktype { WHILE_LOOP, FOR_LOOP, TRY_EXCEPT, FINALLY_TRY, FINALLY_END,\n                  WITH, ASYNC_WITH, HANDLER_CLEANUP, POP_VALUE, EXCEPTION_HANDLER,\n                  EXCEPTION_GROUP_HANDLER, ASYNC_COMPREHENSION_GENERATOR };\n\nstruct fblockinfo {\n    enum fblocktype fb_type;\n    jump_target_label fb_block;\n    /* (optional) type-specific exit or cleanup block */\n    jump_target_label fb_exit;\n    /* (optional) additional information required for unwinding */\n    void *fb_datum;\n};\n\nenum {\n    COMPILER_SCOPE_MODULE,\n    COMPILER_SCOPE_CLASS,\n    COMPILER_SCOPE_FUNCTION,\n    COMPILER_SCOPE_ASYNC_FUNCTION,\n    COMPILER_SCOPE_LAMBDA,\n    COMPILER_SCOPE_COMPREHENSION,\n    COMPILER_SCOPE_TYPEPARAMS,\n};\n\n\nint\n_PyCompile_InstrSize(int opcode, int oparg)\n{\n    assert(!IS_PSEUDO_OPCODE(opcode));\n    assert(HAS_ARG(opcode) || oparg == 0);\n    int extended_args = (0xFFFFFF < oparg) + (0xFFFF < oparg) + (0xFF < oparg);\n    int caches = _PyOpcode_Caches[opcode];\n    return extended_args + 1 + caches;\n}\n\ntypedef _PyCompile_Instruction instruction;\ntypedef _PyCompile_InstructionSequence instr_sequence;\n\n#define INITIAL_INSTR_SEQUENCE_SIZE 100\n#define INITIAL_INSTR_SEQUENCE_LABELS_MAP_SIZE 10\n\n/*\n * Resize the array if index is out of range.\n *\n * idx: the index we want to access\n * arr: pointer to the array\n * alloc: pointer to the capacity of the array\n * default_alloc: initial number of items\n * item_size: size of each item\n *\n */\nint\n_PyCompile_EnsureArrayLargeEnough(int idx, void **array, int *alloc,\n                                  int default_alloc, size_t item_size)\n{\n    void *arr = *array;\n    if (arr == NULL) {\n        int new_alloc = default_alloc;\n        if (idx >= new_alloc) {\n            new_alloc = idx + default_alloc;\n        }\n        arr = PyObject_Calloc(new_alloc, item_size);\n        if (arr == NULL) {\n            PyErr_NoMemory();\n            return ERROR;\n        }\n        *alloc = new_alloc;\n    }\n    else if (idx >= *alloc) {\n        size_t oldsize = *alloc * item_size;\n        int new_alloc = *alloc << 1;\n        if (idx >= new_alloc) {\n            new_alloc = idx + default_alloc;\n        }\n        size_t newsize = new_alloc * item_size;\n\n        if (oldsize > (SIZE_MAX >> 1)) {\n            PyErr_NoMemory();\n            return ERROR;\n        }\n\n        assert(newsize > 0);\n        void *tmp = PyObject_Realloc(arr, newsize);\n        if (tmp == NULL) {\n            PyErr_NoMemory();\n            return ERROR;\n        }\n        *alloc = new_alloc;\n        arr = tmp;\n        memset((char *)arr + oldsize, 0, newsize - oldsize);\n    }\n\n    *array = arr;\n    return SUCCESS;\n}\n\nstatic int\ninstr_sequence_next_inst(instr_sequence *seq) {\n    assert(seq->s_instrs != NULL || seq->s_used == 0);\n\n    RETURN_IF_ERROR(\n        _PyCompile_EnsureArrayLargeEnough(seq->s_used + 1,\n                                          (void**)&seq->s_instrs,\n                                          &seq->s_allocated,\n                                          INITIAL_INSTR_SEQUENCE_SIZE,\n                                          sizeof(instruction)));\n    assert(seq->s_allocated >= 0);\n    assert(seq->s_used < seq->s_allocated);\n    return seq->s_used++;\n}\n\nstatic jump_target_label\ninstr_sequence_new_label(instr_sequence *seq)\n{\n    jump_target_label lbl = {++seq->s_next_free_label};\n    return lbl;\n}\n\nstatic int\ninstr_sequence_use_label(instr_sequence *seq, int lbl) {\n    int old_size = seq->s_labelmap_size;\n    RETURN_IF_ERROR(\n        _PyCompile_EnsureArrayLargeEnough(lbl,\n                                          (void**)&seq->s_labelmap,\n                                           &seq->s_labelmap_size,\n                                           INITIAL_INSTR_SEQUENCE_LABELS_MAP_SIZE,\n                                           sizeof(int)));\n\n    for(int i = old_size; i < seq->s_labelmap_size; i++) {\n        seq->s_labelmap[i] = -111;  /* something weird, for debugging */\n    }\n    seq->s_labelmap[lbl] = seq->s_used; /* label refers to the next instruction */\n    return SUCCESS;\n}\n\nstatic int\ninstr_sequence_addop(instr_sequence *seq, int opcode, int oparg, location loc)\n{\n    assert(IS_WITHIN_OPCODE_RANGE(opcode));\n    assert(HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);\n    assert(0 <= oparg && oparg < (1 << 30));\n\n    int idx = instr_sequence_next_inst(seq);\n    RETURN_IF_ERROR(idx);\n    instruction *ci = &seq->s_instrs[idx];\n    ci->i_opcode = opcode;\n    ci->i_oparg = oparg;\n    ci->i_loc = loc;\n    return SUCCESS;\n}\n\nstatic int\ninstr_sequence_insert_instruction(instr_sequence *seq, int pos,\n                                  int opcode, int oparg, location loc)\n{\n    assert(pos >= 0 && pos <= seq->s_used);\n    int last_idx = instr_sequence_next_inst(seq);\n    RETURN_IF_ERROR(last_idx);\n    for (int i=last_idx-1; i >= pos; i--) {\n        seq->s_instrs[i+1] = seq->s_instrs[i];\n    }\n    instruction *ci = &seq->s_instrs[pos];\n    ci->i_opcode = opcode;\n    ci->i_oparg = oparg;\n    ci->i_loc = loc;\n\n    /* fix the labels map */\n    for(int lbl=0; lbl < seq->s_labelmap_size; lbl++) {\n        if (seq->s_labelmap[lbl] >= pos) {\n            seq->s_labelmap[lbl]++;\n        }\n    }\n    return SUCCESS;\n}\n\nstatic void\ninstr_sequence_fini(instr_sequence *seq) {\n    PyObject_Free(seq->s_labelmap);\n    seq->s_labelmap = NULL;\n\n    PyObject_Free(seq->s_instrs);\n    seq->s_instrs = NULL;\n}\n\nstatic int\ninstr_sequence_to_cfg(instr_sequence *seq, cfg_builder *g) {\n    memset(g, 0, sizeof(cfg_builder));\n    RETURN_IF_ERROR(_PyCfgBuilder_Init(g));\n\n    /* There can be more than one label for the same offset. The\n     * offset2lbl maping selects one of them which we use consistently.\n     */\n\n    int *offset2lbl = PyMem_Malloc(seq->s_used * sizeof(int));\n    if (offset2lbl == NULL) {\n        PyErr_NoMemory();\n        return ERROR;\n    }\n    for (int i = 0; i < seq->s_used; i++) {\n        offset2lbl[i] = -1;\n    }\n    for (int lbl=0; lbl < seq->s_labelmap_size; lbl++) {\n        int offset = seq->s_labelmap[lbl];\n        if (offset >= 0) {\n            assert(offset < seq->s_used);\n            offset2lbl[offset] = lbl;\n        }\n    }\n\n    for (int i = 0; i < seq->s_used; i++) {\n        int lbl = offset2lbl[i];\n        if (lbl >= 0) {\n            assert (lbl < seq->s_labelmap_size);\n            jump_target_label lbl_ = {lbl};\n            if (_PyCfgBuilder_UseLabel(g, lbl_) < 0) {\n                goto error;\n            }\n        }\n        instruction *instr = &seq->s_instrs[i];\n        int opcode = instr->i_opcode;\n        int oparg = instr->i_oparg;\n        if (HAS_TARGET(opcode)) {\n            int offset = seq->s_labelmap[oparg];\n            assert(offset >= 0 && offset < seq->s_used);\n            int lbl = offset2lbl[offset];\n            assert(lbl >= 0 && lbl < seq->s_labelmap_size);\n            oparg = lbl;\n        }\n        if (_PyCfgBuilder_Addop(g, opcode, oparg, instr->i_loc) < 0) {\n            goto error;\n        }\n    }\n    PyMem_Free(offset2lbl);\n\n    int nblocks = 0;\n    for (basicblock *b = g->g_block_list; b != NULL; b = b->b_list) {\n        nblocks++;\n    }\n    if ((size_t)nblocks > SIZE_MAX / sizeof(basicblock *)) {\n        PyErr_NoMemory();\n        return ERROR;\n    }\n    return SUCCESS;\nerror:\n    PyMem_Free(offset2lbl);\n    return ERROR;\n}\n\n\n/* The following items change on entry and exit of code blocks.\n   They must be saved and restored when returning to a block.\n*/\nstruct compiler_unit {\n    PySTEntryObject *u_ste;\n\n    int u_scope_type;\n\n    PyObject *u_private;        /* for private name mangling */\n\n    instr_sequence u_instr_sequence; /* codegen output */\n\n    int u_nfblocks;\n    int u_in_inlined_comp;\n\n    struct fblockinfo u_fblock[CO_MAXBLOCKS];\n\n    _PyCompile_CodeUnitMetadata u_metadata;\n};\n\n/* This struct captures the global state of a compilation.\n\nThe u pointer points to the current compilation unit, while units\nfor enclosing blocks are stored in c_stack.     The u and c_stack are\nmanaged by compiler_enter_scope() and compiler_exit_scope().\n\nNote that we don't track recursion levels during compilation - the\ntask of detecting and rejecting excessive levels of nesting is\nhandled by the symbol analysis pass.\n\n*/\n\nstruct compiler {\n    PyObject *c_filename;\n    struct symtable *c_st;\n    PyFutureFeatures c_future;   /* module's __future__ */\n    PyCompilerFlags c_flags;\n\n    int c_optimize;              /* optimization level */\n    int c_interactive;           /* true if in interactive mode */\n    int c_nestlevel;\n    PyObject *c_const_cache;     /* Python dict holding all constants,\n                                    including names tuple */\n    struct compiler_unit *u; /* compiler state for current block */\n    PyObject *c_stack;           /* Python list holding compiler_unit ptrs */\n    PyArena *c_arena;            /* pointer to memory allocation arena */\n};\n\n#define INSTR_SEQUENCE(C) (&((C)->u->u_instr_sequence))\n\n\ntypedef struct {\n    // A list of strings corresponding to name captures. It is used to track:\n    // - Repeated name assignments in the same pattern.\n    // - Different name assignments in alternatives.\n    // - The order of name assignments in alternatives.\n    PyObject *stores;\n    // If 0, any name captures against our subject will raise.\n    int allow_irrefutable;\n    // An array of blocks to jump to on failure. Jumping to fail_pop[i] will pop\n    // i items off of the stack. The end result looks like this (with each block\n    // falling through to the next):\n    // fail_pop[4]: POP_TOP\n    // fail_pop[3]: POP_TOP\n    // fail_pop[2]: POP_TOP\n    // fail_pop[1]: POP_TOP\n    // fail_pop[0]: NOP\n    jump_target_label *fail_pop;\n    // The current length of fail_pop.\n    Py_ssize_t fail_pop_size;\n    // The number of items on top of the stack that need to *stay* on top of the\n    // stack. Variable captures go beneath these. All of them will be popped on\n    // failure.\n    Py_ssize_t on_top;\n} pattern_context;\n\nstatic int codegen_addop_i(instr_sequence *seq, int opcode, Py_ssize_t oparg, location loc);\n\nstatic void compiler_free(struct compiler *);\nstatic int compiler_error(struct compiler *, location loc, const char *, ...);\nstatic int compiler_warn(struct compiler *, location loc, const char *, ...);\nstatic int compiler_nameop(struct compiler *, location, identifier, expr_context_ty);\n\nstatic PyCodeObject *compiler_mod(struct compiler *, mod_ty);\nstatic int compiler_visit_stmt(struct compiler *, stmt_ty);\nstatic int compiler_visit_keyword(struct compiler *, keyword_ty);\nstatic int compiler_visit_expr(struct compiler *, expr_ty);\nstatic int compiler_augassign(struct compiler *, stmt_ty);\nstatic int compiler_annassign(struct compiler *, stmt_ty);\nstatic int compiler_subscript(struct compiler *, expr_ty);\nstatic int compiler_slice(struct compiler *, expr_ty);\n\nstatic bool are_all_items_const(asdl_expr_seq *, Py_ssize_t, Py_ssize_t);\n\n\nstatic int compiler_with(struct compiler *, stmt_ty, int);\nstatic int compiler_async_with(struct compiler *, stmt_ty, int);\nstatic int compiler_async_for(struct compiler *, stmt_ty);\nstatic int compiler_call_simple_kw_helper(struct compiler *c,\n                                          location loc,\n                                          asdl_keyword_seq *keywords,\n                                          Py_ssize_t nkwelts);\nstatic int compiler_call_helper(struct compiler *c, location loc,\n                                int n, asdl_expr_seq *args,\n                                asdl_keyword_seq *keywords);\nstatic int compiler_try_except(struct compiler *, stmt_ty);\nstatic int compiler_try_star_except(struct compiler *, stmt_ty);\nstatic int compiler_set_qualname(struct compiler *);\n\nstatic int compiler_sync_comprehension_generator(\n                                      struct compiler *c, location loc,\n                                      asdl_comprehension_seq *generators, int gen_index,\n                                      int depth,\n                                      expr_ty elt, expr_ty val, int type,\n                                      int iter_on_stack);\n\nstatic int compiler_async_comprehension_generator(\n                                      struct compiler *c, location loc,\n                                      asdl_comprehension_seq *generators, int gen_index,\n                                      int depth,\n                                      expr_ty elt, expr_ty val, int type,\n                                      int iter_on_stack);\n\nstatic int compiler_pattern(struct compiler *, pattern_ty, pattern_context *);\nstatic int compiler_match(struct compiler *, stmt_ty);\nstatic int compiler_pattern_subpattern(struct compiler *,\n                                       pattern_ty, pattern_context *);\n\nstatic PyCodeObject *optimize_and_assemble(struct compiler *, int addNone);\n\n#define CAPSULE_NAME \"compile.c compiler unit\"\n\n\nstatic int\ncompiler_setup(struct compiler *c, mod_ty mod, PyObject *filename,\n               PyCompilerFlags flags, int optimize, PyArena *arena)\n{\n    c->c_const_cache = PyDict_New();\n    if (!c->c_const_cache) {\n        return ERROR;\n    }\n\n    c->c_stack = PyList_New(0);\n    if (!c->c_stack) {\n        return ERROR;\n    }\n\n    c->c_filename = Py_NewRef(filename);\n    c->c_arena = arena;\n    if (!_PyFuture_FromAST(mod, filename, &c->c_future)) {\n        return ERROR;\n    }\n    int merged = c->c_future.ff_features | flags.cf_flags;\n    c->c_future.ff_features = merged;\n    flags.cf_flags = merged;\n    c->c_flags = flags;\n    c->c_optimize = (optimize == -1) ? _Py_GetConfig()->optimization_level : optimize;\n    c->c_nestlevel = 0;\n\n    if (!_PyAST_Optimize(mod, arena, c->c_optimize, merged)) {\n        return ERROR;\n    }\n    c->c_st = _PySymtable_Build(mod, filename, &c->c_future);\n    if (c->c_st == NULL) {\n        if (!PyErr_Occurred()) {\n            PyErr_SetString(PyExc_SystemError, \"no symtable\");\n        }\n        return ERROR;\n    }\n    return SUCCESS;\n}\n\nstatic struct compiler*\nnew_compiler(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,\n             int optimize, PyArena *arena)\n{\n    PyCompilerFlags flags = pflags ? *pflags : _PyCompilerFlags_INIT;\n    struct compiler *c = PyMem_Calloc(1, sizeof(struct compiler));\n    if (c == NULL) {\n        return NULL;\n    }\n    if (compiler_setup(c, mod, filename, flags, optimize, arena) < 0) {\n        compiler_free(c);\n        return NULL;\n    }\n    return c;\n}\n\nPyCodeObject *\n_PyAST_Compile(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,\n               int optimize, PyArena *arena)\n{\n    assert(!PyErr_Occurred());\n    struct compiler *c = new_compiler(mod, filename, pflags, optimize, arena);\n    if (c == NULL) {\n        return NULL;\n    }\n\n    PyCodeObject *co = compiler_mod(c, mod);\n    compiler_free(c);\n    assert(co || PyErr_Occurred());\n    return co;\n}\n\nstatic void\ncompiler_free(struct compiler *c)\n{\n    if (c->c_st)\n        _PySymtable_Free(c->c_st);\n    Py_XDECREF(c->c_filename);\n    Py_XDECREF(c->c_const_cache);\n    Py_XDECREF(c->c_stack);\n    PyMem_Free(c);\n}\n\nstatic PyObject *\nlist2dict(PyObject *list)\n{\n    Py_ssize_t i, n;\n    PyObject *v, *k;\n    PyObject *dict = PyDict_New();\n    if (!dict) return NULL;\n\n    n = PyList_Size(list);\n    for (i = 0; i < n; i++) {\n        v = PyLong_FromSsize_t(i);\n        if (!v) {\n            Py_DECREF(dict);\n            return NULL;\n        }\n        k = PyList_GET_ITEM(list, i);\n        if (PyDict_SetItem(dict, k, v) < 0) {\n            Py_DECREF(v);\n            Py_DECREF(dict);\n            return NULL;\n        }\n        Py_DECREF(v);\n    }\n    return dict;\n}\n\n/* Return new dict containing names from src that match scope(s).\n\nsrc is a symbol table dictionary.  If the scope of a name matches\neither scope_type or flag is set, insert it into the new dict.  The\nvalues are integers, starting at offset and increasing by one for\neach key.\n*/\n\nstatic PyObject *\ndictbytype(PyObject *src, int scope_type, int flag, Py_ssize_t offset)\n{\n    Py_ssize_t i = offset, scope, num_keys, key_i;\n    PyObject *k, *v, *dest = PyDict_New();\n    PyObject *sorted_keys;\n\n    assert(offset >= 0);\n    if (dest == NULL)\n        return NULL;\n\n    /* Sort the keys so that we have a deterministic order on the indexes\n       saved in the returned dictionary.  These indexes are used as indexes\n       into the free and cell var storage.  Therefore if they aren't\n       deterministic, then the generated bytecode is not deterministic.\n    */\n    sorted_keys = PyDict_Keys(src);\n    if (sorted_keys == NULL)\n        return NULL;\n    if (PyList_Sort(sorted_keys) != 0) {\n        Py_DECREF(sorted_keys);\n        return NULL;\n    }\n    num_keys = PyList_GET_SIZE(sorted_keys);\n\n    for (key_i = 0; key_i < num_keys; key_i++) {\n        /* XXX this should probably be a macro in symtable.h */\n        long vi;\n        k = PyList_GET_ITEM(sorted_keys, key_i);\n        v = PyDict_GetItemWithError(src, k);\n        assert(v && PyLong_Check(v));\n        vi = PyLong_AS_LONG(v);\n        scope = (vi >> SCOPE_OFFSET) & SCOPE_MASK;\n\n        if (scope == scope_type || vi & flag) {\n            PyObject *item = PyLong_FromSsize_t(i);\n            if (item == NULL) {\n                Py_DECREF(sorted_keys);\n                Py_DECREF(dest);\n                return NULL;\n            }\n            i++;\n            if (PyDict_SetItem(dest, k, item) < 0) {\n                Py_DECREF(sorted_keys);\n                Py_DECREF(item);\n                Py_DECREF(dest);\n                return NULL;\n            }\n            Py_DECREF(item);\n        }\n    }\n    Py_DECREF(sorted_keys);\n    return dest;\n}\n\nstatic void\ncompiler_unit_free(struct compiler_unit *u)\n{\n    instr_sequence_fini(&u->u_instr_sequence);\n    Py_CLEAR(u->u_ste);\n    Py_CLEAR(u->u_metadata.u_name);\n    Py_CLEAR(u->u_metadata.u_qualname);\n    Py_CLEAR(u->u_metadata.u_consts);\n    Py_CLEAR(u->u_metadata.u_names);\n    Py_CLEAR(u->u_metadata.u_varnames);\n    Py_CLEAR(u->u_metadata.u_freevars);\n    Py_CLEAR(u->u_metadata.u_cellvars);\n    Py_CLEAR(u->u_metadata.u_fasthidden);\n    Py_CLEAR(u->u_private);\n    PyObject_Free(u);\n}\n\nstatic int\ncompiler_set_qualname(struct compiler *c)\n{\n    Py_ssize_t stack_size;\n    struct compiler_unit *u = c->u;\n    PyObject *name, *base;\n\n    base = NULL;\n    stack_size = PyList_GET_SIZE(c->c_stack);\n    assert(stack_size >= 1);\n    if (stack_size > 1) {\n        int scope, force_global = 0;\n        struct compiler_unit *parent;\n        PyObject *mangled, *capsule;\n\n        capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1);\n        parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME);\n        assert(parent);\n        if (parent->u_scope_type == COMPILER_SCOPE_TYPEPARAMS) {\n            /* The parent is a type parameter scope, so we need to\n               look at the grandparent. */\n            if (stack_size == 2) {\n                // If we're immediately within the module, we can skip\n                // the rest and just set the qualname to be the same as name.\n                u->u_metadata.u_qualname = Py_NewRef(u->u_metadata.u_name);\n                return SUCCESS;\n            }\n            capsule = PyList_GET_ITEM(c->c_stack, stack_size - 2);\n            parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME);\n            assert(parent);\n        }\n\n        if (u->u_scope_type == COMPILER_SCOPE_FUNCTION\n            || u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION\n            || u->u_scope_type == COMPILER_SCOPE_CLASS) {\n            assert(u->u_metadata.u_name);\n            mangled = _Py_Mangle(parent->u_private, u->u_metadata.u_name);\n            if (!mangled) {\n                return ERROR;\n            }\n\n            scope = _PyST_GetScope(parent->u_ste, mangled);\n            Py_DECREF(mangled);\n            assert(scope != GLOBAL_IMPLICIT);\n            if (scope == GLOBAL_EXPLICIT)\n                force_global = 1;\n        }\n\n        if (!force_global) {\n            if (parent->u_scope_type == COMPILER_SCOPE_FUNCTION\n                || parent->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION\n                || parent->u_scope_type == COMPILER_SCOPE_LAMBDA)\n            {\n                _Py_DECLARE_STR(dot_locals, \".<locals>\");\n                base = PyUnicode_Concat(parent->u_metadata.u_qualname,\n                                        &_Py_STR(dot_locals));\n                if (base == NULL) {\n                    return ERROR;\n                }\n            }\n            else {\n                base = Py_NewRef(parent->u_metadata.u_qualname);\n            }\n        }\n    }\n\n    if (base != NULL) {\n        _Py_DECLARE_STR(dot, \".\");\n        name = PyUnicode_Concat(base, &_Py_STR(dot));\n        Py_DECREF(base);\n        if (name == NULL) {\n            return ERROR;\n        }\n        PyUnicode_Append(&name, u->u_metadata.u_name);\n        if (name == NULL) {\n            return ERROR;\n        }\n    }\n    else {\n        name = Py_NewRef(u->u_metadata.u_name);\n    }\n    u->u_metadata.u_qualname = name;\n\n    return SUCCESS;\n}\n\n/* Return the stack effect of opcode with argument oparg.\n\n   Some opcodes have different stack effect when jump to the target and\n   when not jump. The 'jump' parameter specifies the case:\n\n   * 0 -- when not jump\n   * 1 -- when jump\n   * -1 -- maximal\n */\nstatic int\nstack_effect(int opcode, int oparg, int jump)\n{\n    if (0 <= opcode && opcode <= MAX_REAL_OPCODE) {\n        if (_PyOpcode_Deopt[opcode] != opcode) {\n            // Specialized instructions are not supported.\n            return PY_INVALID_STACK_EFFECT;\n        }\n        int popped, pushed;\n        if (jump > 0) {\n            popped = _PyOpcode_num_popped(opcode, oparg, true);\n            pushed = _PyOpcode_num_pushed(opcode, oparg, true);\n        }\n        else {\n            popped = _PyOpcode_num_popped(opcode, oparg, false);\n            pushed = _PyOpcode_num_pushed(opcode, oparg, false);\n        }\n        if (popped < 0 || pushed < 0) {\n            return PY_INVALID_STACK_EFFECT;\n        }\n        if (jump >= 0) {\n            return pushed - popped;\n        }\n        if (jump < 0) {\n            // Compute max(pushed - popped, alt_pushed - alt_popped)\n            int alt_popped = _PyOpcode_num_popped(opcode, oparg, true);\n            int alt_pushed = _PyOpcode_num_pushed(opcode, oparg, true);\n            if (alt_popped < 0 || alt_pushed < 0) {\n                return PY_INVALID_STACK_EFFECT;\n            }\n            int diff = pushed - popped;\n            int alt_diff = alt_pushed - alt_popped;\n            if (alt_diff > diff) {\n                return alt_diff;\n            }\n            return diff;\n        }\n    }\n\n    // Pseudo ops\n    switch (opcode) {\n        case POP_BLOCK:\n        case JUMP:\n        case JUMP_NO_INTERRUPT:\n            return 0;\n\n        /* Exception handling pseudo-instructions */\n        case SETUP_FINALLY:\n            /* 0 in the normal flow.\n             * Restore the stack position and push 1 value before jumping to\n             * the handler if an exception be raised. */\n            return jump ? 1 : 0;\n        case SETUP_CLEANUP:\n            /* As SETUP_FINALLY, but pushes lasti as well */\n            return jump ? 2 : 0;\n        case SETUP_WITH:\n            /* 0 in the normal flow.\n             * Restore the stack position to the position before the result\n             * of __(a)enter__ and push 2 values before jumping to the handler\n             * if an exception be raised. */\n            return jump ? 1 : 0;\n\n        case STORE_FAST_MAYBE_NULL:\n            return -1;\n        case LOAD_METHOD:\n            return 1;\n        case LOAD_SUPER_METHOD:\n        case LOAD_ZERO_SUPER_METHOD:\n        case LOAD_ZERO_SUPER_ATTR:\n            return -1;\n        default:\n            return PY_INVALID_STACK_EFFECT;\n    }\n\n    return PY_INVALID_STACK_EFFECT; /* not reachable */\n}\n\nint\nPyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump)\n{\n    return stack_effect(opcode, oparg, jump);\n}\n\nint\nPyCompile_OpcodeStackEffect(int opcode, int oparg)\n{\n    return stack_effect(opcode, oparg, -1);\n}\n\nstatic int\ncodegen_addop_noarg(instr_sequence *seq, int opcode, location loc)\n{\n    assert(!HAS_ARG(opcode));\n    assert(!IS_ASSEMBLER_OPCODE(opcode));\n    return instr_sequence_addop(seq, opcode, 0, loc);\n}\n\nstatic Py_ssize_t\ndict_add_o(PyObject *dict, PyObject *o)\n{\n    PyObject *v;\n    Py_ssize_t arg;\n\n    v = PyDict_GetItemWithError(dict, o);\n    if (!v) {\n        if (PyErr_Occurred()) {\n            return ERROR;\n        }\n        arg = PyDict_GET_SIZE(dict);\n        v = PyLong_FromSsize_t(arg);\n        if (!v) {\n            return ERROR;\n        }\n        if (PyDict_SetItem(dict, o, v) < 0) {\n            Py_DECREF(v);\n            return ERROR;\n        }\n        Py_DECREF(v);\n    }\n    else\n        arg = PyLong_AsLong(v);\n    return arg;\n}\n\n// Merge const *o* recursively and return constant key object.\nstatic PyObject*\nmerge_consts_recursive(PyObject *const_cache, PyObject *o)\n{\n    assert(PyDict_CheckExact(const_cache));\n    // None and Ellipsis are immortal objects, and key is the singleton.\n    // No need to merge object and key.\n    if (o == Py_None || o == Py_Ellipsis) {\n        return o;\n    }\n\n    PyObject *key = _PyCode_ConstantKey(o);\n    if (key == NULL) {\n        return NULL;\n    }\n\n    // t is borrowed reference\n    PyObject *t = PyDict_SetDefault(const_cache, key, key);\n    if (t != key) {\n        // o is registered in const_cache.  Just use it.\n        Py_XINCREF(t);\n        Py_DECREF(key);\n        return t;\n    }\n\n    // We registered o in const_cache.\n    // When o is a tuple or frozenset, we want to merge its\n    // items too.\n    if (PyTuple_CheckExact(o)) {\n        Py_ssize_t len = PyTuple_GET_SIZE(o);\n        for (Py_ssize_t i = 0; i < len; i++) {\n            PyObject *item = PyTuple_GET_ITEM(o, i);\n            PyObject *u = merge_consts_recursive(const_cache, item);\n            if (u == NULL) {\n                Py_DECREF(key);\n                return NULL;\n            }\n\n            // See _PyCode_ConstantKey()\n            PyObject *v;  // borrowed\n            if (PyTuple_CheckExact(u)) {\n                v = PyTuple_GET_ITEM(u, 1);\n            }\n            else {\n                v = u;\n            }\n            if (v != item) {\n                PyTuple_SET_ITEM(o, i, Py_NewRef(v));\n                Py_DECREF(item);\n            }\n\n            Py_DECREF(u);\n        }\n    }\n    else if (PyFrozenSet_CheckExact(o)) {\n        // *key* is tuple. And its first item is frozenset of\n        // constant keys.\n        // See _PyCode_ConstantKey() for detail.\n        assert(PyTuple_CheckExact(key));\n        assert(PyTuple_GET_SIZE(key) == 2);\n\n        Py_ssize_t len = PySet_GET_SIZE(o);\n        if (len == 0) {  // empty frozenset should not be re-created.\n            return key;\n        }\n        PyObject *tuple = PyTuple_New(len);\n        if (tuple == NULL) {\n            Py_DECREF(key);\n            return NULL;\n        }\n        Py_ssize_t i = 0, pos = 0;\n        PyObject *item;\n        Py_hash_t hash;\n        while (_PySet_NextEntry(o, &pos, &item, &hash)) {\n            PyObject *k = merge_consts_recursive(const_cache, item);\n            if (k == NULL) {\n                Py_DECREF(tuple);\n                Py_DECREF(key);\n                return NULL;\n            }\n            PyObject *u;\n            if (PyTuple_CheckExact(k)) {\n                u = Py_NewRef(PyTuple_GET_ITEM(k, 1));\n                Py_DECREF(k);\n            }\n            else {\n                u = k;\n            }\n            PyTuple_SET_ITEM(tuple, i, u);  // Steals reference of u.\n            i++;\n        }\n\n        // Instead of rewriting o, we create new frozenset and embed in the\n        // key tuple.  Caller should get merged frozenset from the key tuple.\n        PyObject *new = PyFrozenSet_New(tuple);\n        Py_DECREF(tuple);\n        if (new == NULL) {\n            Py_DECREF(key);\n            return NULL;\n        }\n        assert(PyTuple_GET_ITEM(key, 1) == o);\n        Py_DECREF(o);\n        PyTuple_SET_ITEM(key, 1, new);\n    }\n\n    return key;\n}\n\nstatic Py_ssize_t\ncompiler_add_const(PyObject *const_cache, struct compiler_unit *u, PyObject *o)\n{\n    assert(PyDict_CheckExact(const_cache));\n    PyObject *key = merge_consts_recursive(const_cache, o);\n    if (key == NULL) {\n        return ERROR;\n    }\n\n    Py_ssize_t arg = dict_add_o(u->u_metadata.u_consts, key);\n    Py_DECREF(key);\n    return arg;\n}\n\nstatic int\ncompiler_addop_load_const(PyObject *const_cache, struct compiler_unit *u, location loc, PyObject *o)\n{\n    Py_ssize_t arg = compiler_add_const(const_cache, u, o);\n    if (arg < 0) {\n        return ERROR;\n    }\n    return codegen_addop_i(&u->u_instr_sequence, LOAD_CONST, arg, loc);\n}\n\nstatic int\ncompiler_addop_o(struct compiler_unit *u, location loc,\n                 int opcode, PyObject *dict, PyObject *o)\n{\n    Py_ssize_t arg = dict_add_o(dict, o);\n    if (arg < 0) {\n        return ERROR;\n    }\n    return codegen_addop_i(&u->u_instr_sequence, opcode, arg, loc);\n}\n\nstatic int\ncompiler_addop_name(struct compiler_unit *u, location loc,\n                    int opcode, PyObject *dict, PyObject *o)\n{\n    PyObject *mangled = _Py_Mangle(u->u_private, o);\n    if (!mangled) {\n        return ERROR;\n    }\n    Py_ssize_t arg = dict_add_o(dict, mangled);\n    Py_DECREF(mangled);\n    if (arg < 0) {\n        return ERROR;\n    }\n    if (opcode == LOAD_ATTR) {\n        arg <<= 1;\n    }\n    if (opcode == LOAD_METHOD) {\n        opcode = LOAD_ATTR;\n        arg <<= 1;\n        arg |= 1;\n    }\n    if (opcode == LOAD_SUPER_ATTR) {\n        arg <<= 2;\n        arg |= 2;\n    }\n    if (opcode == LOAD_SUPER_METHOD) {\n        opcode = LOAD_SUPER_ATTR;\n        arg <<= 2;\n        arg |= 3;\n    }\n    if (opcode == LOAD_ZERO_SUPER_ATTR) {\n        opcode = LOAD_SUPER_ATTR;\n        arg <<= 2;\n    }\n    if (opcode == LOAD_ZERO_SUPER_METHOD) {\n        opcode = LOAD_SUPER_ATTR;\n        arg <<= 2;\n        arg |= 1;\n    }\n    return codegen_addop_i(&u->u_instr_sequence, opcode, arg, loc);\n}\n\n/* Add an opcode with an integer argument */\nstatic int\ncodegen_addop_i(instr_sequence *seq, int opcode, Py_ssize_t oparg, location loc)\n{\n    /* oparg value is unsigned, but a signed C int is usually used to store\n       it in the C code (like Python/ceval.c).\n\n       Limit to 32-bit signed C int (rather than INT_MAX) for portability.\n\n       The argument of a concrete bytecode instruction is limited to 8-bit.\n       EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */\n\n    int oparg_ = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int);\n    assert(!IS_ASSEMBLER_OPCODE(opcode));\n    return instr_sequence_addop(seq, opcode, oparg_, loc);\n}\n\nstatic int\ncodegen_addop_j(instr_sequence *seq, location loc,\n                int opcode, jump_target_label target)\n{\n    assert(IS_LABEL(target));\n    assert(IS_JUMP_OPCODE(opcode) || IS_BLOCK_PUSH_OPCODE(opcode));\n    assert(!IS_ASSEMBLER_OPCODE(opcode));\n    return instr_sequence_addop(seq, opcode, target.id, loc);\n}\n\n#define RETURN_IF_ERROR_IN_SCOPE(C, CALL) { \\\n    if ((CALL) < 0) { \\\n        compiler_exit_scope((C)); \\\n        return ERROR; \\\n    } \\\n}\n\n#define ADDOP(C, LOC, OP) \\\n    RETURN_IF_ERROR(codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))\n\n#define ADDOP_IN_SCOPE(C, LOC, OP) RETURN_IF_ERROR_IN_SCOPE((C), codegen_addop_noarg(INSTR_SEQUENCE(C), (OP), (LOC)))\n\n#define ADDOP_LOAD_CONST(C, LOC, O) \\\n    RETURN_IF_ERROR(compiler_addop_load_const((C)->c_const_cache, (C)->u, (LOC), (O)))\n\n/* Same as ADDOP_LOAD_CONST, but steals a reference. */\n#define ADDOP_LOAD_CONST_NEW(C, LOC, O) { \\\n    PyObject *__new_const = (O); \\\n    if (__new_const == NULL) { \\\n        return ERROR; \\\n    } \\\n    if (compiler_addop_load_const((C)->c_const_cache, (C)->u, (LOC), __new_const) < 0) { \\\n        Py_DECREF(__new_const); \\\n        return ERROR; \\\n    } \\\n    Py_DECREF(__new_const); \\\n}\n\n#define ADDOP_N(C, LOC, OP, O, TYPE) { \\\n    assert(!HAS_CONST(OP)); /* use ADDOP_LOAD_CONST_NEW */ \\\n    if (compiler_addop_o((C)->u, (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)) < 0) { \\\n        Py_DECREF((O)); \\\n        return ERROR; \\\n    } \\\n    Py_DECREF((O)); \\\n}\n\n#define ADDOP_NAME(C, LOC, OP, O, TYPE) \\\n    RETURN_IF_ERROR(compiler_addop_name((C)->u, (LOC), (OP), (C)->u->u_metadata.u_ ## TYPE, (O)))\n\n#define ADDOP_I(C, LOC, OP, O) \\\n    RETURN_IF_ERROR(codegen_addop_i(INSTR_SEQUENCE(C), (OP), (O), (LOC)))\n\n#define ADDOP_JUMP(C, LOC, OP, O) \\\n    RETURN_IF_ERROR(codegen_addop_j(INSTR_SEQUENCE(C), (LOC), (OP), (O)))\n\n#define ADDOP_COMPARE(C, LOC, CMP) \\\n    RETURN_IF_ERROR(compiler_addcompare((C), (LOC), (cmpop_ty)(CMP)))\n\n#define ADDOP_BINARY(C, LOC, BINOP) \\\n    RETURN_IF_ERROR(addop_binary((C), (LOC), (BINOP), false))\n\n#define ADDOP_INPLACE(C, LOC, BINOP) \\\n    RETURN_IF_ERROR(addop_binary((C), (LOC), (BINOP), true))\n\n#define ADD_YIELD_FROM(C, LOC, await) \\\n    RETURN_IF_ERROR(compiler_add_yield_from((C), (LOC), (await)))\n\n#define POP_EXCEPT_AND_RERAISE(C, LOC) \\\n    RETURN_IF_ERROR(compiler_pop_except_and_reraise((C), (LOC)))\n\n#define ADDOP_YIELD(C, LOC) \\\n    RETURN_IF_ERROR(addop_yield((C), (LOC)))\n\n/* VISIT and VISIT_SEQ takes an ASDL type as their second argument.  They use\n   the ASDL name to synthesize the name of the C type and the visit function.\n*/\n\n#define VISIT(C, TYPE, V) \\\n    RETURN_IF_ERROR(compiler_visit_ ## TYPE((C), (V)));\n\n#define VISIT_IN_SCOPE(C, TYPE, V) \\\n    RETURN_IF_ERROR_IN_SCOPE((C), compiler_visit_ ## TYPE((C), (V)))\n\n#define VISIT_SEQ(C, TYPE, SEQ) { \\\n    int _i; \\\n    asdl_ ## TYPE ## _seq *seq = (SEQ); /* avoid variable capture */ \\\n    for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \\\n        TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \\\n        RETURN_IF_ERROR(compiler_visit_ ## TYPE((C), elt)); \\\n    } \\\n}\n\n#define VISIT_SEQ_IN_SCOPE(C, TYPE, SEQ) { \\\n    int _i; \\\n    asdl_ ## TYPE ## _seq *seq = (SEQ); /* avoid variable capture */ \\\n    for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \\\n        TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \\\n        if (compiler_visit_ ## TYPE((C), elt) < 0) { \\\n            compiler_exit_scope(C); \\\n            return ERROR; \\\n        } \\\n    } \\\n}\n\n\nstatic int\ncompiler_enter_scope(struct compiler *c, identifier name,\n                     int scope_type, void *key, int lineno)\n{\n    location loc = LOCATION(lineno, lineno, 0, 0);\n\n    struct compiler_unit *u;\n\n    u = (struct compiler_unit *)PyObject_Calloc(1, sizeof(\n                                            struct compiler_unit));\n    if (!u) {\n        PyErr_NoMemory();\n        return ERROR;\n    }\n    u->u_scope_type = scope_type;\n    u->u_metadata.u_argcount = 0;\n    u->u_metadata.u_posonlyargcount = 0;\n    u->u_metadata.u_kwonlyargcount = 0;\n    u->u_ste = PySymtable_Lookup(c->c_st, key);\n    if (!u->u_ste) {\n        compiler_unit_free(u);\n        return ERROR;\n    }\n    u->u_metadata.u_name = Py_NewRef(name);\n    u->u_metadata.u_varnames = list2dict(u->u_ste->ste_varnames);\n    if (!u->u_metadata.u_varnames) {\n        compiler_unit_free(u);\n        return ERROR;\n    }\n    u->u_metadata.u_cellvars = dictbytype(u->u_ste->ste_symbols, CELL, DEF_COMP_CELL, 0);\n    if (!u->u_metadata.u_cellvars) {\n        compiler_unit_free(u);\n        return ERROR;\n    }\n    if (u->u_ste->ste_needs_class_closure) {\n        /* Cook up an implicit __class__ cell. */\n        Py_ssize_t res;\n        assert(u->u_scope_type == COMPILER_SCOPE_CLASS);\n        res = dict_add_o(u->u_metadata.u_cellvars, &_Py_ID(__class__));\n        if (res < 0) {\n            compiler_unit_free(u);\n            return ERROR;\n        }\n    }\n    if (u->u_ste->ste_needs_classdict) {\n        /* Cook up an implicit __classdict__ cell. */\n        Py_ssize_t res;\n        assert(u->u_scope_type == COMPILER_SCOPE_CLASS);\n        res = dict_add_o(u->u_metadata.u_cellvars, &_Py_ID(__classdict__));\n        if (res < 0) {\n            compiler_unit_free(u);\n            return ERROR;\n        }\n    }\n\n    u->u_metadata.u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS,\n                               PyDict_GET_SIZE(u->u_metadata.u_cellvars));\n    if (!u->u_metadata.u_freevars) {\n        compiler_unit_free(u);\n        return ERROR;\n    }\n\n    u->u_metadata.u_fasthidden = PyDict_New();\n    if (!u->u_metadata.u_fasthidden) {\n        compiler_unit_free(u);\n        return ERROR;\n    }\n\n    u->u_nfblocks = 0;\n    u->u_in_inlined_comp = 0;\n    u->u_metadata.u_firstlineno = lineno;\n    u->u_metadata.u_consts = PyDict_New();\n    if (!u->u_metadata.u_consts) {\n        compiler_unit_free(u);\n        return ERROR;\n    }\n    u->u_metadata.u_names = PyDict_New();\n    if (!u->u_metadata.u_names) {\n        compiler_unit_free(u);\n        return ERROR;\n    }\n\n    u->u_private = NULL;\n\n    /* Push the old compiler_unit on the stack. */\n    if (c->u) {\n        PyObject *capsule = PyCapsule_New(c->u, CAPSULE_NAME, NULL);\n        if (!capsule || PyList_Append(c->c_stack, capsule) < 0) {\n            Py_XDECREF(capsule);\n            compiler_unit_free(u);\n            return ERROR;\n        }\n        Py_DECREF(capsule);\n        u->u_private = Py_XNewRef(c->u->u_private);\n    }\n    c->u = u;\n\n    c->c_nestlevel++;\n\n    if (u->u_scope_type == COMPILER_SCOPE_MODULE) {\n        loc.lineno = 0;\n    }\n    else {\n        RETURN_IF_ERROR(compiler_set_qualname(c));\n    }\n    ADDOP_I(c, loc, RESUME, 0);\n\n    if (u->u_scope_type == COMPILER_SCOPE_MODULE) {\n        loc.lineno = -1;\n    }\n    return SUCCESS;\n}\n\nstatic void\ncompiler_exit_scope(struct compiler *c)\n{\n    // Don't call PySequence_DelItem() with an exception raised\n    PyObject *exc = PyErr_GetRaisedException();\n\n    c->c_nestlevel--;\n    compiler_unit_free(c->u);\n    /* Restore c->u to the parent unit. */\n    Py_ssize_t n = PyList_GET_SIZE(c->c_stack) - 1;\n    if (n >= 0) {\n        PyObject *capsule = PyList_GET_ITEM(c->c_stack, n);\n        c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME);\n        assert(c->u);\n        /* we are deleting from a list so this really shouldn't fail */\n        if (PySequence_DelItem(c->c_stack, n) < 0) {\n            _PyErr_WriteUnraisableMsg(\"on removing the last compiler \"\n                                      \"stack item\", NULL);\n        }\n    }\n    else {\n        c->u = NULL;\n    }\n\n    PyErr_SetRaisedException(exc);\n}\n\n/* Search if variable annotations are present statically in a block. */\n\nstatic bool\nfind_ann(asdl_stmt_seq *stmts)\n{\n    int i, j, res = 0;\n    stmt_ty st;\n\n    for (i = 0; i < asdl_seq_LEN(stmts); i++) {\n        st = (stmt_ty)asdl_seq_GET(stmts, i);\n        switch (st->kind) {\n        case AnnAssign_kind:\n            return true;\n        case For_kind:\n            res = find_ann(st->v.For.body) ||\n                  find_ann(st->v.For.orelse);\n            break;\n        case AsyncFor_kind:\n            res = find_ann(st->v.AsyncFor.body) ||\n                  find_ann(st->v.AsyncFor.orelse);\n            break;\n        case While_kind:\n            res = find_ann(st->v.While.body) ||\n                  find_ann(st->v.While.orelse);\n            break;\n        case If_kind:\n            res = find_ann(st->v.If.body) ||\n                  find_ann(st->v.If.orelse);\n            break;\n        case With_kind:\n            res = find_ann(st->v.With.body);\n            break;\n        case AsyncWith_kind:\n            res = find_ann(st->v.AsyncWith.body);\n            break;\n        case Try_kind:\n            for (j = 0; j < asdl_seq_LEN(st->v.Try.handlers); j++) {\n                excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(\n                    st->v.Try.handlers, j);\n                if (find_ann(handler->v.ExceptHandler.body)) {\n                    return true;\n                }\n            }\n            res = find_ann(st->v.Try.body) ||\n                  find_ann(st->v.Try.finalbody) ||\n                  find_ann(st->v.Try.orelse);\n            break;\n        case TryStar_kind:\n            for (j = 0; j < asdl_seq_LEN(st->v.TryStar.handlers); j++) {\n                excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(\n                    st->v.TryStar.handlers, j);\n                if (find_ann(handler->v.ExceptHandler.body)) {\n                    return true;\n                }\n            }\n            res = find_ann(st->v.TryStar.body) ||\n                  find_ann(st->v.TryStar.finalbody) ||\n                  find_ann(st->v.TryStar.orelse);\n            break;\n        case Match_kind:\n            for (j = 0; j < asdl_seq_LEN(st->v.Match.cases); j++) {\n                match_case_ty match_case = (match_case_ty)asdl_seq_GET(\n                    st->v.Match.cases, j);\n                if (find_ann(match_case->body)) {\n                    return true;\n                }\n            }\n            break;\n        default:\n            res = false;\n            break;\n        }\n        if (res) {\n            break;\n        }\n    }\n    return res;\n}\n\n/*\n * Frame block handling functions\n */\n\nstatic int\ncompiler_push_fblock(struct compiler *c, location loc,\n                     enum fblocktype t, jump_target_label block_label,\n                     jump_target_label exit, void *datum)\n{\n    struct fblockinfo *f;\n    if (c->u->u_nfblocks >= CO_MAXBLOCKS) {\n        return compiler_error(c, loc, \"too many statically nested blocks\");\n    }\n    f = &c->u->u_fblock[c->u->u_nfblocks++];\n    f->fb_type = t;\n    f->fb_block = block_label;\n    f->fb_exit = exit;\n    f->fb_datum = datum;\n    return SUCCESS;\n}\n\nstatic void\ncompiler_pop_fblock(struct compiler *c, enum fblocktype t, jump_target_label block_label)\n{\n    struct compiler_unit *u = c->u;\n    assert(u->u_nfblocks > 0);\n    u->u_nfblocks--;\n    assert(u->u_fblock[u->u_nfblocks].fb_type == t);\n    assert(SAME_LABEL(u->u_fblock[u->u_nfblocks].fb_block, block_label));\n}\n\nstatic int\ncompiler_call_exit_with_nones(struct compiler *c, location loc)\n{\n    ADDOP_LOAD_CONST(c, loc, Py_None);\n    ADDOP_LOAD_CONST(c, loc, Py_None);\n    ADDOP_LOAD_CONST(c, loc, Py_None);\n    ADDOP_I(c, loc, CALL, 2);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_add_yield_from(struct compiler *c, location loc, int await)\n{\n    NEW_JUMP_TARGET_LABEL(c, send);\n    NEW_JUMP_TARGET_LABEL(c, fail);\n    NEW_JUMP_TARGET_LABEL(c, exit);\n\n    USE_LABEL(c, send);\n    ADDOP_JUMP(c, loc, SEND, exit);\n    // Set up a virtual try/except to handle when StopIteration is raised during\n    // a close or throw call. The only way YIELD_VALUE raises if they do!\n    ADDOP_JUMP(c, loc, SETUP_FINALLY, fail);\n    ADDOP_I(c, loc, YIELD_VALUE, 0);\n    ADDOP(c, NO_LOCATION, POP_BLOCK);\n    ADDOP_I(c, loc, RESUME, await ? 3 : 2);\n    ADDOP_JUMP(c, loc, JUMP_NO_INTERRUPT, send);\n\n    USE_LABEL(c, fail);\n    ADDOP(c, loc, CLEANUP_THROW);\n\n    USE_LABEL(c, exit);\n    ADDOP(c, loc, END_SEND);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_pop_except_and_reraise(struct compiler *c, location loc)\n{\n    /* Stack contents\n     * [exc_info, lasti, exc]            COPY        3\n     * [exc_info, lasti, exc, exc_info]  POP_EXCEPT\n     * [exc_info, lasti, exc]            RERAISE      1\n     * (exception_unwind clears the stack)\n     */\n\n    ADDOP_I(c, loc, COPY, 3);\n    ADDOP(c, loc, POP_EXCEPT);\n    ADDOP_I(c, loc, RERAISE, 1);\n    return SUCCESS;\n}\n\n/* Unwind a frame block.  If preserve_tos is true, the TOS before\n * popping the blocks will be restored afterwards, unless another\n * return, break or continue is found. In which case, the TOS will\n * be popped.\n */\nstatic int\ncompiler_unwind_fblock(struct compiler *c, location *ploc,\n                       struct fblockinfo *info, int preserve_tos)\n{\n    switch (info->fb_type) {\n        case WHILE_LOOP:\n        case EXCEPTION_HANDLER:\n        case EXCEPTION_GROUP_HANDLER:\n        case ASYNC_COMPREHENSION_GENERATOR:\n            return SUCCESS;\n\n        case FOR_LOOP:\n            /* Pop the iterator */\n            if (preserve_tos) {\n                ADDOP_I(c, *ploc, SWAP, 2);\n            }\n            ADDOP(c, *ploc, POP_TOP);\n            return SUCCESS;\n\n        case TRY_EXCEPT:\n            ADDOP(c, *ploc, POP_BLOCK);\n            return SUCCESS;\n\n        case FINALLY_TRY:\n            /* This POP_BLOCK gets the line number of the unwinding statement */\n            ADDOP(c, *ploc, POP_BLOCK);\n            if (preserve_tos) {\n                RETURN_IF_ERROR(\n                    compiler_push_fblock(c, *ploc, POP_VALUE, NO_LABEL, NO_LABEL, NULL));\n            }\n            /* Emit the finally block */\n            VISIT_SEQ(c, stmt, info->fb_datum);\n            if (preserve_tos) {\n                compiler_pop_fblock(c, POP_VALUE, NO_LABEL);\n            }\n            /* The finally block should appear to execute after the\n             * statement causing the unwinding, so make the unwinding\n             * instruction artificial */\n            *ploc = NO_LOCATION;\n            return SUCCESS;\n\n        case FINALLY_END:\n            if (preserve_tos) {\n                ADDOP_I(c, *ploc, SWAP, 2);\n            }\n            ADDOP(c, *ploc, POP_TOP); /* exc_value */\n            if (preserve_tos) {\n                ADDOP_I(c, *ploc, SWAP, 2);\n            }\n            ADDOP(c, *ploc, POP_BLOCK);\n            ADDOP(c, *ploc, POP_EXCEPT);\n            return SUCCESS;\n\n        case WITH:\n        case ASYNC_WITH:\n            *ploc = LOC((stmt_ty)info->fb_datum);\n            ADDOP(c, *ploc, POP_BLOCK);\n            if (preserve_tos) {\n                ADDOP_I(c, *ploc, SWAP, 2);\n            }\n            RETURN_IF_ERROR(compiler_call_exit_with_nones(c, *ploc));\n            if (info->fb_type == ASYNC_WITH) {\n                ADDOP_I(c, *ploc, GET_AWAITABLE, 2);\n                ADDOP_LOAD_CONST(c, *ploc, Py_None);\n                ADD_YIELD_FROM(c, *ploc, 1);\n            }\n            ADDOP(c, *ploc, POP_TOP);\n            /* The exit block should appear to execute after the\n             * statement causing the unwinding, so make the unwinding\n             * instruction artificial */\n            *ploc = NO_LOCATION;\n            return SUCCESS;\n\n        case HANDLER_CLEANUP: {\n            if (info->fb_datum) {\n                ADDOP(c, *ploc, POP_BLOCK);\n            }\n            if (preserve_tos) {\n                ADDOP_I(c, *ploc, SWAP, 2);\n            }\n            ADDOP(c, *ploc, POP_BLOCK);\n            ADDOP(c, *ploc, POP_EXCEPT);\n            if (info->fb_datum) {\n                ADDOP_LOAD_CONST(c, *ploc, Py_None);\n                RETURN_IF_ERROR(compiler_nameop(c, *ploc, info->fb_datum, Store));\n                RETURN_IF_ERROR(compiler_nameop(c, *ploc, info->fb_datum, Del));\n            }\n            return SUCCESS;\n        }\n        case POP_VALUE: {\n            if (preserve_tos) {\n                ADDOP_I(c, *ploc, SWAP, 2);\n            }\n            ADDOP(c, *ploc, POP_TOP);\n            return SUCCESS;\n        }\n    }\n    Py_UNREACHABLE();\n}\n\n/** Unwind block stack. If loop is not NULL, then stop when the first loop is encountered. */\nstatic int\ncompiler_unwind_fblock_stack(struct compiler *c, location *ploc,\n                             int preserve_tos, struct fblockinfo **loop)\n{\n    if (c->u->u_nfblocks == 0) {\n        return SUCCESS;\n    }\n    struct fblockinfo *top = &c->u->u_fblock[c->u->u_nfblocks-1];\n    if (top->fb_type == EXCEPTION_GROUP_HANDLER) {\n        return compiler_error(\n            c, *ploc, \"'break', 'continue' and 'return' cannot appear in an except* block\");\n    }\n    if (loop != NULL && (top->fb_type == WHILE_LOOP || top->fb_type == FOR_LOOP)) {\n        *loop = top;\n        return SUCCESS;\n    }\n    struct fblockinfo copy = *top;\n    c->u->u_nfblocks--;\n    RETURN_IF_ERROR(compiler_unwind_fblock(c, ploc, &copy, preserve_tos));\n    RETURN_IF_ERROR(compiler_unwind_fblock_stack(c, ploc, preserve_tos, loop));\n    c->u->u_fblock[c->u->u_nfblocks] = copy;\n    c->u->u_nfblocks++;\n    return SUCCESS;\n}\n\n/* Compile a sequence of statements, checking for a docstring\n   and for annotations. */\n\nstatic int\ncompiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)\n{\n    int i = 0;\n    stmt_ty st;\n    PyObject *docstring;\n\n    /* Set current line number to the line number of first statement.\n       This way line number for SETUP_ANNOTATIONS will always\n       coincide with the line number of first \"real\" statement in module.\n       If body is empty, then lineno will be set later in optimize_and_assemble. */\n    if (c->u->u_scope_type == COMPILER_SCOPE_MODULE && asdl_seq_LEN(stmts)) {\n        st = (stmt_ty)asdl_seq_GET(stmts, 0);\n        loc = LOC(st);\n    }\n    /* Every annotated class and module should have __annotations__. */\n    if (find_ann(stmts)) {\n        ADDOP(c, loc, SETUP_ANNOTATIONS);\n    }\n    if (!asdl_seq_LEN(stmts)) {\n        return SUCCESS;\n    }\n    /* if not -OO mode, set docstring */\n    if (c->c_optimize < 2) {\n        docstring = _PyAST_GetDocString(stmts);\n        if (docstring) {\n            i = 1;\n            st = (stmt_ty)asdl_seq_GET(stmts, 0);\n            assert(st->kind == Expr_kind);\n            VISIT(c, expr, st->v.Expr.value);\n            RETURN_IF_ERROR(compiler_nameop(c, NO_LOCATION, &_Py_ID(__doc__), Store));\n        }\n    }\n    for (; i < asdl_seq_LEN(stmts); i++) {\n        VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i));\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_codegen(struct compiler *c, mod_ty mod)\n{\n    _Py_DECLARE_STR(anon_module, \"<module>\");\n    RETURN_IF_ERROR(\n        compiler_enter_scope(c, &_Py_STR(anon_module), COMPILER_SCOPE_MODULE,\n                             mod, 1));\n\n    location loc = LOCATION(1, 1, 0, 0);\n    switch (mod->kind) {\n    case Module_kind:\n        if (compiler_body(c, loc, mod->v.Module.body) < 0) {\n            compiler_exit_scope(c);\n            return ERROR;\n        }\n        break;\n    case Interactive_kind:\n        if (find_ann(mod->v.Interactive.body)) {\n            ADDOP(c, loc, SETUP_ANNOTATIONS);\n        }\n        c->c_interactive = 1;\n        VISIT_SEQ_IN_SCOPE(c, stmt, mod->v.Interactive.body);\n        break;\n    case Expression_kind:\n        VISIT_IN_SCOPE(c, expr, mod->v.Expression.body);\n        break;\n    default:\n        PyErr_Format(PyExc_SystemError,\n                     \"module kind %d should not be possible\",\n                     mod->kind);\n        return ERROR;\n    }\n    return SUCCESS;\n}\n\nstatic PyCodeObject *\ncompiler_mod(struct compiler *c, mod_ty mod)\n{\n    int addNone = mod->kind != Expression_kind;\n    if (compiler_codegen(c, mod) < 0) {\n        return NULL;\n    }\n    PyCodeObject *co = optimize_and_assemble(c, addNone);\n    compiler_exit_scope(c);\n    return co;\n}\n\n/* The test for LOCAL must come before the test for FREE in order to\n   handle classes where name is both local and free.  The local var is\n   a method and the free var is a free var referenced within a method.\n*/\n\nstatic int\nget_ref_type(struct compiler *c, PyObject *name)\n{\n    int scope;\n    if (c->u->u_scope_type == COMPILER_SCOPE_CLASS &&\n        (_PyUnicode_EqualToASCIIString(name, \"__class__\") ||\n         _PyUnicode_EqualToASCIIString(name, \"__classdict__\"))) {\n        return CELL;\n    }\n    scope = _PyST_GetScope(c->u->u_ste, name);\n    if (scope == 0) {\n        PyErr_Format(PyExc_SystemError,\n                     \"_PyST_GetScope(name=%R) failed: \"\n                     \"unknown scope in unit %S (%R); \"\n                     \"symbols: %R; locals: %R; globals: %R\",\n                     name,\n                     c->u->u_metadata.u_name, c->u->u_ste->ste_id,\n                     c->u->u_ste->ste_symbols, c->u->u_metadata.u_varnames, c->u->u_metadata.u_names);\n        return ERROR;\n    }\n    return scope;\n}\n\nstatic int\ncompiler_lookup_arg(PyObject *dict, PyObject *name)\n{\n    PyObject *v = PyDict_GetItemWithError(dict, name);\n    if (v == NULL) {\n        return ERROR;\n    }\n    return PyLong_AS_LONG(v);\n}\n\nstatic int\ncompiler_make_closure(struct compiler *c, location loc,\n                      PyCodeObject *co, Py_ssize_t flags)\n{\n    if (co->co_nfreevars) {\n        int i = PyCode_GetFirstFree(co);\n        for (; i < co->co_nlocalsplus; ++i) {\n            /* Bypass com_addop_varname because it will generate\n               LOAD_DEREF but LOAD_CLOSURE is needed.\n            */\n            PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);\n\n            /* Special case: If a class contains a method with a\n               free variable that has the same name as a method,\n               the name will be considered free *and* local in the\n               class.  It should be handled by the closure, as\n               well as by the normal name lookup logic.\n            */\n            int reftype = get_ref_type(c, name);\n            if (reftype == -1) {\n                return ERROR;\n            }\n            int arg;\n            if (reftype == CELL) {\n                arg = compiler_lookup_arg(c->u->u_metadata.u_cellvars, name);\n            }\n            else {\n                arg = compiler_lookup_arg(c->u->u_metadata.u_freevars, name);\n            }\n            if (arg == -1) {\n                PyObject *freevars = _PyCode_GetFreevars(co);\n                if (freevars == NULL) {\n                    PyErr_Clear();\n                }\n                PyErr_Format(PyExc_SystemError,\n                    \"compiler_lookup_arg(name=%R) with reftype=%d failed in %S; \"\n                    \"freevars of code %S: %R\",\n                    name,\n                    reftype,\n                    c->u->u_metadata.u_name,\n                    co->co_name,\n                    freevars);\n                Py_DECREF(freevars);\n                return ERROR;\n            }\n            ADDOP_I(c, loc, LOAD_CLOSURE, arg);\n        }\n        flags |= MAKE_FUNCTION_CLOSURE;\n        ADDOP_I(c, loc, BUILD_TUPLE, co->co_nfreevars);\n    }\n    ADDOP_LOAD_CONST(c, loc, (PyObject*)co);\n    ADDOP_I(c, loc, MAKE_FUNCTION, flags);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_decorators(struct compiler *c, asdl_expr_seq* decos)\n{\n    if (!decos) {\n        return SUCCESS;\n    }\n\n    for (Py_ssize_t i = 0; i < asdl_seq_LEN(decos); i++) {\n        VISIT(c, expr, (expr_ty)asdl_seq_GET(decos, i));\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_apply_decorators(struct compiler *c, asdl_expr_seq* decos)\n{\n    if (!decos) {\n        return SUCCESS;\n    }\n\n    for (Py_ssize_t i = asdl_seq_LEN(decos) - 1; i > -1; i--) {\n        location loc = LOC((expr_ty)asdl_seq_GET(decos, i));\n        ADDOP_I(c, loc, CALL, 0);\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_visit_kwonlydefaults(struct compiler *c, location loc,\n                              asdl_arg_seq *kwonlyargs, asdl_expr_seq *kw_defaults)\n{\n    /* Push a dict of keyword-only default values.\n\n       Return -1 on error, 0 if no dict pushed, 1 if a dict is pushed.\n       */\n    int i;\n    PyObject *keys = NULL;\n\n    for (i = 0; i < asdl_seq_LEN(kwonlyargs); i++) {\n        arg_ty arg = asdl_seq_GET(kwonlyargs, i);\n        expr_ty default_ = asdl_seq_GET(kw_defaults, i);\n        if (default_) {\n            PyObject *mangled = _Py_Mangle(c->u->u_private, arg->arg);\n            if (!mangled) {\n                goto error;\n            }\n            if (keys == NULL) {\n                keys = PyList_New(1);\n                if (keys == NULL) {\n                    Py_DECREF(mangled);\n                    return ERROR;\n                }\n                PyList_SET_ITEM(keys, 0, mangled);\n            }\n            else {\n                int res = PyList_Append(keys, mangled);\n                Py_DECREF(mangled);\n                if (res == -1) {\n                    goto error;\n                }\n            }\n            if (compiler_visit_expr(c, default_) < 0) {\n                goto error;\n            }\n        }\n    }\n    if (keys != NULL) {\n        Py_ssize_t default_count = PyList_GET_SIZE(keys);\n        PyObject *keys_tuple = PyList_AsTuple(keys);\n        Py_DECREF(keys);\n        ADDOP_LOAD_CONST_NEW(c, loc, keys_tuple);\n        ADDOP_I(c, loc, BUILD_CONST_KEY_MAP, default_count);\n        assert(default_count > 0);\n        return 1;\n    }\n    else {\n        return 0;\n    }\n\nerror:\n    Py_XDECREF(keys);\n    return ERROR;\n}\n\nstatic int\ncompiler_visit_annexpr(struct compiler *c, expr_ty annotation)\n{\n    location loc = LOC(annotation);\n    ADDOP_LOAD_CONST_NEW(c, loc, _PyAST_ExprAsUnicode(annotation));\n    return SUCCESS;\n}\n\nstatic int\ncompiler_visit_argannotation(struct compiler *c, identifier id,\n    expr_ty annotation, Py_ssize_t *annotations_len, location loc)\n{\n    if (!annotation) {\n        return SUCCESS;\n    }\n    PyObject *mangled = _Py_Mangle(c->u->u_private, id);\n    if (!mangled) {\n        return ERROR;\n    }\n    ADDOP_LOAD_CONST(c, loc, mangled);\n    Py_DECREF(mangled);\n\n    if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) {\n        VISIT(c, annexpr, annotation);\n    }\n    else {\n        if (annotation->kind == Starred_kind) {\n            // *args: *Ts (where Ts is a TypeVarTuple).\n            // Do [annotation_value] = [*Ts].\n            // (Note that in theory we could end up here even for an argument\n            // other than *args, but in practice the grammar doesn't allow it.)\n            VISIT(c, expr, annotation->v.Starred.value);\n            ADDOP_I(c, loc, UNPACK_SEQUENCE, (Py_ssize_t) 1);\n        }\n        else {\n            VISIT(c, expr, annotation);\n        }\n    }\n    *annotations_len += 2;\n    return SUCCESS;\n}\n\nstatic int\ncompiler_visit_argannotations(struct compiler *c, asdl_arg_seq* args,\n                              Py_ssize_t *annotations_len, location loc)\n{\n    int i;\n    for (i = 0; i < asdl_seq_LEN(args); i++) {\n        arg_ty arg = (arg_ty)asdl_seq_GET(args, i);\n        RETURN_IF_ERROR(\n            compiler_visit_argannotation(\n                        c,\n                        arg->arg,\n                        arg->annotation,\n                        annotations_len,\n                        loc));\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_visit_annotations(struct compiler *c, location loc,\n                           arguments_ty args, expr_ty returns)\n{\n    /* Push arg annotation names and values.\n       The expressions are evaluated out-of-order wrt the source code.\n\n       Return -1 on error, 0 if no annotations pushed, 1 if a annotations is pushed.\n       */\n    Py_ssize_t annotations_len = 0;\n\n    RETURN_IF_ERROR(\n        compiler_visit_argannotations(c, args->args, &annotations_len, loc));\n\n    RETURN_IF_ERROR(\n        compiler_visit_argannotations(c, args->posonlyargs, &annotations_len, loc));\n\n    if (args->vararg && args->vararg->annotation) {\n        RETURN_IF_ERROR(\n            compiler_visit_argannotation(c, args->vararg->arg,\n                                         args->vararg->annotation, &annotations_len, loc));\n    }\n\n    RETURN_IF_ERROR(\n        compiler_visit_argannotations(c, args->kwonlyargs, &annotations_len, loc));\n\n    if (args->kwarg && args->kwarg->annotation) {\n        RETURN_IF_ERROR(\n            compiler_visit_argannotation(c, args->kwarg->arg,\n                                         args->kwarg->annotation, &annotations_len, loc));\n    }\n\n    RETURN_IF_ERROR(\n        compiler_visit_argannotation(c, &_Py_ID(return), returns, &annotations_len, loc));\n\n    if (annotations_len) {\n        ADDOP_I(c, loc, BUILD_TUPLE, annotations_len);\n        return 1;\n    }\n\n    return 0;\n}\n\nstatic int\ncompiler_visit_defaults(struct compiler *c, arguments_ty args,\n                        location loc)\n{\n    VISIT_SEQ(c, expr, args->defaults);\n    ADDOP_I(c, loc, BUILD_TUPLE, asdl_seq_LEN(args->defaults));\n    return SUCCESS;\n}\n\nstatic Py_ssize_t\ncompiler_default_arguments(struct compiler *c, location loc,\n                           arguments_ty args)\n{\n    Py_ssize_t funcflags = 0;\n    if (args->defaults && asdl_seq_LEN(args->defaults) > 0) {\n        RETURN_IF_ERROR(compiler_visit_defaults(c, args, loc));\n        funcflags |= MAKE_FUNCTION_DEFAULTS;\n    }\n    if (args->kwonlyargs) {\n        int res = compiler_visit_kwonlydefaults(c, loc,\n                                                args->kwonlyargs,\n                                                args->kw_defaults);\n        RETURN_IF_ERROR(res);\n        if (res > 0) {\n            funcflags |= MAKE_FUNCTION_KWDEFAULTS;\n        }\n    }\n    return funcflags;\n}\n\nstatic bool\nforbidden_name(struct compiler *c, location loc, identifier name,\n               expr_context_ty ctx)\n{\n    if (ctx == Store && _PyUnicode_EqualToASCIIString(name, \"__debug__\")) {\n        compiler_error(c, loc, \"cannot assign to __debug__\");\n        return true;\n    }\n    if (ctx == Del && _PyUnicode_EqualToASCIIString(name, \"__debug__\")) {\n        compiler_error(c, loc, \"cannot delete __debug__\");\n        return true;\n    }\n    return false;\n}\n\nstatic int\ncompiler_check_debug_one_arg(struct compiler *c, arg_ty arg)\n{\n    if (arg != NULL) {\n        if (forbidden_name(c, LOC(arg), arg->arg, Store)) {\n            return ERROR;\n        }\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_check_debug_args_seq(struct compiler *c, asdl_arg_seq *args)\n{\n    if (args != NULL) {\n        for (Py_ssize_t i = 0, n = asdl_seq_LEN(args); i < n; i++) {\n            RETURN_IF_ERROR(\n                compiler_check_debug_one_arg(c, asdl_seq_GET(args, i)));\n        }\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_check_debug_args(struct compiler *c, arguments_ty args)\n{\n    RETURN_IF_ERROR(compiler_check_debug_args_seq(c, args->posonlyargs));\n    RETURN_IF_ERROR(compiler_check_debug_args_seq(c, args->args));\n    RETURN_IF_ERROR(compiler_check_debug_one_arg(c, args->vararg));\n    RETURN_IF_ERROR(compiler_check_debug_args_seq(c, args->kwonlyargs));\n    RETURN_IF_ERROR(compiler_check_debug_one_arg(c, args->kwarg));\n    return SUCCESS;\n}\n\nstatic int\nwrap_in_stopiteration_handler(struct compiler *c)\n{\n    NEW_JUMP_TARGET_LABEL(c, handler);\n\n    /* Insert SETUP_CLEANUP at start */\n    RETURN_IF_ERROR(\n        instr_sequence_insert_instruction(\n            INSTR_SEQUENCE(c), 0,\n            SETUP_CLEANUP, handler.id, NO_LOCATION));\n\n    ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);\n    ADDOP(c, NO_LOCATION, RETURN_VALUE);\n    USE_LABEL(c, handler);\n    ADDOP_I(c, NO_LOCATION, CALL_INTRINSIC_1, INTRINSIC_STOPITERATION_ERROR);\n    ADDOP_I(c, NO_LOCATION, RERAISE, 1);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_type_params(struct compiler *c, asdl_type_param_seq *type_params)\n{\n    if (!type_params) {\n        return SUCCESS;\n    }\n    Py_ssize_t n = asdl_seq_LEN(type_params);\n\n    for (Py_ssize_t i = 0; i < n; i++) {\n        type_param_ty typeparam = asdl_seq_GET(type_params, i);\n        location loc = LOC(typeparam);\n        switch(typeparam->kind) {\n        case TypeVar_kind:\n            ADDOP_LOAD_CONST(c, loc, typeparam->v.TypeVar.name);\n            if (typeparam->v.TypeVar.bound) {\n                expr_ty bound = typeparam->v.TypeVar.bound;\n                if (compiler_enter_scope(c, typeparam->v.TypeVar.name, COMPILER_SCOPE_TYPEPARAMS,\n                                        (void *)typeparam, bound->lineno) == -1) {\n                    return ERROR;\n                }\n                VISIT_IN_SCOPE(c, expr, bound);\n                ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);\n                PyCodeObject *co = optimize_and_assemble(c, 1);\n                compiler_exit_scope(c);\n                if (co == NULL) {\n                    return ERROR;\n                }\n                if (compiler_make_closure(c, loc, co, 0) < 0) {\n                    Py_DECREF(co);\n                    return ERROR;\n                }\n                Py_DECREF(co);\n\n                int intrinsic = bound->kind == Tuple_kind\n                    ? INTRINSIC_TYPEVAR_WITH_CONSTRAINTS\n                    : INTRINSIC_TYPEVAR_WITH_BOUND;\n                ADDOP_I(c, loc, CALL_INTRINSIC_2, intrinsic);\n            }\n            else {\n                ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEVAR);\n            }\n            ADDOP_I(c, loc, COPY, 1);\n            RETURN_IF_ERROR(compiler_nameop(c, loc, typeparam->v.TypeVar.name, Store));\n            break;\n        case TypeVarTuple_kind:\n            ADDOP_LOAD_CONST(c, loc, typeparam->v.TypeVarTuple.name);\n            ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEVARTUPLE);\n            ADDOP_I(c, loc, COPY, 1);\n            RETURN_IF_ERROR(compiler_nameop(c, loc, typeparam->v.TypeVarTuple.name, Store));\n            break;\n        case ParamSpec_kind:\n            ADDOP_LOAD_CONST(c, loc, typeparam->v.ParamSpec.name);\n            ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_PARAMSPEC);\n            ADDOP_I(c, loc, COPY, 1);\n            RETURN_IF_ERROR(compiler_nameop(c, loc, typeparam->v.ParamSpec.name, Store));\n            break;\n        }\n    }\n    ADDOP_I(c, LOC(asdl_seq_GET(type_params, 0)), BUILD_TUPLE, n);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t funcflags,\n                       int firstlineno)\n{\n    PyObject *docstring = NULL;\n    arguments_ty args;\n    identifier name;\n    asdl_stmt_seq *body;\n    int scope_type;\n\n    if (is_async) {\n        assert(s->kind == AsyncFunctionDef_kind);\n\n        args = s->v.AsyncFunctionDef.args;\n        name = s->v.AsyncFunctionDef.name;\n        body = s->v.AsyncFunctionDef.body;\n\n        scope_type = COMPILER_SCOPE_ASYNC_FUNCTION;\n    } else {\n        assert(s->kind == FunctionDef_kind);\n\n        args = s->v.FunctionDef.args;\n        name = s->v.FunctionDef.name;\n        body = s->v.FunctionDef.body;\n\n        scope_type = COMPILER_SCOPE_FUNCTION;\n    }\n\n    RETURN_IF_ERROR(\n        compiler_enter_scope(c, name, scope_type, (void *)s, firstlineno));\n\n    /* if not -OO mode, add docstring */\n    if (c->c_optimize < 2) {\n        docstring = _PyAST_GetDocString(body);\n    }\n    if (compiler_add_const(c->c_const_cache, c->u, docstring ? docstring : Py_None) < 0) {\n        compiler_exit_scope(c);\n        return ERROR;\n    }\n\n    c->u->u_metadata.u_argcount = asdl_seq_LEN(args->args);\n    c->u->u_metadata.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);\n    c->u->u_metadata.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);\n    for (Py_ssize_t i = docstring ? 1 : 0; i < asdl_seq_LEN(body); i++) {\n        VISIT_IN_SCOPE(c, stmt, (stmt_ty)asdl_seq_GET(body, i));\n    }\n    if (c->u->u_ste->ste_coroutine || c->u->u_ste->ste_generator) {\n        if (wrap_in_stopiteration_handler(c) < 0) {\n            compiler_exit_scope(c);\n            return ERROR;\n        }\n    }\n    PyCodeObject *co = optimize_and_assemble(c, 1);\n    compiler_exit_scope(c);\n    if (co == NULL) {\n        Py_XDECREF(co);\n        return ERROR;\n    }\n    location loc = LOC(s);\n    if (compiler_make_closure(c, loc, co, funcflags) < 0) {\n        Py_DECREF(co);\n        return ERROR;\n    }\n    Py_DECREF(co);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_function(struct compiler *c, stmt_ty s, int is_async)\n{\n    arguments_ty args;\n    expr_ty returns;\n    identifier name;\n    asdl_expr_seq *decos;\n    asdl_type_param_seq *type_params;\n    Py_ssize_t funcflags;\n    int annotations;\n    int firstlineno;\n\n    if (is_async) {\n        assert(s->kind == AsyncFunctionDef_kind);\n\n        args = s->v.AsyncFunctionDef.args;\n        returns = s->v.AsyncFunctionDef.returns;\n        decos = s->v.AsyncFunctionDef.decorator_list;\n        name = s->v.AsyncFunctionDef.name;\n        type_params = s->v.AsyncFunctionDef.type_params;\n    } else {\n        assert(s->kind == FunctionDef_kind);\n\n        args = s->v.FunctionDef.args;\n        returns = s->v.FunctionDef.returns;\n        decos = s->v.FunctionDef.decorator_list;\n        name = s->v.FunctionDef.name;\n        type_params = s->v.FunctionDef.type_params;\n    }\n\n    RETURN_IF_ERROR(compiler_check_debug_args(c, args));\n    RETURN_IF_ERROR(compiler_decorators(c, decos));\n\n    firstlineno = s->lineno;\n    if (asdl_seq_LEN(decos)) {\n        firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno;\n    }\n\n    location loc = LOC(s);\n\n    int is_generic = asdl_seq_LEN(type_params) > 0;\n\n    if (is_generic) {\n        // Used by the CALL to the type parameters function.\n        ADDOP(c, loc, PUSH_NULL);\n    }\n\n    funcflags = compiler_default_arguments(c, loc, args);\n    if (funcflags == -1) {\n        return ERROR;\n    }\n\n    int num_typeparam_args = 0;\n\n    if (is_generic) {\n        if (funcflags & MAKE_FUNCTION_DEFAULTS) {\n            num_typeparam_args += 1;\n        }\n        if (funcflags & MAKE_FUNCTION_KWDEFAULTS) {\n            num_typeparam_args += 1;\n        }\n        if (num_typeparam_args == 2) {\n            ADDOP_I(c, loc, SWAP, 2);\n        }\n        PyObject *type_params_name = PyUnicode_FromFormat(\"<generic parameters of %U>\", name);\n        if (!type_params_name) {\n            return ERROR;\n        }\n        if (compiler_enter_scope(c, type_params_name, COMPILER_SCOPE_TYPEPARAMS,\n                                 (void *)type_params, firstlineno) == -1) {\n            Py_DECREF(type_params_name);\n            return ERROR;\n        }\n        Py_DECREF(type_params_name);\n        RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params));\n        for (int i = 0; i < num_typeparam_args; i++) {\n            RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(INSTR_SEQUENCE(c), LOAD_FAST, i, loc));\n        }\n    }\n\n    annotations = compiler_visit_annotations(c, loc, args, returns);\n    if (annotations < 0) {\n        if (is_generic) {\n            compiler_exit_scope(c);\n        }\n        return ERROR;\n    }\n    if (annotations > 0) {\n        funcflags |= MAKE_FUNCTION_ANNOTATIONS;\n    }\n\n    if (compiler_function_body(c, s, is_async, funcflags, firstlineno) < 0) {\n        if (is_generic) {\n            compiler_exit_scope(c);\n        }\n        return ERROR;\n    }\n\n    if (is_generic) {\n        RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(\n            INSTR_SEQUENCE(c), SWAP, 2, loc));\n        RETURN_IF_ERROR_IN_SCOPE(c, codegen_addop_i(\n            INSTR_SEQUENCE(c), CALL_INTRINSIC_2, INTRINSIC_SET_FUNCTION_TYPE_PARAMS, loc));\n\n        c->u->u_metadata.u_argcount = num_typeparam_args;\n        PyCodeObject *co = optimize_and_assemble(c, 0);\n        compiler_exit_scope(c);\n        if (co == NULL) {\n            return ERROR;\n        }\n        if (compiler_make_closure(c, loc, co, 0) < 0) {\n            Py_DECREF(co);\n            return ERROR;\n        }\n        Py_DECREF(co);\n        if (num_typeparam_args > 0) {\n            ADDOP_I(c, loc, SWAP, num_typeparam_args + 1);\n        }\n        ADDOP_I(c, loc, CALL, num_typeparam_args);\n    }\n\n    RETURN_IF_ERROR(compiler_apply_decorators(c, decos));\n    return compiler_nameop(c, loc, name, Store);\n}\n\nstatic int\ncompiler_set_type_params_in_class(struct compiler *c, location loc)\n{\n    _Py_DECLARE_STR(type_params, \".type_params\");\n    RETURN_IF_ERROR(compiler_nameop(c, loc, &_Py_STR(type_params), Load));\n    RETURN_IF_ERROR(compiler_nameop(c, loc, &_Py_ID(__type_params__), Store));\n    return 1;\n}\n\nstatic int\ncompiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)\n{\n    /* ultimately generate code for:\n         <name> = __build_class__(<func>, <name>, *<bases>, **<keywords>)\n       where:\n         <func> is a zero arg function/closure created from the class body.\n            It mutates its locals to build the class namespace.\n         <name> is the class name\n         <bases> is the positional arguments and *varargs argument\n         <keywords> is the keyword arguments and **kwds argument\n       This borrows from compiler_call.\n    */\n\n    /* 1. compile the class body into a code object */\n    RETURN_IF_ERROR(\n        compiler_enter_scope(c, s->v.ClassDef.name,\n                             COMPILER_SCOPE_CLASS, (void *)s, firstlineno));\n\n    location loc = LOCATION(firstlineno, firstlineno, 0, 0);\n    /* use the class name for name mangling */\n    Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name));\n    /* load (global) __name__ ... */\n    if (compiler_nameop(c, loc, &_Py_ID(__name__), Load) < 0) {\n        compiler_exit_scope(c);\n        return ERROR;\n    }\n    /* ... and store it as __module__ */\n    if (compiler_nameop(c, loc, &_Py_ID(__module__), Store) < 0) {\n        compiler_exit_scope(c);\n        return ERROR;\n    }\n    assert(c->u->u_metadata.u_qualname);\n    ADDOP_LOAD_CONST(c, loc, c->u->u_metadata.u_qualname);\n    if (compiler_nameop(c, loc, &_Py_ID(__qualname__), Store) < 0) {\n        compiler_exit_scope(c);\n        return ERROR;\n    }\n    asdl_type_param_seq *type_params = s->v.ClassDef.type_params;\n    if (asdl_seq_LEN(type_params) > 0) {\n        if (!compiler_set_type_params_in_class(c, loc)) {\n            compiler_exit_scope(c);\n            return ERROR;\n        }\n    }\n    if (c->u->u_ste->ste_needs_classdict) {\n        ADDOP(c, loc, LOAD_LOCALS);\n\n        // We can't use compiler_nameop here because we need to generate a\n        // STORE_DEREF in a class namespace, and compiler_nameop() won't do\n        // that by default.\n        PyObject *cellvars = c->u->u_metadata.u_cellvars;\n        if (compiler_addop_o(c->u, loc, STORE_DEREF, cellvars,\n                             &_Py_ID(__classdict__)) < 0) {\n            compiler_exit_scope(c);\n            return ERROR;\n        }\n    }\n    /* compile the body proper */\n    if (compiler_body(c, loc, s->v.ClassDef.body) < 0) {\n        compiler_exit_scope(c);\n        return ERROR;\n    }\n    /* The following code is artificial */\n    /* Set __classdictcell__ if necessary */\n    if (c->u->u_ste->ste_needs_classdict) {\n        /* Store __classdictcell__ into class namespace */\n        int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__classdict__));\n        if (i < 0) {\n            compiler_exit_scope(c);\n            return ERROR;\n        }\n        ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i);\n        if (compiler_nameop(c, NO_LOCATION, &_Py_ID(__classdictcell__), Store) < 0) {\n            compiler_exit_scope(c);\n            return ERROR;\n        }\n    }\n    /* Return __classcell__ if it is referenced, otherwise return None */\n    if (c->u->u_ste->ste_needs_class_closure) {\n        /* Store __classcell__ into class namespace & return it */\n        int i = compiler_lookup_arg(c->u->u_metadata.u_cellvars, &_Py_ID(__class__));\n        if (i < 0) {\n            compiler_exit_scope(c);\n            return ERROR;\n        }\n        ADDOP_I(c, NO_LOCATION, LOAD_CLOSURE, i);\n        ADDOP_I(c, NO_LOCATION, COPY, 1);\n        if (compiler_nameop(c, NO_LOCATION, &_Py_ID(__classcell__), Store) < 0) {\n            compiler_exit_scope(c);\n            return ERROR;\n        }\n    }\n    else {\n        /* No methods referenced __class__, so just return None */\n        ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);\n    }\n    ADDOP_IN_SCOPE(c, NO_LOCATION, RETURN_VALUE);\n    /* create the code object */\n    PyCodeObject *co = optimize_and_assemble(c, 1);\n\n    /* leave the new scope */\n    compiler_exit_scope(c);\n    if (co == NULL) {\n        return ERROR;\n    }\n\n    /* 2. load the 'build_class' function */\n\n    // these instructions should be attributed to the class line,\n    // not a decorator line\n    loc = LOC(s);\n    ADDOP(c, loc, PUSH_NULL);\n    ADDOP(c, loc, LOAD_BUILD_CLASS);\n\n    /* 3. load a function (or closure) made from the code object */\n    if (compiler_make_closure(c, loc, co, 0) < 0) {\n        Py_DECREF(co);\n        return ERROR;\n    }\n    Py_DECREF(co);\n\n    /* 4. load class name */\n    ADDOP_LOAD_CONST(c, loc, s->v.ClassDef.name);\n\n    return SUCCESS;\n}\n\nstatic int\ncompiler_class(struct compiler *c, stmt_ty s)\n{\n    asdl_expr_seq *decos = s->v.ClassDef.decorator_list;\n\n    RETURN_IF_ERROR(compiler_decorators(c, decos));\n\n    int firstlineno = s->lineno;\n    if (asdl_seq_LEN(decos)) {\n        firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno;\n    }\n    location loc = LOC(s);\n\n    asdl_type_param_seq *type_params = s->v.ClassDef.type_params;\n    int is_generic = asdl_seq_LEN(type_params) > 0;\n    if (is_generic) {\n        Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name));\n        ADDOP(c, loc, PUSH_NULL);\n        PyObject *type_params_name = PyUnicode_FromFormat(\"<generic parameters of %U>\",\n                                                         s->v.ClassDef.name);\n        if (!type_params_name) {\n            return ERROR;\n        }\n        if (compiler_enter_scope(c, type_params_name, COMPILER_SCOPE_TYPEPARAMS,\n                                 (void *)type_params, firstlineno) == -1) {\n            Py_DECREF(type_params_name);\n            return ERROR;\n        }\n        Py_DECREF(type_params_name);\n        RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params));\n        _Py_DECLARE_STR(type_params, \".type_params\");\n        RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(type_params), Store));\n    }\n\n    if (compiler_class_body(c, s, firstlineno) < 0) {\n        if (is_generic) {\n            compiler_exit_scope(c);\n        }\n        return ERROR;\n    }\n\n    /* generate the rest of the code for the call */\n\n    if (is_generic) {\n        _Py_DECLARE_STR(type_params, \".type_params\");\n        _Py_DECLARE_STR(generic_base, \".generic_base\");\n        RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(type_params), Load));\n        RETURN_IF_ERROR_IN_SCOPE(\n            c, codegen_addop_i(INSTR_SEQUENCE(c), CALL_INTRINSIC_1, INTRINSIC_SUBSCRIPT_GENERIC, loc)\n        )\n        RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(generic_base), Store));\n\n        Py_ssize_t original_len = asdl_seq_LEN(s->v.ClassDef.bases);\n        asdl_expr_seq *bases = _Py_asdl_expr_seq_new(\n            original_len + 1, c->c_arena);\n        if (bases == NULL) {\n            compiler_exit_scope(c);\n            return ERROR;\n        }\n        for (Py_ssize_t i = 0; i < original_len; i++) {\n            asdl_seq_SET(bases, i, asdl_seq_GET(s->v.ClassDef.bases, i));\n        }\n        expr_ty name_node = _PyAST_Name(\n            &_Py_STR(generic_base), Load,\n            loc.lineno, loc.col_offset, loc.end_lineno, loc.end_col_offset, c->c_arena\n        );\n        if (name_node == NULL) {\n            compiler_exit_scope(c);\n            return ERROR;\n        }\n        asdl_seq_SET(bases, original_len, name_node);\n        RETURN_IF_ERROR_IN_SCOPE(c, compiler_call_helper(c, loc, 2,\n                                                         bases,\n                                                         s->v.ClassDef.keywords));\n\n        PyCodeObject *co = optimize_and_assemble(c, 0);\n        compiler_exit_scope(c);\n        if (co == NULL) {\n            return ERROR;\n        }\n        if (compiler_make_closure(c, loc, co, 0) < 0) {\n            Py_DECREF(co);\n            return ERROR;\n        }\n        Py_DECREF(co);\n        ADDOP_I(c, loc, CALL, 0);\n    } else {\n        RETURN_IF_ERROR(compiler_call_helper(c, loc, 2,\n                                            s->v.ClassDef.bases,\n                                            s->v.ClassDef.keywords));\n    }\n\n    /* 6. apply decorators */\n    RETURN_IF_ERROR(compiler_apply_decorators(c, decos));\n\n    /* 7. store into <name> */\n    RETURN_IF_ERROR(compiler_nameop(c, loc, s->v.ClassDef.name, Store));\n    return SUCCESS;\n}\n\nstatic int\ncompiler_typealias_body(struct compiler *c, stmt_ty s)\n{\n    location loc = LOC(s);\n    PyObject *name = s->v.TypeAlias.name->v.Name.id;\n    RETURN_IF_ERROR(\n        compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION, s, loc.lineno));\n    /* Make None the first constant, so the evaluate function can't have a\n        docstring. */\n    RETURN_IF_ERROR(compiler_add_const(c->c_const_cache, c->u, Py_None));\n    VISIT_IN_SCOPE(c, expr, s->v.TypeAlias.value);\n    ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);\n    PyCodeObject *co = optimize_and_assemble(c, 0);\n    compiler_exit_scope(c);\n    if (co == NULL) {\n        return ERROR;\n    }\n    if (compiler_make_closure(c, loc, co, 0) < 0) {\n        Py_DECREF(co);\n        return ERROR;\n    }\n    Py_DECREF(co);\n    ADDOP_I(c, loc, BUILD_TUPLE, 3);\n    ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEALIAS);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_typealias(struct compiler *c, stmt_ty s)\n{\n    location loc = LOC(s);\n    asdl_type_param_seq *type_params = s->v.TypeAlias.type_params;\n    int is_generic = asdl_seq_LEN(type_params) > 0;\n    PyObject *name = s->v.TypeAlias.name->v.Name.id;\n    if (is_generic) {\n        ADDOP(c, loc, PUSH_NULL);\n        PyObject *type_params_name = PyUnicode_FromFormat(\"<generic parameters of %U>\",\n                                                         name);\n        if (!type_params_name) {\n            return ERROR;\n        }\n        if (compiler_enter_scope(c, type_params_name, COMPILER_SCOPE_TYPEPARAMS,\n                                 (void *)type_params, loc.lineno) == -1) {\n            Py_DECREF(type_params_name);\n            return ERROR;\n        }\n        Py_DECREF(type_params_name);\n        RETURN_IF_ERROR_IN_SCOPE(\n            c, compiler_addop_load_const(c->c_const_cache, c->u, loc, name)\n        );\n        RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params));\n    }\n    else {\n        ADDOP_LOAD_CONST(c, loc, name);\n        ADDOP_LOAD_CONST(c, loc, Py_None);\n    }\n\n    if (compiler_typealias_body(c, s) < 0) {\n        if (is_generic) {\n            compiler_exit_scope(c);\n        }\n        return ERROR;\n    }\n\n    if (is_generic) {\n        PyCodeObject *co = optimize_and_assemble(c, 0);\n        compiler_exit_scope(c);\n        if (co == NULL) {\n            return ERROR;\n        }\n        if (compiler_make_closure(c, loc, co, 0) < 0) {\n            Py_DECREF(co);\n            return ERROR;\n        }\n        Py_DECREF(co);\n        ADDOP_I(c, loc, CALL, 0);\n    }\n    RETURN_IF_ERROR(compiler_nameop(c, loc, name, Store));\n    return SUCCESS;\n}\n\n/* Return false if the expression is a constant value except named singletons.\n   Return true otherwise. */\nstatic bool\ncheck_is_arg(expr_ty e)\n{\n    if (e->kind != Constant_kind) {\n        return true;\n    }\n    PyObject *value = e->v.Constant.value;\n    return (value == Py_None\n         || value == Py_False\n         || value == Py_True\n         || value == Py_Ellipsis);\n}\n\nstatic PyTypeObject * infer_type(expr_ty e);\n\n/* Check operands of identity checks (\"is\" and \"is not\").\n   Emit a warning if any operand is a constant except named singletons.\n */\nstatic int\ncheck_compare(struct compiler *c, expr_ty e)\n{\n    Py_ssize_t i, n;\n    bool left = check_is_arg(e->v.Compare.left);\n    expr_ty left_expr = e->v.Compare.left;\n    n = asdl_seq_LEN(e->v.Compare.ops);\n    for (i = 0; i < n; i++) {\n        cmpop_ty op = (cmpop_ty)asdl_seq_GET(e->v.Compare.ops, i);\n        expr_ty right_expr = (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i);\n        bool right = check_is_arg(right_expr);\n        if (op == Is || op == IsNot) {\n            if (!right || !left) {\n                const char *msg = (op == Is)\n                        ? \"\\\"is\\\" with '%.200s' literal. Did you mean \\\"==\\\"?\"\n                        : \"\\\"is not\\\" with '%.200s' literal. Did you mean \\\"!=\\\"?\";\n                expr_ty literal = !left ? left_expr : right_expr;\n                return compiler_warn(\n                    c, LOC(e), msg, infer_type(literal)->tp_name\n                );\n            }\n        }\n        left = right;\n        left_expr = right_expr;\n    }\n    return SUCCESS;\n}\n\nstatic const int compare_masks[] = {\n    [Py_LT] = COMPARISON_LESS_THAN,\n    [Py_LE] = COMPARISON_LESS_THAN | COMPARISON_EQUALS,\n    [Py_EQ] = COMPARISON_EQUALS,\n    [Py_NE] = COMPARISON_NOT_EQUALS,\n    [Py_GT] = COMPARISON_GREATER_THAN,\n    [Py_GE] = COMPARISON_GREATER_THAN | COMPARISON_EQUALS,\n};\n\nstatic int compiler_addcompare(struct compiler *c, location loc,\n                               cmpop_ty op)\n{\n    int cmp;\n    switch (op) {\n    case Eq:\n        cmp = Py_EQ;\n        break;\n    case NotEq:\n        cmp = Py_NE;\n        break;\n    case Lt:\n        cmp = Py_LT;\n        break;\n    case LtE:\n        cmp = Py_LE;\n        break;\n    case Gt:\n        cmp = Py_GT;\n        break;\n    case GtE:\n        cmp = Py_GE;\n        break;\n    case Is:\n        ADDOP_I(c, loc, IS_OP, 0);\n        return SUCCESS;\n    case IsNot:\n        ADDOP_I(c, loc, IS_OP, 1);\n        return SUCCESS;\n    case In:\n        ADDOP_I(c, loc, CONTAINS_OP, 0);\n        return SUCCESS;\n    case NotIn:\n        ADDOP_I(c, loc, CONTAINS_OP, 1);\n        return SUCCESS;\n    default:\n        Py_UNREACHABLE();\n    }\n    /* cmp goes in top bits of the oparg, while the low bits are used by quickened\n     * versions of this opcode to store the comparison mask. */\n    ADDOP_I(c, loc, COMPARE_OP, (cmp << 4) | compare_masks[cmp]);\n    return SUCCESS;\n}\n\n\n\nstatic int\ncompiler_jump_if(struct compiler *c, location loc,\n                 expr_ty e, jump_target_label next, int cond)\n{\n    switch (e->kind) {\n    case UnaryOp_kind:\n        if (e->v.UnaryOp.op == Not) {\n            return compiler_jump_if(c, loc, e->v.UnaryOp.operand, next, !cond);\n        }\n        /* fallback to general implementation */\n        break;\n    case BoolOp_kind: {\n        asdl_expr_seq *s = e->v.BoolOp.values;\n        Py_ssize_t i, n = asdl_seq_LEN(s) - 1;\n        assert(n >= 0);\n        int cond2 = e->v.BoolOp.op == Or;\n        jump_target_label next2 = next;\n        if (!cond2 != !cond) {\n            NEW_JUMP_TARGET_LABEL(c, new_next2);\n            next2 = new_next2;\n        }\n        for (i = 0; i < n; ++i) {\n            RETURN_IF_ERROR(\n                compiler_jump_if(c, loc, (expr_ty)asdl_seq_GET(s, i), next2, cond2));\n        }\n        RETURN_IF_ERROR(\n            compiler_jump_if(c, loc, (expr_ty)asdl_seq_GET(s, n), next, cond));\n        if (!SAME_LABEL(next2, next)) {\n            USE_LABEL(c, next2);\n        }\n        return SUCCESS;\n    }\n    case IfExp_kind: {\n        NEW_JUMP_TARGET_LABEL(c, end);\n        NEW_JUMP_TARGET_LABEL(c, next2);\n        RETURN_IF_ERROR(\n            compiler_jump_if(c, loc, e->v.IfExp.test, next2, 0));\n        RETURN_IF_ERROR(\n            compiler_jump_if(c, loc, e->v.IfExp.body, next, cond));\n        ADDOP_JUMP(c, NO_LOCATION, JUMP, end);\n\n        USE_LABEL(c, next2);\n        RETURN_IF_ERROR(\n            compiler_jump_if(c, loc, e->v.IfExp.orelse, next, cond));\n\n        USE_LABEL(c, end);\n        return SUCCESS;\n    }\n    case Compare_kind: {\n        Py_ssize_t n = asdl_seq_LEN(e->v.Compare.ops) - 1;\n        if (n > 0) {\n            RETURN_IF_ERROR(check_compare(c, e));\n            NEW_JUMP_TARGET_LABEL(c, cleanup);\n            VISIT(c, expr, e->v.Compare.left);\n            for (Py_ssize_t i = 0; i < n; i++) {\n                VISIT(c, expr,\n                    (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));\n                ADDOP_I(c, LOC(e), SWAP, 2);\n                ADDOP_I(c, LOC(e), COPY, 2);\n                ADDOP_COMPARE(c, LOC(e), asdl_seq_GET(e->v.Compare.ops, i));\n                ADDOP_JUMP(c, LOC(e), POP_JUMP_IF_FALSE, cleanup);\n            }\n            VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));\n            ADDOP_COMPARE(c, LOC(e), asdl_seq_GET(e->v.Compare.ops, n));\n            ADDOP_JUMP(c, LOC(e), cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);\n            NEW_JUMP_TARGET_LABEL(c, end);\n            ADDOP_JUMP(c, NO_LOCATION, JUMP, end);\n\n            USE_LABEL(c, cleanup);\n            ADDOP(c, LOC(e), POP_TOP);\n            if (!cond) {\n                ADDOP_JUMP(c, NO_LOCATION, JUMP, next);\n            }\n\n            USE_LABEL(c, end);\n            return SUCCESS;\n        }\n        /* fallback to general implementation */\n        break;\n    }\n    default:\n        /* fallback to general implementation */\n        break;\n    }\n\n    /* general implementation */\n    VISIT(c, expr, e);\n    ADDOP_JUMP(c, LOC(e), cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_ifexp(struct compiler *c, expr_ty e)\n{\n    assert(e->kind == IfExp_kind);\n    NEW_JUMP_TARGET_LABEL(c, end);\n    NEW_JUMP_TARGET_LABEL(c, next);\n\n    RETURN_IF_ERROR(\n        compiler_jump_if(c, LOC(e), e->v.IfExp.test, next, 0));\n\n    VISIT(c, expr, e->v.IfExp.body);\n    ADDOP_JUMP(c, NO_LOCATION, JUMP, end);\n\n    USE_LABEL(c, next);\n    VISIT(c, expr, e->v.IfExp.orelse);\n\n    USE_LABEL(c, end);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_lambda(struct compiler *c, expr_ty e)\n{\n    PyCodeObject *co;\n    Py_ssize_t funcflags;\n    arguments_ty args = e->v.Lambda.args;\n    assert(e->kind == Lambda_kind);\n\n    RETURN_IF_ERROR(compiler_check_debug_args(c, args));\n\n    location loc = LOC(e);\n    funcflags = compiler_default_arguments(c, loc, args);\n    if (funcflags == -1) {\n        return ERROR;\n    }\n\n    _Py_DECLARE_STR(anon_lambda, \"<lambda>\");\n    RETURN_IF_ERROR(\n        compiler_enter_scope(c, &_Py_STR(anon_lambda), COMPILER_SCOPE_LAMBDA,\n                             (void *)e, e->lineno));\n\n    /* Make None the first constant, so the lambda can't have a\n       docstring. */\n    RETURN_IF_ERROR(compiler_add_const(c->c_const_cache, c->u, Py_None));\n\n    c->u->u_metadata.u_argcount = asdl_seq_LEN(args->args);\n    c->u->u_metadata.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);\n    c->u->u_metadata.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);\n    VISIT_IN_SCOPE(c, expr, e->v.Lambda.body);\n    if (c->u->u_ste->ste_generator) {\n        co = optimize_and_assemble(c, 0);\n    }\n    else {\n        location loc = LOCATION(e->lineno, e->lineno, 0, 0);\n        ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);\n        co = optimize_and_assemble(c, 1);\n    }\n    compiler_exit_scope(c);\n    if (co == NULL) {\n        return ERROR;\n    }\n\n    if (compiler_make_closure(c, loc, co, funcflags) < 0) {\n        Py_DECREF(co);\n        return ERROR;\n    }\n    Py_DECREF(co);\n\n    return SUCCESS;\n}\n\nstatic int\ncompiler_if(struct compiler *c, stmt_ty s)\n{\n    jump_target_label next;\n    assert(s->kind == If_kind);\n    NEW_JUMP_TARGET_LABEL(c, end);\n    if (asdl_seq_LEN(s->v.If.orelse)) {\n        NEW_JUMP_TARGET_LABEL(c, orelse);\n        next = orelse;\n    }\n    else {\n        next = end;\n    }\n    RETURN_IF_ERROR(\n        compiler_jump_if(c, LOC(s), s->v.If.test, next, 0));\n\n    VISIT_SEQ(c, stmt, s->v.If.body);\n    if (asdl_seq_LEN(s->v.If.orelse)) {\n        ADDOP_JUMP(c, NO_LOCATION, JUMP, end);\n\n        USE_LABEL(c, next);\n        VISIT_SEQ(c, stmt, s->v.If.orelse);\n    }\n\n    USE_LABEL(c, end);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_for(struct compiler *c, stmt_ty s)\n{\n    location loc = LOC(s);\n    NEW_JUMP_TARGET_LABEL(c, start);\n    NEW_JUMP_TARGET_LABEL(c, body);\n    NEW_JUMP_TARGET_LABEL(c, cleanup);\n    NEW_JUMP_TARGET_LABEL(c, end);\n\n    RETURN_IF_ERROR(compiler_push_fblock(c, loc, FOR_LOOP, start, end, NULL));\n\n    VISIT(c, expr, s->v.For.iter);\n    ADDOP(c, loc, GET_ITER);\n\n    USE_LABEL(c, start);\n    ADDOP_JUMP(c, loc, FOR_ITER, cleanup);\n\n    USE_LABEL(c, body);\n    VISIT(c, expr, s->v.For.target);\n    VISIT_SEQ(c, stmt, s->v.For.body);\n    /* Mark jump as artificial */\n    ADDOP_JUMP(c, NO_LOCATION, JUMP, start);\n\n    USE_LABEL(c, cleanup);\n    ADDOP(c, NO_LOCATION, END_FOR);\n\n    compiler_pop_fblock(c, FOR_LOOP, start);\n\n    VISIT_SEQ(c, stmt, s->v.For.orelse);\n\n    USE_LABEL(c, end);\n    return SUCCESS;\n}\n\n\nstatic int\ncompiler_async_for(struct compiler *c, stmt_ty s)\n{\n    location loc = LOC(s);\n    if (IS_TOP_LEVEL_AWAIT(c)){\n        c->u->u_ste->ste_coroutine = 1;\n    } else if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION) {\n        return compiler_error(c, loc, \"'async for' outside async function\");\n    }\n\n    NEW_JUMP_TARGET_LABEL(c, start);\n    NEW_JUMP_TARGET_LABEL(c, except);\n    NEW_JUMP_TARGET_LABEL(c, end);\n\n    VISIT(c, expr, s->v.AsyncFor.iter);\n    ADDOP(c, loc, GET_AITER);\n\n    USE_LABEL(c, start);\n    RETURN_IF_ERROR(compiler_push_fblock(c, loc, FOR_LOOP, start, end, NULL));\n\n    /* SETUP_FINALLY to guard the __anext__ call */\n    ADDOP_JUMP(c, loc, SETUP_FINALLY, except);\n    ADDOP(c, loc, GET_ANEXT);\n    ADDOP_LOAD_CONST(c, loc, Py_None);\n    ADD_YIELD_FROM(c, loc, 1);\n    ADDOP(c, loc, POP_BLOCK);  /* for SETUP_FINALLY */\n\n    /* Success block for __anext__ */\n    VISIT(c, expr, s->v.AsyncFor.target);\n    VISIT_SEQ(c, stmt, s->v.AsyncFor.body);\n    /* Mark jump as artificial */\n    ADDOP_JUMP(c, NO_LOCATION, JUMP, start);\n\n    compiler_pop_fblock(c, FOR_LOOP, start);\n\n    /* Except block for __anext__ */\n    USE_LABEL(c, except);\n\n    /* Use same line number as the iterator,\n     * as the END_ASYNC_FOR succeeds the `for`, not the body. */\n    loc = LOC(s->v.AsyncFor.iter);\n    ADDOP(c, loc, END_ASYNC_FOR);\n\n    /* `else` block */\n    VISIT_SEQ(c, stmt, s->v.For.orelse);\n\n    USE_LABEL(c, end);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_while(struct compiler *c, stmt_ty s)\n{\n    NEW_JUMP_TARGET_LABEL(c, loop);\n    NEW_JUMP_TARGET_LABEL(c, body);\n    NEW_JUMP_TARGET_LABEL(c, end);\n    NEW_JUMP_TARGET_LABEL(c, anchor);\n\n    USE_LABEL(c, loop);\n\n    RETURN_IF_ERROR(compiler_push_fblock(c, LOC(s), WHILE_LOOP, loop, end, NULL));\n    RETURN_IF_ERROR(compiler_jump_if(c, LOC(s), s->v.While.test, anchor, 0));\n\n    USE_LABEL(c, body);\n    VISIT_SEQ(c, stmt, s->v.While.body);\n    RETURN_IF_ERROR(compiler_jump_if(c, LOC(s), s->v.While.test, body, 1));\n\n    compiler_pop_fblock(c, WHILE_LOOP, loop);\n\n    USE_LABEL(c, anchor);\n    if (s->v.While.orelse) {\n        VISIT_SEQ(c, stmt, s->v.While.orelse);\n    }\n\n    USE_LABEL(c, end);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_return(struct compiler *c, stmt_ty s)\n{\n    location loc = LOC(s);\n    int preserve_tos = ((s->v.Return.value != NULL) &&\n                        (s->v.Return.value->kind != Constant_kind));\n    if (!_PyST_IsFunctionLike(c->u->u_ste)) {\n        return compiler_error(c, loc, \"'return' outside function\");\n    }\n    if (s->v.Return.value != NULL &&\n        c->u->u_ste->ste_coroutine && c->u->u_ste->ste_generator)\n    {\n        return compiler_error(c, loc, \"'return' with value in async generator\");\n    }\n\n    if (preserve_tos) {\n        VISIT(c, expr, s->v.Return.value);\n    } else {\n        /* Emit instruction with line number for return value */\n        if (s->v.Return.value != NULL) {\n            loc = LOC(s->v.Return.value);\n            ADDOP(c, loc, NOP);\n        }\n    }\n    if (s->v.Return.value == NULL || s->v.Return.value->lineno != s->lineno) {\n        loc = LOC(s);\n        ADDOP(c, loc, NOP);\n    }\n\n    RETURN_IF_ERROR(compiler_unwind_fblock_stack(c, &loc, preserve_tos, NULL));\n    if (s->v.Return.value == NULL) {\n        ADDOP_LOAD_CONST(c, loc, Py_None);\n    }\n    else if (!preserve_tos) {\n        ADDOP_LOAD_CONST(c, loc, s->v.Return.value->v.Constant.value);\n    }\n    ADDOP(c, loc, RETURN_VALUE);\n\n    return SUCCESS;\n}\n\nstatic int\ncompiler_break(struct compiler *c, location loc)\n{\n    struct fblockinfo *loop = NULL;\n    location origin_loc = loc;\n    /* Emit instruction with line number */\n    ADDOP(c, loc, NOP);\n    RETURN_IF_ERROR(compiler_unwind_fblock_stack(c, &loc, 0, &loop));\n    if (loop == NULL) {\n        return compiler_error(c, origin_loc, \"'break' outside loop\");\n    }\n    RETURN_IF_ERROR(compiler_unwind_fblock(c, &loc, loop, 0));\n    ADDOP_JUMP(c, loc, JUMP, loop->fb_exit);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_continue(struct compiler *c, location loc)\n{\n    struct fblockinfo *loop = NULL;\n    location origin_loc = loc;\n    /* Emit instruction with line number */\n    ADDOP(c, loc, NOP);\n    RETURN_IF_ERROR(compiler_unwind_fblock_stack(c, &loc, 0, &loop));\n    if (loop == NULL) {\n        return compiler_error(c, origin_loc, \"'continue' not properly in loop\");\n    }\n    ADDOP_JUMP(c, loc, JUMP, loop->fb_block);\n    return SUCCESS;\n}\n\n\nstatic location\nlocation_of_last_executing_statement(asdl_stmt_seq *stmts)\n{\n    for (Py_ssize_t i = asdl_seq_LEN(stmts) - 1; i >= 0; i++) {\n        location loc = LOC((stmt_ty)asdl_seq_GET(stmts, i));\n        if (loc.lineno > 0) {\n            return loc;\n        }\n    }\n    return NO_LOCATION;\n}\n\n/* Code generated for \"try: <body> finally: <finalbody>\" is as follows:\n\n        SETUP_FINALLY           L\n        <code for body>\n        POP_BLOCK\n        <code for finalbody>\n        JUMP E\n    L:\n        <code for finalbody>\n    E:\n\n   The special instructions use the block stack.  Each block\n   stack entry contains the instruction that created it (here\n   SETUP_FINALLY), the level of the value stack at the time the\n   block stack entry was created, and a label (here L).\n\n   SETUP_FINALLY:\n    Pushes the current value stack level and the label\n    onto the block stack.\n   POP_BLOCK:\n    Pops en entry from the block stack.\n\n   The block stack is unwound when an exception is raised:\n   when a SETUP_FINALLY entry is found, the raised and the caught\n   exceptions are pushed onto the value stack (and the exception\n   condition is cleared), and the interpreter jumps to the label\n   gotten from the block stack.\n*/\n\nstatic int\ncompiler_try_finally(struct compiler *c, stmt_ty s)\n{\n    location loc = LOC(s);\n\n    NEW_JUMP_TARGET_LABEL(c, body);\n    NEW_JUMP_TARGET_LABEL(c, end);\n    NEW_JUMP_TARGET_LABEL(c, exit);\n    NEW_JUMP_TARGET_LABEL(c, cleanup);\n\n    /* `try` block */\n    ADDOP_JUMP(c, loc, SETUP_FINALLY, end);\n\n    USE_LABEL(c, body);\n    RETURN_IF_ERROR(\n        compiler_push_fblock(c, loc, FINALLY_TRY, body, end,\n                             s->v.Try.finalbody));\n\n    if (s->v.Try.handlers && asdl_seq_LEN(s->v.Try.handlers)) {\n        RETURN_IF_ERROR(compiler_try_except(c, s));\n    }\n    else {\n        VISIT_SEQ(c, stmt, s->v.Try.body);\n    }\n    ADDOP(c, NO_LOCATION, POP_BLOCK);\n    compiler_pop_fblock(c, FINALLY_TRY, body);\n    VISIT_SEQ(c, stmt, s->v.Try.finalbody);\n\n    ADDOP_JUMP(c, NO_LOCATION, JUMP, exit);\n    /* `finally` block */\n\n    USE_LABEL(c, end);\n\n    loc = NO_LOCATION;\n    ADDOP_JUMP(c, loc, SETUP_CLEANUP, cleanup);\n    ADDOP(c, loc, PUSH_EXC_INFO);\n    RETURN_IF_ERROR(\n        compiler_push_fblock(c, loc, FINALLY_END, end, NO_LABEL, NULL));\n    VISIT_SEQ(c, stmt, s->v.Try.finalbody);\n    loc = location_of_last_executing_statement(s->v.Try.finalbody);\n    compiler_pop_fblock(c, FINALLY_END, end);\n\n    ADDOP_I(c, loc, RERAISE, 0);\n\n    USE_LABEL(c, cleanup);\n    POP_EXCEPT_AND_RERAISE(c, loc);\n\n    USE_LABEL(c, exit);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_try_star_finally(struct compiler *c, stmt_ty s)\n{\n    location loc = LOC(s);\n\n    NEW_JUMP_TARGET_LABEL(c, body);\n    NEW_JUMP_TARGET_LABEL(c, end);\n    NEW_JUMP_TARGET_LABEL(c, exit);\n    NEW_JUMP_TARGET_LABEL(c, cleanup);\n    /* `try` block */\n    ADDOP_JUMP(c, loc, SETUP_FINALLY, end);\n\n    USE_LABEL(c, body);\n    RETURN_IF_ERROR(\n        compiler_push_fblock(c, loc, FINALLY_TRY, body, end,\n                             s->v.TryStar.finalbody));\n\n    if (s->v.TryStar.handlers && asdl_seq_LEN(s->v.TryStar.handlers)) {\n        RETURN_IF_ERROR(compiler_try_star_except(c, s));\n    }\n    else {\n        VISIT_SEQ(c, stmt, s->v.TryStar.body);\n    }\n    ADDOP(c, NO_LOCATION, POP_BLOCK);\n    compiler_pop_fblock(c, FINALLY_TRY, body);\n    VISIT_SEQ(c, stmt, s->v.TryStar.finalbody);\n\n    ADDOP_JUMP(c, NO_LOCATION, JUMP, exit);\n\n    /* `finally` block */\n    USE_LABEL(c, end);\n\n    loc = NO_LOCATION;\n    ADDOP_JUMP(c, loc, SETUP_CLEANUP, cleanup);\n    ADDOP(c, loc, PUSH_EXC_INFO);\n    RETURN_IF_ERROR(\n        compiler_push_fblock(c, loc, FINALLY_END, end, NO_LABEL, NULL));\n\n    VISIT_SEQ(c, stmt, s->v.TryStar.finalbody);\n    loc = location_of_last_executing_statement(s->v.Try.finalbody);\n\n    compiler_pop_fblock(c, FINALLY_END, end);\n    ADDOP_I(c, loc, RERAISE, 0);\n\n    USE_LABEL(c, cleanup);\n    POP_EXCEPT_AND_RERAISE(c, loc);\n\n    USE_LABEL(c, exit);\n    return SUCCESS;\n}\n\n\n/*\n   Code generated for \"try: S except E1 as V1: S1 except E2 as V2: S2 ...\":\n   (The contents of the value stack is shown in [], with the top\n   at the right; 'tb' is trace-back info, 'val' the exception's\n   associated value, and 'exc' the exception.)\n\n   Value stack          Label   Instruction     Argument\n   []                           SETUP_FINALLY   L1\n   []                           <code for S>\n   []                           POP_BLOCK\n   []                           JUMP            L0\n\n   [exc]                L1:     <evaluate E1>           )\n   [exc, E1]                    CHECK_EXC_MATCH         )\n   [exc, bool]                  POP_JUMP_IF_FALSE L2    ) only if E1\n   [exc]                        <assign to V1>  (or POP if no V1)\n   []                           <code for S1>\n                                JUMP            L0\n\n   [exc]                L2:     <evaluate E2>\n   .............................etc.......................\n\n   [exc]                Ln+1:   RERAISE     # re-raise exception\n\n   []                   L0:     <next statement>\n\n   Of course, parts are not generated if Vi or Ei is not present.\n*/\nstatic int\ncompiler_try_except(struct compiler *c, stmt_ty s)\n{\n    location loc = LOC(s);\n    Py_ssize_t i, n;\n\n    NEW_JUMP_TARGET_LABEL(c, body);\n    NEW_JUMP_TARGET_LABEL(c, except);\n    NEW_JUMP_TARGET_LABEL(c, end);\n    NEW_JUMP_TARGET_LABEL(c, cleanup);\n\n    ADDOP_JUMP(c, loc, SETUP_FINALLY, except);\n\n    USE_LABEL(c, body);\n    RETURN_IF_ERROR(\n        compiler_push_fblock(c, loc, TRY_EXCEPT, body, NO_LABEL, NULL));\n    VISIT_SEQ(c, stmt, s->v.Try.body);\n    compiler_pop_fblock(c, TRY_EXCEPT, body);\n    ADDOP(c, NO_LOCATION, POP_BLOCK);\n    if (s->v.Try.orelse && asdl_seq_LEN(s->v.Try.orelse)) {\n        VISIT_SEQ(c, stmt, s->v.Try.orelse);\n    }\n    ADDOP_JUMP(c, NO_LOCATION, JUMP, end);\n    n = asdl_seq_LEN(s->v.Try.handlers);\n\n    USE_LABEL(c, except);\n\n    ADDOP_JUMP(c, NO_LOCATION, SETUP_CLEANUP, cleanup);\n    ADDOP(c, NO_LOCATION, PUSH_EXC_INFO);\n\n    /* Runtime will push a block here, so we need to account for that */\n    RETURN_IF_ERROR(\n        compiler_push_fblock(c, loc, EXCEPTION_HANDLER, NO_LABEL, NO_LABEL, NULL));\n\n    for (i = 0; i < n; i++) {\n        excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(\n            s->v.Try.handlers, i);\n        location loc = LOC(handler);\n        if (!handler->v.ExceptHandler.type && i < n-1) {\n            return compiler_error(c, loc, \"default 'except:' must be last\");\n        }\n        NEW_JUMP_TARGET_LABEL(c, next_except);\n        except = next_except;\n        if (handler->v.ExceptHandler.type) {\n            VISIT(c, expr, handler->v.ExceptHandler.type);\n            ADDOP(c, loc, CHECK_EXC_MATCH);\n            ADDOP_JUMP(c, loc, POP_JUMP_IF_FALSE, except);\n        }\n        if (handler->v.ExceptHandler.name) {\n            NEW_JUMP_TARGET_LABEL(c, cleanup_end);\n            NEW_JUMP_TARGET_LABEL(c, cleanup_body);\n\n            RETURN_IF_ERROR(\n                compiler_nameop(c, loc, handler->v.ExceptHandler.name, Store));\n\n            /*\n              try:\n                  # body\n              except type as name:\n                  try:\n                      # body\n                  finally:\n                      name = None # in case body contains \"del name\"\n                      del name\n            */\n\n            /* second try: */\n            ADDOP_JUMP(c, loc, SETUP_CLEANUP, cleanup_end);\n\n            USE_LABEL(c, cleanup_body);\n            RETURN_IF_ERROR(\n                compiler_push_fblock(c, loc, HANDLER_CLEANUP, cleanup_body,\n                                     NO_LABEL, handler->v.ExceptHandler.name));\n\n            /* second # body */\n            VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body);\n            compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body);\n            /* name = None; del name; # Mark as artificial */\n            ADDOP(c, NO_LOCATION, POP_BLOCK);\n            ADDOP(c, NO_LOCATION, POP_BLOCK);\n            ADDOP(c, NO_LOCATION, POP_EXCEPT);\n            ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);\n            RETURN_IF_ERROR(\n                compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store));\n            RETURN_IF_ERROR(\n                compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del));\n            ADDOP_JUMP(c, NO_LOCATION, JUMP, end);\n\n            /* except: */\n            USE_LABEL(c, cleanup_end);\n\n            /* name = None; del name; # artificial */\n            ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);\n            RETURN_IF_ERROR(\n                compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store));\n            RETURN_IF_ERROR(\n                compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del));\n\n            ADDOP_I(c, NO_LOCATION, RERAISE, 1);\n        }\n        else {\n            NEW_JUMP_TARGET_LABEL(c, cleanup_body);\n\n            ADDOP(c, loc, POP_TOP); /* exc_value */\n\n            USE_LABEL(c, cleanup_body);\n            RETURN_IF_ERROR(\n                compiler_push_fblock(c, loc, HANDLER_CLEANUP, cleanup_body,\n                                     NO_LABEL, NULL));\n\n            VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body);\n            compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body);\n            ADDOP(c, NO_LOCATION, POP_BLOCK);\n            ADDOP(c, NO_LOCATION, POP_EXCEPT);\n            ADDOP_JUMP(c, NO_LOCATION, JUMP, end);\n        }\n\n        USE_LABEL(c, except);\n    }\n    /* artificial */\n    compiler_pop_fblock(c, EXCEPTION_HANDLER, NO_LABEL);\n    ADDOP_I(c, NO_LOCATION, RERAISE, 0);\n\n    USE_LABEL(c, cleanup);\n    POP_EXCEPT_AND_RERAISE(c, NO_LOCATION);\n\n    USE_LABEL(c, end);\n    return SUCCESS;\n}\n\n/*\n   Code generated for \"try: S except* E1 as V1: S1 except* E2 as V2: S2 ...\":\n   (The contents of the value stack is shown in [], with the top\n   at the right; 'tb' is trace-back info, 'val' the exception instance,\n   and 'typ' the exception's type.)\n\n   Value stack                   Label         Instruction     Argument\n   []                                         SETUP_FINALLY         L1\n   []                                         <code for S>\n   []                                         POP_BLOCK\n   []                                         JUMP                  L0\n\n   [exc]                            L1:       BUILD_LIST   )  list for raised/reraised excs (\"result\")\n   [orig, res]                                COPY 2       )  make a copy of the original EG\n\n   [orig, res, exc]                           <evaluate E1>\n   [orig, res, exc, E1]                       CHECK_EG_MATCH\n   [orig, res, rest/exc, match?]              COPY 1\n   [orig, res, rest/exc, match?, match?]      POP_JUMP_IF_NONE      C1\n\n   [orig, res, rest, match]                   <assign to V1>  (or POP if no V1)\n\n   [orig, res, rest]                          SETUP_FINALLY         R1\n   [orig, res, rest]                          <code for S1>\n   [orig, res, rest]                          JUMP                  L2\n\n   [orig, res, rest, i, v]          R1:       LIST_APPEND   3 ) exc raised in except* body - add to res\n   [orig, res, rest, i]                       POP\n   [orig, res, rest]                          JUMP                  LE2\n\n   [orig, res, rest]                L2:       NOP  ) for lineno\n   [orig, res, rest]                          JUMP                  LE2\n\n   [orig, res, rest/exc, None]      C1:       POP\n\n   [orig, res, rest]               LE2:       <evaluate E2>\n   .............................etc.......................\n\n   [orig, res, rest]                Ln+1:     LIST_APPEND 1  ) add unhandled exc to res (could be None)\n\n   [orig, res]                                CALL_INTRINSIC_2 PREP_RERAISE_STAR\n   [exc]                                      COPY 1\n   [exc, exc]                                 POP_JUMP_IF_NOT_NONE  RER\n   [exc]                                      POP_TOP\n   []                                         JUMP                  L0\n\n   [exc]                            RER:      SWAP 2\n   [exc, prev_exc_info]                       POP_EXCEPT\n   [exc]                                      RERAISE               0\n\n   []                               L0:       <next statement>\n*/\nstatic int\ncompiler_try_star_except(struct compiler *c, stmt_ty s)\n{\n    location loc = LOC(s);\n\n    NEW_JUMP_TARGET_LABEL(c, body);\n    NEW_JUMP_TARGET_LABEL(c, except);\n    NEW_JUMP_TARGET_LABEL(c, orelse);\n    NEW_JUMP_TARGET_LABEL(c, end);\n    NEW_JUMP_TARGET_LABEL(c, cleanup);\n    NEW_JUMP_TARGET_LABEL(c, reraise_star);\n\n    ADDOP_JUMP(c, loc, SETUP_FINALLY, except);\n\n    USE_LABEL(c, body);\n    RETURN_IF_ERROR(\n        compiler_push_fblock(c, loc, TRY_EXCEPT, body, NO_LABEL, NULL));\n    VISIT_SEQ(c, stmt, s->v.TryStar.body);\n    compiler_pop_fblock(c, TRY_EXCEPT, body);\n    ADDOP(c, NO_LOCATION, POP_BLOCK);\n    ADDOP_JUMP(c, NO_LOCATION, JUMP, orelse);\n    Py_ssize_t n = asdl_seq_LEN(s->v.TryStar.handlers);\n\n    USE_LABEL(c, except);\n\n    ADDOP_JUMP(c, NO_LOCATION, SETUP_CLEANUP, cleanup);\n    ADDOP(c, NO_LOCATION, PUSH_EXC_INFO);\n\n    /* Runtime will push a block here, so we need to account for that */\n    RETURN_IF_ERROR(\n        compiler_push_fblock(c, loc, EXCEPTION_GROUP_HANDLER,\n                             NO_LABEL, NO_LABEL, \"except handler\"));\n\n    for (Py_ssize_t i = 0; i < n; i++) {\n        excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(\n            s->v.TryStar.handlers, i);\n        location loc = LOC(handler);\n        NEW_JUMP_TARGET_LABEL(c, next_except);\n        except = next_except;\n        NEW_JUMP_TARGET_LABEL(c, except_with_error);\n        NEW_JUMP_TARGET_LABEL(c, no_match);\n        if (i == 0) {\n            /* create empty list for exceptions raised/reraise in the except* blocks */\n            /*\n               [orig]       BUILD_LIST\n            */\n            /* Create a copy of the original EG */\n            /*\n               [orig, []]   COPY 2\n               [orig, [], exc]\n            */\n            ADDOP_I(c, loc, BUILD_LIST, 0);\n            ADDOP_I(c, loc, COPY, 2);\n        }\n        if (handler->v.ExceptHandler.type) {\n            VISIT(c, expr, handler->v.ExceptHandler.type);\n            ADDOP(c, loc, CHECK_EG_MATCH);\n            ADDOP_I(c, loc, COPY, 1);\n            ADDOP_JUMP(c, loc, POP_JUMP_IF_NONE, no_match);\n        }\n\n        NEW_JUMP_TARGET_LABEL(c, cleanup_end);\n        NEW_JUMP_TARGET_LABEL(c, cleanup_body);\n\n        if (handler->v.ExceptHandler.name) {\n            RETURN_IF_ERROR(\n                compiler_nameop(c, loc, handler->v.ExceptHandler.name, Store));\n        }\n        else {\n            ADDOP(c, loc, POP_TOP);  // match\n        }\n\n        /*\n          try:\n              # body\n          except type as name:\n              try:\n                  # body\n              finally:\n                  name = None # in case body contains \"del name\"\n                  del name\n        */\n        /* second try: */\n        ADDOP_JUMP(c, loc, SETUP_CLEANUP, cleanup_end);\n\n        USE_LABEL(c, cleanup_body);\n        RETURN_IF_ERROR(\n            compiler_push_fblock(c, loc, HANDLER_CLEANUP, cleanup_body,\n                                 NO_LABEL, handler->v.ExceptHandler.name));\n\n        /* second # body */\n        VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body);\n        compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body);\n        /* name = None; del name; # artificial */\n        ADDOP(c, NO_LOCATION, POP_BLOCK);\n        if (handler->v.ExceptHandler.name) {\n            ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);\n            RETURN_IF_ERROR(\n                compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store));\n            RETURN_IF_ERROR(\n                compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del));\n        }\n        ADDOP_JUMP(c, NO_LOCATION, JUMP, except);\n\n        /* except: */\n        USE_LABEL(c, cleanup_end);\n\n        /* name = None; del name; # artificial */\n        if (handler->v.ExceptHandler.name) {\n            ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);\n            RETURN_IF_ERROR(\n                compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store));\n            RETURN_IF_ERROR(\n                compiler_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del));\n        }\n\n        /* add exception raised to the res list */\n        ADDOP_I(c, NO_LOCATION, LIST_APPEND, 3); // exc\n        ADDOP(c, NO_LOCATION, POP_TOP); // lasti\n        ADDOP_JUMP(c, NO_LOCATION, JUMP, except_with_error);\n\n        USE_LABEL(c, except);\n        ADDOP(c, NO_LOCATION, NOP);  // to hold a propagated location info\n        ADDOP_JUMP(c, NO_LOCATION, JUMP, except_with_error);\n\n        USE_LABEL(c, no_match);\n        ADDOP(c, loc, POP_TOP);  // match (None)\n\n        USE_LABEL(c, except_with_error);\n\n        if (i == n - 1) {\n            /* Add exc to the list (if not None it's the unhandled part of the EG) */\n            ADDOP_I(c, NO_LOCATION, LIST_APPEND, 1);\n            ADDOP_JUMP(c, NO_LOCATION, JUMP, reraise_star);\n        }\n    }\n    /* artificial */\n    compiler_pop_fblock(c, EXCEPTION_GROUP_HANDLER, NO_LABEL);\n    NEW_JUMP_TARGET_LABEL(c, reraise);\n\n    USE_LABEL(c, reraise_star);\n    ADDOP_I(c, NO_LOCATION, CALL_INTRINSIC_2, INTRINSIC_PREP_RERAISE_STAR);\n    ADDOP_I(c, NO_LOCATION, COPY, 1);\n    ADDOP_JUMP(c, NO_LOCATION, POP_JUMP_IF_NOT_NONE, reraise);\n\n    /* Nothing to reraise */\n    ADDOP(c, NO_LOCATION, POP_TOP);\n    ADDOP(c, NO_LOCATION, POP_BLOCK);\n    ADDOP(c, NO_LOCATION, POP_EXCEPT);\n    ADDOP_JUMP(c, NO_LOCATION, JUMP, end);\n\n    USE_LABEL(c, reraise);\n    ADDOP(c, NO_LOCATION, POP_BLOCK);\n    ADDOP_I(c, NO_LOCATION, SWAP, 2);\n    ADDOP(c, NO_LOCATION, POP_EXCEPT);\n    ADDOP_I(c, NO_LOCATION, RERAISE, 0);\n\n    USE_LABEL(c, cleanup);\n    POP_EXCEPT_AND_RERAISE(c, NO_LOCATION);\n\n    USE_LABEL(c, orelse);\n    VISIT_SEQ(c, stmt, s->v.TryStar.orelse);\n\n    USE_LABEL(c, end);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_try(struct compiler *c, stmt_ty s) {\n    if (s->v.Try.finalbody && asdl_seq_LEN(s->v.Try.finalbody))\n        return compiler_try_finally(c, s);\n    else\n        return compiler_try_except(c, s);\n}\n\nstatic int\ncompiler_try_star(struct compiler *c, stmt_ty s)\n{\n    if (s->v.TryStar.finalbody && asdl_seq_LEN(s->v.TryStar.finalbody)) {\n        return compiler_try_star_finally(c, s);\n    }\n    else {\n        return compiler_try_star_except(c, s);\n    }\n}\n\nstatic int\ncompiler_import_as(struct compiler *c, location loc,\n                   identifier name, identifier asname)\n{\n    /* The IMPORT_NAME opcode was already generated.  This function\n       merely needs to bind the result to a name.\n\n       If there is a dot in name, we need to split it and emit a\n       IMPORT_FROM for each name.\n    */\n    Py_ssize_t len = PyUnicode_GET_LENGTH(name);\n    Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0, len, 1);\n    if (dot == -2) {\n        return ERROR;\n    }\n    if (dot != -1) {\n        /* Consume the base module name to get the first attribute */\n        while (1) {\n            Py_ssize_t pos = dot + 1;\n            PyObject *attr;\n            dot = PyUnicode_FindChar(name, '.', pos, len, 1);\n            if (dot == -2) {\n                return ERROR;\n            }\n            attr = PyUnicode_Substring(name, pos, (dot != -1) ? dot : len);\n            if (!attr) {\n                return ERROR;\n            }\n            ADDOP_N(c, loc, IMPORT_FROM, attr, names);\n            if (dot == -1) {\n                break;\n            }\n            ADDOP_I(c, loc, SWAP, 2);\n            ADDOP(c, loc, POP_TOP);\n        }\n        RETURN_IF_ERROR(compiler_nameop(c, loc, asname, Store));\n        ADDOP(c, loc, POP_TOP);\n        return SUCCESS;\n    }\n    return compiler_nameop(c, loc, asname, Store);\n}\n\nstatic int\ncompiler_import(struct compiler *c, stmt_ty s)\n{\n    location loc = LOC(s);\n    /* The Import node stores a module name like a.b.c as a single\n       string.  This is convenient for all cases except\n         import a.b.c as d\n       where we need to parse that string to extract the individual\n       module names.\n       XXX Perhaps change the representation to make this case simpler?\n     */\n    Py_ssize_t i, n = asdl_seq_LEN(s->v.Import.names);\n\n    PyObject *zero = _PyLong_GetZero();  // borrowed reference\n    for (i = 0; i < n; i++) {\n        alias_ty alias = (alias_ty)asdl_seq_GET(s->v.Import.names, i);\n        int r;\n\n        ADDOP_LOAD_CONST(c, loc, zero);\n        ADDOP_LOAD_CONST(c, loc, Py_None);\n        ADDOP_NAME(c, loc, IMPORT_NAME, alias->name, names);\n\n        if (alias->asname) {\n            r = compiler_import_as(c, loc, alias->name, alias->asname);\n            RETURN_IF_ERROR(r);\n        }\n        else {\n            identifier tmp = alias->name;\n            Py_ssize_t dot = PyUnicode_FindChar(\n                alias->name, '.', 0, PyUnicode_GET_LENGTH(alias->name), 1);\n            if (dot != -1) {\n                tmp = PyUnicode_Substring(alias->name, 0, dot);\n                if (tmp == NULL) {\n                    return ERROR;\n                }\n            }\n            r = compiler_nameop(c, loc, tmp, Store);\n            if (dot != -1) {\n                Py_DECREF(tmp);\n            }\n            RETURN_IF_ERROR(r);\n        }\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_from_import(struct compiler *c, stmt_ty s)\n{\n    Py_ssize_t n = asdl_seq_LEN(s->v.ImportFrom.names);\n\n    ADDOP_LOAD_CONST_NEW(c, LOC(s), PyLong_FromLong(s->v.ImportFrom.level));\n\n    PyObject *names = PyTuple_New(n);\n    if (!names) {\n        return ERROR;\n    }\n\n    /* build up the names */\n    for (Py_ssize_t i = 0; i < n; i++) {\n        alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i);\n        PyTuple_SET_ITEM(names, i, Py_NewRef(alias->name));\n    }\n\n    if (location_is_after(LOC(s), c->c_future.ff_location) &&\n        s->v.ImportFrom.module &&\n        _PyUnicode_EqualToASCIIString(s->v.ImportFrom.module, \"__future__\"))\n    {\n        Py_DECREF(names);\n        return compiler_error(c, LOC(s), \"from __future__ imports must occur \"\n                              \"at the beginning of the file\");\n    }\n    ADDOP_LOAD_CONST_NEW(c, LOC(s), names);\n\n    if (s->v.ImportFrom.module) {\n        ADDOP_NAME(c, LOC(s), IMPORT_NAME, s->v.ImportFrom.module, names);\n    }\n    else {\n        _Py_DECLARE_STR(empty, \"\");\n        ADDOP_NAME(c, LOC(s), IMPORT_NAME, &_Py_STR(empty), names);\n    }\n    for (Py_ssize_t i = 0; i < n; i++) {\n        alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i);\n        identifier store_name;\n\n        if (i == 0 && PyUnicode_READ_CHAR(alias->name, 0) == '*') {\n            assert(n == 1);\n            ADDOP_I(c, LOC(s), CALL_INTRINSIC_1, INTRINSIC_IMPORT_STAR);\n            ADDOP(c, NO_LOCATION, POP_TOP);\n            return SUCCESS;\n        }\n\n        ADDOP_NAME(c, LOC(s), IMPORT_FROM, alias->name, names);\n        store_name = alias->name;\n        if (alias->asname) {\n            store_name = alias->asname;\n        }\n\n        RETURN_IF_ERROR(compiler_nameop(c, LOC(s), store_name, Store));\n    }\n    /* remove imported module */\n    ADDOP(c, LOC(s), POP_TOP);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_assert(struct compiler *c, stmt_ty s)\n{\n    /* Always emit a warning if the test is a non-zero length tuple */\n    if ((s->v.Assert.test->kind == Tuple_kind &&\n        asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) ||\n        (s->v.Assert.test->kind == Constant_kind &&\n         PyTuple_Check(s->v.Assert.test->v.Constant.value) &&\n         PyTuple_Size(s->v.Assert.test->v.Constant.value) > 0))\n    {\n        RETURN_IF_ERROR(\n            compiler_warn(c, LOC(s), \"assertion is always true, \"\n                                     \"perhaps remove parentheses?\"));\n    }\n    if (c->c_optimize) {\n        return SUCCESS;\n    }\n    NEW_JUMP_TARGET_LABEL(c, end);\n    RETURN_IF_ERROR(compiler_jump_if(c, LOC(s), s->v.Assert.test, end, 1));\n    ADDOP(c, LOC(s), LOAD_ASSERTION_ERROR);\n    if (s->v.Assert.msg) {\n        VISIT(c, expr, s->v.Assert.msg);\n        ADDOP_I(c, LOC(s), CALL, 0);\n    }\n    ADDOP_I(c, LOC(s), RAISE_VARARGS, 1);\n\n    USE_LABEL(c, end);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_stmt_expr(struct compiler *c, location loc, expr_ty value)\n{\n    if (c->c_interactive && c->c_nestlevel <= 1) {\n        VISIT(c, expr, value);\n        ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_PRINT);\n        ADDOP(c, NO_LOCATION, POP_TOP);\n        return SUCCESS;\n    }\n\n    if (value->kind == Constant_kind) {\n        /* ignore constant statement */\n        ADDOP(c, loc, NOP);\n        return SUCCESS;\n    }\n\n    VISIT(c, expr, value);\n    ADDOP(c, NO_LOCATION, POP_TOP); /* artificial */\n    return SUCCESS;\n}\n\nstatic int\ncompiler_visit_stmt(struct compiler *c, stmt_ty s)\n{\n\n    switch (s->kind) {\n    case FunctionDef_kind:\n        return compiler_function(c, s, 0);\n    case ClassDef_kind:\n        return compiler_class(c, s);\n    case TypeAlias_kind:\n        return compiler_typealias(c, s);\n    case Return_kind:\n        return compiler_return(c, s);\n    case Delete_kind:\n        VISIT_SEQ(c, expr, s->v.Delete.targets)\n        break;\n    case Assign_kind:\n    {\n        Py_ssize_t n = asdl_seq_LEN(s->v.Assign.targets);\n        VISIT(c, expr, s->v.Assign.value);\n        for (Py_ssize_t i = 0; i < n; i++) {\n            if (i < n - 1) {\n                ADDOP_I(c, LOC(s), COPY, 1);\n            }\n            VISIT(c, expr,\n                  (expr_ty)asdl_seq_GET(s->v.Assign.targets, i));\n        }\n        break;\n    }\n    case AugAssign_kind:\n        return compiler_augassign(c, s);\n    case AnnAssign_kind:\n        return compiler_annassign(c, s);\n    case For_kind:\n        return compiler_for(c, s);\n    case While_kind:\n        return compiler_while(c, s);\n    case If_kind:\n        return compiler_if(c, s);\n    case Match_kind:\n        return compiler_match(c, s);\n    case Raise_kind:\n    {\n        Py_ssize_t n = 0;\n        if (s->v.Raise.exc) {\n            VISIT(c, expr, s->v.Raise.exc);\n            n++;\n            if (s->v.Raise.cause) {\n                VISIT(c, expr, s->v.Raise.cause);\n                n++;\n            }\n        }\n        ADDOP_I(c, LOC(s), RAISE_VARARGS, (int)n);\n        break;\n    }\n    case Try_kind:\n        return compiler_try(c, s);\n    case TryStar_kind:\n        return compiler_try_star(c, s);\n    case Assert_kind:\n        return compiler_assert(c, s);\n    case Import_kind:\n        return compiler_import(c, s);\n    case ImportFrom_kind:\n        return compiler_from_import(c, s);\n    case Global_kind:\n    case Nonlocal_kind:\n        break;\n    case Expr_kind:\n    {\n        return compiler_stmt_expr(c, LOC(s), s->v.Expr.value);\n    }\n    case Pass_kind:\n    {\n        ADDOP(c, LOC(s), NOP);\n        break;\n    }\n    case Break_kind:\n    {\n        return compiler_break(c, LOC(s));\n    }\n    case Continue_kind:\n    {\n        return compiler_continue(c, LOC(s));\n    }\n    case With_kind:\n        return compiler_with(c, s, 0);\n    case AsyncFunctionDef_kind:\n        return compiler_function(c, s, 1);\n    case AsyncWith_kind:\n        return compiler_async_with(c, s, 0);\n    case AsyncFor_kind:\n        return compiler_async_for(c, s);\n    }\n\n    return SUCCESS;\n}\n\nstatic int\nunaryop(unaryop_ty op)\n{\n    switch (op) {\n    case Invert:\n        return UNARY_INVERT;\n    case Not:\n        return UNARY_NOT;\n    case USub:\n        return UNARY_NEGATIVE;\n    default:\n        PyErr_Format(PyExc_SystemError,\n            \"unary op %d should not be possible\", op);\n        return 0;\n    }\n}\n\nstatic int\naddop_binary(struct compiler *c, location loc, operator_ty binop,\n             bool inplace)\n{\n    int oparg;\n    switch (binop) {\n        case Add:\n            oparg = inplace ? NB_INPLACE_ADD : NB_ADD;\n            break;\n        case Sub:\n            oparg = inplace ? NB_INPLACE_SUBTRACT : NB_SUBTRACT;\n            break;\n        case Mult:\n            oparg = inplace ? NB_INPLACE_MULTIPLY : NB_MULTIPLY;\n            break;\n        case MatMult:\n            oparg = inplace ? NB_INPLACE_MATRIX_MULTIPLY : NB_MATRIX_MULTIPLY;\n            break;\n        case Div:\n            oparg = inplace ? NB_INPLACE_TRUE_DIVIDE : NB_TRUE_DIVIDE;\n            break;\n        case Mod:\n            oparg = inplace ? NB_INPLACE_REMAINDER : NB_REMAINDER;\n            break;\n        case Pow:\n            oparg = inplace ? NB_INPLACE_POWER : NB_POWER;\n            break;\n        case LShift:\n            oparg = inplace ? NB_INPLACE_LSHIFT : NB_LSHIFT;\n            break;\n        case RShift:\n            oparg = inplace ? NB_INPLACE_RSHIFT : NB_RSHIFT;\n            break;\n        case BitOr:\n            oparg = inplace ? NB_INPLACE_OR : NB_OR;\n            break;\n        case BitXor:\n            oparg = inplace ? NB_INPLACE_XOR : NB_XOR;\n            break;\n        case BitAnd:\n            oparg = inplace ? NB_INPLACE_AND : NB_AND;\n            break;\n        case FloorDiv:\n            oparg = inplace ? NB_INPLACE_FLOOR_DIVIDE : NB_FLOOR_DIVIDE;\n            break;\n        default:\n            PyErr_Format(PyExc_SystemError, \"%s op %d should not be possible\",\n                         inplace ? \"inplace\" : \"binary\", binop);\n            return ERROR;\n    }\n    ADDOP_I(c, loc, BINARY_OP, oparg);\n    return SUCCESS;\n}\n\n\nstatic int\naddop_yield(struct compiler *c, location loc) {\n    if (c->u->u_ste->ste_generator && c->u->u_ste->ste_coroutine) {\n        ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_ASYNC_GEN_WRAP);\n    }\n    ADDOP_I(c, loc, YIELD_VALUE, 0);\n    ADDOP_I(c, loc, RESUME, 1);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_nameop(struct compiler *c, location loc,\n                identifier name, expr_context_ty ctx)\n{\n    int op, scope;\n    Py_ssize_t arg;\n    enum { OP_FAST, OP_GLOBAL, OP_DEREF, OP_NAME } optype;\n\n    PyObject *dict = c->u->u_metadata.u_names;\n    PyObject *mangled;\n\n    assert(!_PyUnicode_EqualToASCIIString(name, \"None\") &&\n           !_PyUnicode_EqualToASCIIString(name, \"True\") &&\n           !_PyUnicode_EqualToASCIIString(name, \"False\"));\n\n    if (forbidden_name(c, loc, name, ctx)) {\n        return ERROR;\n    }\n\n    mangled = _Py_Mangle(c->u->u_private, name);\n    if (!mangled) {\n        return ERROR;\n    }\n\n    op = 0;\n    optype = OP_NAME;\n    scope = _PyST_GetScope(c->u->u_ste, mangled);\n    switch (scope) {\n    case FREE:\n        dict = c->u->u_metadata.u_freevars;\n        optype = OP_DEREF;\n        break;\n    case CELL:\n        dict = c->u->u_metadata.u_cellvars;\n        optype = OP_DEREF;\n        break;\n    case LOCAL:\n        if (_PyST_IsFunctionLike(c->u->u_ste) ||\n                (PyDict_GetItem(c->u->u_metadata.u_fasthidden, mangled) == Py_True))\n            optype = OP_FAST;\n        break;\n    case GLOBAL_IMPLICIT:\n        if (_PyST_IsFunctionLike(c->u->u_ste))\n            optype = OP_GLOBAL;\n        break;\n    case GLOBAL_EXPLICIT:\n        optype = OP_GLOBAL;\n        break;\n    default:\n        /* scope can be 0 */\n        break;\n    }\n\n    /* XXX Leave assert here, but handle __doc__ and the like better */\n    assert(scope || PyUnicode_READ_CHAR(name, 0) == '_');\n\n    switch (optype) {\n    case OP_DEREF:\n        switch (ctx) {\n        case Load:\n            if (c->u->u_ste->ste_type == ClassBlock && !c->u->u_in_inlined_comp) {\n                op = LOAD_FROM_DICT_OR_DEREF;\n                // First load the locals\n                if (codegen_addop_noarg(INSTR_SEQUENCE(c), LOAD_LOCALS, loc) < 0) {\n                    return ERROR;\n                }\n            }\n            else if (c->u->u_ste->ste_can_see_class_scope) {\n                op = LOAD_FROM_DICT_OR_DEREF;\n                // First load the classdict\n                if (compiler_addop_o(c->u, loc, LOAD_DEREF,\n                                     c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {\n                    return ERROR;\n                }\n            }\n            else {\n                op = LOAD_DEREF;\n            }\n            break;\n        case Store: op = STORE_DEREF; break;\n        case Del: op = DELETE_DEREF; break;\n        }\n        break;\n    case OP_FAST:\n        switch (ctx) {\n        case Load: op = LOAD_FAST; break;\n        case Store: op = STORE_FAST; break;\n        case Del: op = DELETE_FAST; break;\n        }\n        ADDOP_N(c, loc, op, mangled, varnames);\n        return SUCCESS;\n    case OP_GLOBAL:\n        switch (ctx) {\n        case Load:\n            if (c->u->u_ste->ste_can_see_class_scope && scope == GLOBAL_IMPLICIT) {\n                op = LOAD_FROM_DICT_OR_GLOBALS;\n                // First load the classdict\n                if (compiler_addop_o(c->u, loc, LOAD_DEREF,\n                                     c->u->u_metadata.u_freevars, &_Py_ID(__classdict__)) < 0) {\n                    return ERROR;\n                }\n            } else {\n                op = LOAD_GLOBAL;\n            }\n            break;\n        case Store: op = STORE_GLOBAL; break;\n        case Del: op = DELETE_GLOBAL; break;\n        }\n        break;\n    case OP_NAME:\n        switch (ctx) {\n        case Load:\n            op = (c->u->u_ste->ste_type == ClassBlock\n                    && c->u->u_in_inlined_comp)\n                ? LOAD_GLOBAL\n                : LOAD_NAME;\n            break;\n        case Store: op = STORE_NAME; break;\n        case Del: op = DELETE_NAME; break;\n        }\n        break;\n    }\n\n    assert(op);\n    arg = dict_add_o(dict, mangled);\n    Py_DECREF(mangled);\n    if (arg < 0) {\n        return ERROR;\n    }\n    if (op == LOAD_GLOBAL) {\n        arg <<= 1;\n    }\n    return codegen_addop_i(INSTR_SEQUENCE(c), op, arg, loc);\n}\n\nstatic int\ncompiler_boolop(struct compiler *c, expr_ty e)\n{\n    int jumpi;\n    Py_ssize_t i, n;\n    asdl_expr_seq *s;\n\n    location loc = LOC(e);\n    assert(e->kind == BoolOp_kind);\n    if (e->v.BoolOp.op == And)\n        jumpi = POP_JUMP_IF_FALSE;\n    else\n        jumpi = POP_JUMP_IF_TRUE;\n    NEW_JUMP_TARGET_LABEL(c, end);\n    s = e->v.BoolOp.values;\n    n = asdl_seq_LEN(s) - 1;\n    assert(n >= 0);\n    for (i = 0; i < n; ++i) {\n        VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i));\n        ADDOP_I(c, loc, COPY, 1);\n        ADDOP_JUMP(c, loc, jumpi, end);\n        ADDOP(c, loc, POP_TOP);\n    }\n    VISIT(c, expr, (expr_ty)asdl_seq_GET(s, n));\n\n    USE_LABEL(c, end);\n    return SUCCESS;\n}\n\nstatic int\nstarunpack_helper(struct compiler *c, location loc,\n                  asdl_expr_seq *elts, int pushed,\n                  int build, int add, int extend, int tuple)\n{\n    Py_ssize_t n = asdl_seq_LEN(elts);\n    if (n > 2 && are_all_items_const(elts, 0, n)) {\n        PyObject *folded = PyTuple_New(n);\n        if (folded == NULL) {\n            return ERROR;\n        }\n        PyObject *val;\n        for (Py_ssize_t i = 0; i < n; i++) {\n            val = ((expr_ty)asdl_seq_GET(elts, i))->v.Constant.value;\n            PyTuple_SET_ITEM(folded, i, Py_NewRef(val));\n        }\n        if (tuple && !pushed) {\n            ADDOP_LOAD_CONST_NEW(c, loc, folded);\n        } else {\n            if (add == SET_ADD) {\n                Py_SETREF(folded, PyFrozenSet_New(folded));\n                if (folded == NULL) {\n                    return ERROR;\n                }\n            }\n            ADDOP_I(c, loc, build, pushed);\n            ADDOP_LOAD_CONST_NEW(c, loc, folded);\n            ADDOP_I(c, loc, extend, 1);\n            if (tuple) {\n                ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_LIST_TO_TUPLE);\n            }\n        }\n        return SUCCESS;\n    }\n\n    int big = n+pushed > STACK_USE_GUIDELINE;\n    int seen_star = 0;\n    for (Py_ssize_t i = 0; i < n; i++) {\n        expr_ty elt = asdl_seq_GET(elts, i);\n        if (elt->kind == Starred_kind) {\n            seen_star = 1;\n            break;\n        }\n    }\n    if (!seen_star && !big) {\n        for (Py_ssize_t i = 0; i < n; i++) {\n            expr_ty elt = asdl_seq_GET(elts, i);\n            VISIT(c, expr, elt);\n        }\n        if (tuple) {\n            ADDOP_I(c, loc, BUILD_TUPLE, n+pushed);\n        } else {\n            ADDOP_I(c, loc, build, n+pushed);\n        }\n        return SUCCESS;\n    }\n    int sequence_built = 0;\n    if (big) {\n        ADDOP_I(c, loc, build, pushed);\n        sequence_built = 1;\n    }\n    for (Py_ssize_t i = 0; i < n; i++) {\n        expr_ty elt = asdl_seq_GET(elts, i);\n        if (elt->kind == Starred_kind) {\n            if (sequence_built == 0) {\n                ADDOP_I(c, loc, build, i+pushed);\n                sequence_built = 1;\n            }\n            VISIT(c, expr, elt->v.Starred.value);\n            ADDOP_I(c, loc, extend, 1);\n        }\n        else {\n            VISIT(c, expr, elt);\n            if (sequence_built) {\n                ADDOP_I(c, loc, add, 1);\n            }\n        }\n    }\n    assert(sequence_built);\n    if (tuple) {\n        ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_LIST_TO_TUPLE);\n    }\n    return SUCCESS;\n}\n\nstatic int\nunpack_helper(struct compiler *c, location loc, asdl_expr_seq *elts)\n{\n    Py_ssize_t n = asdl_seq_LEN(elts);\n    int seen_star = 0;\n    for (Py_ssize_t i = 0; i < n; i++) {\n        expr_ty elt = asdl_seq_GET(elts, i);\n        if (elt->kind == Starred_kind && !seen_star) {\n            if ((i >= (1 << 8)) ||\n                (n-i-1 >= (INT_MAX >> 8))) {\n                return compiler_error(c, loc,\n                    \"too many expressions in \"\n                    \"star-unpacking assignment\");\n            }\n            ADDOP_I(c, loc, UNPACK_EX, (i + ((n-i-1) << 8)));\n            seen_star = 1;\n        }\n        else if (elt->kind == Starred_kind) {\n            return compiler_error(c, loc,\n                \"multiple starred expressions in assignment\");\n        }\n    }\n    if (!seen_star) {\n        ADDOP_I(c, loc, UNPACK_SEQUENCE, n);\n    }\n    return SUCCESS;\n}\n\nstatic int\nassignment_helper(struct compiler *c, location loc, asdl_expr_seq *elts)\n{\n    Py_ssize_t n = asdl_seq_LEN(elts);\n    RETURN_IF_ERROR(unpack_helper(c, loc, elts));\n    for (Py_ssize_t i = 0; i < n; i++) {\n        expr_ty elt = asdl_seq_GET(elts, i);\n        VISIT(c, expr, elt->kind != Starred_kind ? elt : elt->v.Starred.value);\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_list(struct compiler *c, expr_ty e)\n{\n    location loc = LOC(e);\n    asdl_expr_seq *elts = e->v.List.elts;\n    if (e->v.List.ctx == Store) {\n        return assignment_helper(c, loc, elts);\n    }\n    else if (e->v.List.ctx == Load) {\n        return starunpack_helper(c, loc, elts, 0,\n                                 BUILD_LIST, LIST_APPEND, LIST_EXTEND, 0);\n    }\n    else {\n        VISIT_SEQ(c, expr, elts);\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_tuple(struct compiler *c, expr_ty e)\n{\n    location loc = LOC(e);\n    asdl_expr_seq *elts = e->v.Tuple.elts;\n    if (e->v.Tuple.ctx == Store) {\n        return assignment_helper(c, loc, elts);\n    }\n    else if (e->v.Tuple.ctx == Load) {\n        return starunpack_helper(c, loc, elts, 0,\n                                 BUILD_LIST, LIST_APPEND, LIST_EXTEND, 1);\n    }\n    else {\n        VISIT_SEQ(c, expr, elts);\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_set(struct compiler *c, expr_ty e)\n{\n    location loc = LOC(e);\n    return starunpack_helper(c, loc, e->v.Set.elts, 0,\n                             BUILD_SET, SET_ADD, SET_UPDATE, 0);\n}\n\nstatic bool\nare_all_items_const(asdl_expr_seq *seq, Py_ssize_t begin, Py_ssize_t end)\n{\n    for (Py_ssize_t i = begin; i < end; i++) {\n        expr_ty key = (expr_ty)asdl_seq_GET(seq, i);\n        if (key == NULL || key->kind != Constant_kind) {\n            return false;\n        }\n    }\n    return true;\n}\n\nstatic int\ncompiler_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end)\n{\n    Py_ssize_t i, n = end - begin;\n    PyObject *keys, *key;\n    int big = n*2 > STACK_USE_GUIDELINE;\n    location loc = LOC(e);\n    if (n > 1 && !big && are_all_items_const(e->v.Dict.keys, begin, end)) {\n        for (i = begin; i < end; i++) {\n            VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i));\n        }\n        keys = PyTuple_New(n);\n        if (keys == NULL) {\n            return SUCCESS;\n        }\n        for (i = begin; i < end; i++) {\n            key = ((expr_ty)asdl_seq_GET(e->v.Dict.keys, i))->v.Constant.value;\n            PyTuple_SET_ITEM(keys, i - begin, Py_NewRef(key));\n        }\n        ADDOP_LOAD_CONST_NEW(c, loc, keys);\n        ADDOP_I(c, loc, BUILD_CONST_KEY_MAP, n);\n        return SUCCESS;\n    }\n    if (big) {\n        ADDOP_I(c, loc, BUILD_MAP, 0);\n    }\n    for (i = begin; i < end; i++) {\n        VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i));\n        VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i));\n        if (big) {\n            ADDOP_I(c, loc, MAP_ADD, 1);\n        }\n    }\n    if (!big) {\n        ADDOP_I(c, loc, BUILD_MAP, n);\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_dict(struct compiler *c, expr_ty e)\n{\n    location loc = LOC(e);\n    Py_ssize_t i, n, elements;\n    int have_dict;\n    int is_unpacking = 0;\n    n = asdl_seq_LEN(e->v.Dict.values);\n    have_dict = 0;\n    elements = 0;\n    for (i = 0; i < n; i++) {\n        is_unpacking = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i) == NULL;\n        if (is_unpacking) {\n            if (elements) {\n                RETURN_IF_ERROR(compiler_subdict(c, e, i - elements, i));\n                if (have_dict) {\n                    ADDOP_I(c, loc, DICT_UPDATE, 1);\n                }\n                have_dict = 1;\n                elements = 0;\n            }\n            if (have_dict == 0) {\n                ADDOP_I(c, loc, BUILD_MAP, 0);\n                have_dict = 1;\n            }\n            VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i));\n            ADDOP_I(c, loc, DICT_UPDATE, 1);\n        }\n        else {\n            if (elements*2 > STACK_USE_GUIDELINE) {\n                RETURN_IF_ERROR(compiler_subdict(c, e, i - elements, i + 1));\n                if (have_dict) {\n                    ADDOP_I(c, loc, DICT_UPDATE, 1);\n                }\n                have_dict = 1;\n                elements = 0;\n            }\n            else {\n                elements++;\n            }\n        }\n    }\n    if (elements) {\n        RETURN_IF_ERROR(compiler_subdict(c, e, n - elements, n));\n        if (have_dict) {\n            ADDOP_I(c, loc, DICT_UPDATE, 1);\n        }\n        have_dict = 1;\n    }\n    if (!have_dict) {\n        ADDOP_I(c, loc, BUILD_MAP, 0);\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_compare(struct compiler *c, expr_ty e)\n{\n    location loc = LOC(e);\n    Py_ssize_t i, n;\n\n    RETURN_IF_ERROR(check_compare(c, e));\n    VISIT(c, expr, e->v.Compare.left);\n    assert(asdl_seq_LEN(e->v.Compare.ops) > 0);\n    n = asdl_seq_LEN(e->v.Compare.ops) - 1;\n    if (n == 0) {\n        VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0));\n        ADDOP_COMPARE(c, loc, asdl_seq_GET(e->v.Compare.ops, 0));\n    }\n    else {\n        NEW_JUMP_TARGET_LABEL(c, cleanup);\n        for (i = 0; i < n; i++) {\n            VISIT(c, expr,\n                (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));\n            ADDOP_I(c, loc, SWAP, 2);\n            ADDOP_I(c, loc, COPY, 2);\n            ADDOP_COMPARE(c, loc, asdl_seq_GET(e->v.Compare.ops, i));\n            ADDOP_I(c, loc, COPY, 1);\n            ADDOP_JUMP(c, loc, POP_JUMP_IF_FALSE, cleanup);\n            ADDOP(c, loc, POP_TOP);\n        }\n        VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));\n        ADDOP_COMPARE(c, loc, asdl_seq_GET(e->v.Compare.ops, n));\n        NEW_JUMP_TARGET_LABEL(c, end);\n        ADDOP_JUMP(c, NO_LOCATION, JUMP, end);\n\n        USE_LABEL(c, cleanup);\n        ADDOP_I(c, loc, SWAP, 2);\n        ADDOP(c, loc, POP_TOP);\n\n        USE_LABEL(c, end);\n    }\n    return SUCCESS;\n}\n\nstatic PyTypeObject *\ninfer_type(expr_ty e)\n{\n    switch (e->kind) {\n    case Tuple_kind:\n        return &PyTuple_Type;\n    case List_kind:\n    case ListComp_kind:\n        return &PyList_Type;\n    case Dict_kind:\n    case DictComp_kind:\n        return &PyDict_Type;\n    case Set_kind:\n    case SetComp_kind:\n        return &PySet_Type;\n    case GeneratorExp_kind:\n        return &PyGen_Type;\n    case Lambda_kind:\n        return &PyFunction_Type;\n    case JoinedStr_kind:\n    case FormattedValue_kind:\n        return &PyUnicode_Type;\n    case Constant_kind:\n        return Py_TYPE(e->v.Constant.value);\n    default:\n        return NULL;\n    }\n}\n\nstatic int\ncheck_caller(struct compiler *c, expr_ty e)\n{\n    switch (e->kind) {\n    case Constant_kind:\n    case Tuple_kind:\n    case List_kind:\n    case ListComp_kind:\n    case Dict_kind:\n    case DictComp_kind:\n    case Set_kind:\n    case SetComp_kind:\n    case GeneratorExp_kind:\n    case JoinedStr_kind:\n    case FormattedValue_kind: {\n        location loc = LOC(e);\n        return compiler_warn(c, loc, \"'%.200s' object is not callable; \"\n                                     \"perhaps you missed a comma?\",\n                                     infer_type(e)->tp_name);\n    }\n    default:\n        return SUCCESS;\n    }\n}\n\nstatic int\ncheck_subscripter(struct compiler *c, expr_ty e)\n{\n    PyObject *v;\n\n    switch (e->kind) {\n    case Constant_kind:\n        v = e->v.Constant.value;\n        if (!(v == Py_None || v == Py_Ellipsis ||\n              PyLong_Check(v) || PyFloat_Check(v) || PyComplex_Check(v) ||\n              PyAnySet_Check(v)))\n        {\n            return SUCCESS;\n        }\n        /* fall through */\n    case Set_kind:\n    case SetComp_kind:\n    case GeneratorExp_kind:\n    case Lambda_kind: {\n        location loc = LOC(e);\n        return compiler_warn(c, loc, \"'%.200s' object is not subscriptable; \"\n                                     \"perhaps you missed a comma?\",\n                                     infer_type(e)->tp_name);\n    }\n    default:\n        return SUCCESS;\n    }\n}\n\nstatic int\ncheck_index(struct compiler *c, expr_ty e, expr_ty s)\n{\n    PyObject *v;\n\n    PyTypeObject *index_type = infer_type(s);\n    if (index_type == NULL\n        || PyType_FastSubclass(index_type, Py_TPFLAGS_LONG_SUBCLASS)\n        || index_type == &PySlice_Type) {\n        return SUCCESS;\n    }\n\n    switch (e->kind) {\n    case Constant_kind:\n        v = e->v.Constant.value;\n        if (!(PyUnicode_Check(v) || PyBytes_Check(v) || PyTuple_Check(v))) {\n            return SUCCESS;\n        }\n        /* fall through */\n    case Tuple_kind:\n    case List_kind:\n    case ListComp_kind:\n    case JoinedStr_kind:\n    case FormattedValue_kind: {\n        location loc = LOC(e);\n        return compiler_warn(c, loc, \"%.200s indices must be integers \"\n                                     \"or slices, not %.200s; \"\n                                     \"perhaps you missed a comma?\",\n                                     infer_type(e)->tp_name,\n                                     index_type->tp_name);\n    }\n    default:\n        return SUCCESS;\n    }\n}\n\nstatic int\nis_import_originated(struct compiler *c, expr_ty e)\n{\n    /* Check whether the global scope has an import named\n     e, if it is a Name object. For not traversing all the\n     scope stack every time this function is called, it will\n     only check the global scope to determine whether something\n     is imported or not. */\n\n    if (e->kind != Name_kind) {\n        return 0;\n    }\n\n    long flags = _PyST_GetSymbol(c->c_st->st_top, e->v.Name.id);\n    return flags & DEF_IMPORT;\n}\n\nstatic int\ncan_optimize_super_call(struct compiler *c, expr_ty attr)\n{\n    expr_ty e = attr->v.Attribute.value;\n    if (e->kind != Call_kind ||\n        e->v.Call.func->kind != Name_kind ||\n        !_PyUnicode_EqualToASCIIString(e->v.Call.func->v.Name.id, \"super\") ||\n        _PyUnicode_EqualToASCIIString(attr->v.Attribute.attr, \"__class__\") ||\n        asdl_seq_LEN(e->v.Call.keywords) != 0) {\n        return 0;\n    }\n    Py_ssize_t num_args = asdl_seq_LEN(e->v.Call.args);\n\n    PyObject *super_name = e->v.Call.func->v.Name.id;\n    // detect statically-visible shadowing of 'super' name\n    int scope = _PyST_GetScope(c->u->u_ste, super_name);\n    if (scope != GLOBAL_IMPLICIT) {\n        return 0;\n    }\n    scope = _PyST_GetScope(c->c_st->st_top, super_name);\n    if (scope != 0) {\n        return 0;\n    }\n\n    if (num_args == 2) {\n        for (Py_ssize_t i = 0; i < num_args; i++) {\n            expr_ty elt = asdl_seq_GET(e->v.Call.args, i);\n            if (elt->kind == Starred_kind) {\n                return 0;\n            }\n        }\n        // exactly two non-starred args; we can just load\n        // the provided args\n        return 1;\n    }\n\n    if (num_args != 0) {\n        return 0;\n    }\n    // we need the following for zero-arg super():\n\n    // enclosing function should have at least one argument\n    if (c->u->u_metadata.u_argcount == 0 &&\n        c->u->u_metadata.u_posonlyargcount == 0) {\n        return 0;\n    }\n    // __class__ cell should be available\n    if (get_ref_type(c, &_Py_ID(__class__)) == FREE) {\n        return 1;\n    }\n    return 0;\n}\n\nstatic int\nload_args_for_super(struct compiler *c, expr_ty e) {\n    location loc = LOC(e);\n\n    // load super() global\n    PyObject *super_name = e->v.Call.func->v.Name.id;\n    RETURN_IF_ERROR(compiler_nameop(c, loc, super_name, Load));\n\n    if (asdl_seq_LEN(e->v.Call.args) == 2) {\n        VISIT(c, expr, asdl_seq_GET(e->v.Call.args, 0));\n        VISIT(c, expr, asdl_seq_GET(e->v.Call.args, 1));\n        return SUCCESS;\n    }\n\n    // load __class__ cell\n    PyObject *name = &_Py_ID(__class__);\n    assert(get_ref_type(c, name) == FREE);\n    RETURN_IF_ERROR(compiler_nameop(c, loc, name, Load));\n\n    // load self (first argument)\n    Py_ssize_t i = 0;\n    PyObject *key, *value;\n    if (!PyDict_Next(c->u->u_metadata.u_varnames, &i, &key, &value)) {\n        return ERROR;\n    }\n    RETURN_IF_ERROR(compiler_nameop(c, loc, key, Load));\n\n    return SUCCESS;\n}\n\n// If an attribute access spans multiple lines, update the current start\n// location to point to the attribute name.\nstatic location\nupdate_start_location_to_match_attr(struct compiler *c, location loc,\n                                    expr_ty attr)\n{\n    assert(attr->kind == Attribute_kind);\n    if (loc.lineno != attr->end_lineno) {\n        loc.lineno = attr->end_lineno;\n        int len = (int)PyUnicode_GET_LENGTH(attr->v.Attribute.attr);\n        if (len <= attr->end_col_offset) {\n            loc.col_offset = attr->end_col_offset - len;\n        }\n        else {\n            // GH-94694: Somebody's compiling weird ASTs. Just drop the columns:\n            loc.col_offset = -1;\n            loc.end_col_offset = -1;\n        }\n        // Make sure the end position still follows the start position, even for\n        // weird ASTs:\n        loc.end_lineno = Py_MAX(loc.lineno, loc.end_lineno);\n        if (loc.lineno == loc.end_lineno) {\n            loc.end_col_offset = Py_MAX(loc.col_offset, loc.end_col_offset);\n        }\n    }\n    return loc;\n}\n\n// Return 1 if the method call was optimized, 0 if not, and -1 on error.\nstatic int\nmaybe_optimize_method_call(struct compiler *c, expr_ty e)\n{\n    Py_ssize_t argsl, i, kwdsl;\n    expr_ty meth = e->v.Call.func;\n    asdl_expr_seq *args = e->v.Call.args;\n    asdl_keyword_seq *kwds = e->v.Call.keywords;\n\n    /* Check that the call node is an attribute access */\n    if (meth->kind != Attribute_kind || meth->v.Attribute.ctx != Load) {\n        return 0;\n    }\n\n    /* Check that the base object is not something that is imported */\n    if (is_import_originated(c, meth->v.Attribute.value)) {\n        return 0;\n    }\n\n    /* Check that there aren't too many arguments */\n    argsl = asdl_seq_LEN(args);\n    kwdsl = asdl_seq_LEN(kwds);\n    if (argsl + kwdsl + (kwdsl != 0) >= STACK_USE_GUIDELINE) {\n        return 0;\n    }\n    /* Check that there are no *varargs types of arguments. */\n    for (i = 0; i < argsl; i++) {\n        expr_ty elt = asdl_seq_GET(args, i);\n        if (elt->kind == Starred_kind) {\n            return 0;\n        }\n    }\n\n    for (i = 0; i < kwdsl; i++) {\n        keyword_ty kw = asdl_seq_GET(kwds, i);\n        if (kw->arg == NULL) {\n            return 0;\n        }\n    }\n\n    /* Alright, we can optimize the code. */\n    location loc = LOC(meth);\n\n    if (can_optimize_super_call(c, meth)) {\n        RETURN_IF_ERROR(load_args_for_super(c, meth->v.Attribute.value));\n        int opcode = asdl_seq_LEN(meth->v.Attribute.value->v.Call.args) ?\n            LOAD_SUPER_METHOD : LOAD_ZERO_SUPER_METHOD;\n        ADDOP_NAME(c, loc, opcode, meth->v.Attribute.attr, names);\n        loc = update_start_location_to_match_attr(c, loc, meth);\n        ADDOP(c, loc, NOP);\n    } else {\n        VISIT(c, expr, meth->v.Attribute.value);\n        loc = update_start_location_to_match_attr(c, loc, meth);\n        ADDOP_NAME(c, loc, LOAD_METHOD, meth->v.Attribute.attr, names);\n    }\n\n    VISIT_SEQ(c, expr, e->v.Call.args);\n\n    if (kwdsl) {\n        VISIT_SEQ(c, keyword, kwds);\n        RETURN_IF_ERROR(\n            compiler_call_simple_kw_helper(c, loc, kwds, kwdsl));\n    }\n    loc = update_start_location_to_match_attr(c, LOC(e), meth);\n    ADDOP_I(c, loc, CALL, argsl + kwdsl);\n    return 1;\n}\n\nstatic int\nvalidate_keywords(struct compiler *c, asdl_keyword_seq *keywords)\n{\n    Py_ssize_t nkeywords = asdl_seq_LEN(keywords);\n    for (Py_ssize_t i = 0; i < nkeywords; i++) {\n        keyword_ty key = ((keyword_ty)asdl_seq_GET(keywords, i));\n        if (key->arg == NULL) {\n            continue;\n        }\n        location loc = LOC(key);\n        if (forbidden_name(c, loc, key->arg, Store)) {\n            return ERROR;\n        }\n        for (Py_ssize_t j = i + 1; j < nkeywords; j++) {\n            keyword_ty other = ((keyword_ty)asdl_seq_GET(keywords, j));\n            if (other->arg && !PyUnicode_Compare(key->arg, other->arg)) {\n                compiler_error(c, LOC(other), \"keyword argument repeated: %U\", key->arg);\n                return ERROR;\n            }\n        }\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_call(struct compiler *c, expr_ty e)\n{\n    RETURN_IF_ERROR(validate_keywords(c, e->v.Call.keywords));\n    int ret = maybe_optimize_method_call(c, e);\n    if (ret < 0) {\n        return ERROR;\n    }\n    if (ret == 1) {\n        return SUCCESS;\n    }\n    RETURN_IF_ERROR(check_caller(c, e->v.Call.func));\n    location loc = LOC(e->v.Call.func);\n    ADDOP(c, loc, PUSH_NULL);\n    VISIT(c, expr, e->v.Call.func);\n    loc = LOC(e);\n    return compiler_call_helper(c, loc, 0,\n                                e->v.Call.args,\n                                e->v.Call.keywords);\n}\n\nstatic int\ncompiler_joined_str(struct compiler *c, expr_ty e)\n{\n    location loc = LOC(e);\n    Py_ssize_t value_count = asdl_seq_LEN(e->v.JoinedStr.values);\n    if (value_count > STACK_USE_GUIDELINE) {\n        _Py_DECLARE_STR(empty, \"\");\n        ADDOP_LOAD_CONST_NEW(c, loc, Py_NewRef(&_Py_STR(empty)));\n        ADDOP_NAME(c, loc, LOAD_METHOD, &_Py_ID(join), names);\n        ADDOP_I(c, loc, BUILD_LIST, 0);\n        for (Py_ssize_t i = 0; i < asdl_seq_LEN(e->v.JoinedStr.values); i++) {\n            VISIT(c, expr, asdl_seq_GET(e->v.JoinedStr.values, i));\n            ADDOP_I(c, loc, LIST_APPEND, 1);\n        }\n        ADDOP_I(c, loc, CALL, 1);\n    }\n    else {\n        VISIT_SEQ(c, expr, e->v.JoinedStr.values);\n        if (asdl_seq_LEN(e->v.JoinedStr.values) != 1) {\n            ADDOP_I(c, loc, BUILD_STRING, asdl_seq_LEN(e->v.JoinedStr.values));\n        }\n    }\n    return SUCCESS;\n}\n\n/* Used to implement f-strings. Format a single value. */\nstatic int\ncompiler_formatted_value(struct compiler *c, expr_ty e)\n{\n    /* Our oparg encodes 2 pieces of information: the conversion\n       character, and whether or not a format_spec was provided.\n\n       Convert the conversion char to 3 bits:\n           : 000  0x0  FVC_NONE   The default if nothing specified.\n       !s  : 001  0x1  FVC_STR\n       !r  : 010  0x2  FVC_REPR\n       !a  : 011  0x3  FVC_ASCII\n\n       next bit is whether or not we have a format spec:\n       yes : 100  0x4\n       no  : 000  0x0\n    */\n\n    int conversion = e->v.FormattedValue.conversion;\n    int oparg;\n\n    /* The expression to be formatted. */\n    VISIT(c, expr, e->v.FormattedValue.value);\n\n    switch (conversion) {\n    case 's': oparg = FVC_STR;   break;\n    case 'r': oparg = FVC_REPR;  break;\n    case 'a': oparg = FVC_ASCII; break;\n    case -1:  oparg = FVC_NONE;  break;\n    default:\n        PyErr_Format(PyExc_SystemError,\n                     \"Unrecognized conversion character %d\", conversion);\n        return ERROR;\n    }\n    if (e->v.FormattedValue.format_spec) {\n        /* Evaluate the format spec, and update our opcode arg. */\n        VISIT(c, expr, e->v.FormattedValue.format_spec);\n        oparg |= FVS_HAVE_SPEC;\n    }\n\n    /* And push our opcode and oparg */\n    location loc = LOC(e);\n    ADDOP_I(c, loc, FORMAT_VALUE, oparg);\n\n    return SUCCESS;\n}\n\nstatic int\ncompiler_subkwargs(struct compiler *c, location loc,\n                   asdl_keyword_seq *keywords,\n                   Py_ssize_t begin, Py_ssize_t end)\n{\n    Py_ssize_t i, n = end - begin;\n    keyword_ty kw;\n    PyObject *keys, *key;\n    assert(n > 0);\n    int big = n*2 > STACK_USE_GUIDELINE;\n    if (n > 1 && !big) {\n        for (i = begin; i < end; i++) {\n            kw = asdl_seq_GET(keywords, i);\n            VISIT(c, expr, kw->value);\n        }\n        keys = PyTuple_New(n);\n        if (keys == NULL) {\n            return ERROR;\n        }\n        for (i = begin; i < end; i++) {\n            key = ((keyword_ty) asdl_seq_GET(keywords, i))->arg;\n            PyTuple_SET_ITEM(keys, i - begin, Py_NewRef(key));\n        }\n        ADDOP_LOAD_CONST_NEW(c, loc, keys);\n        ADDOP_I(c, loc, BUILD_CONST_KEY_MAP, n);\n        return SUCCESS;\n    }\n    if (big) {\n        ADDOP_I(c, NO_LOCATION, BUILD_MAP, 0);\n    }\n    for (i = begin; i < end; i++) {\n        kw = asdl_seq_GET(keywords, i);\n        ADDOP_LOAD_CONST(c, loc, kw->arg);\n        VISIT(c, expr, kw->value);\n        if (big) {\n            ADDOP_I(c, NO_LOCATION, MAP_ADD, 1);\n        }\n    }\n    if (!big) {\n        ADDOP_I(c, loc, BUILD_MAP, n);\n    }\n    return SUCCESS;\n}\n\n/* Used by compiler_call_helper and maybe_optimize_method_call to emit\n * KW_NAMES before CALL.\n */\nstatic int\ncompiler_call_simple_kw_helper(struct compiler *c, location loc,\n                               asdl_keyword_seq *keywords, Py_ssize_t nkwelts)\n{\n    PyObject *names;\n    names = PyTuple_New(nkwelts);\n    if (names == NULL) {\n        return ERROR;\n    }\n    for (int i = 0; i < nkwelts; i++) {\n        keyword_ty kw = asdl_seq_GET(keywords, i);\n        PyTuple_SET_ITEM(names, i, Py_NewRef(kw->arg));\n    }\n    Py_ssize_t arg = compiler_add_const(c->c_const_cache, c->u, names);\n    if (arg < 0) {\n        return ERROR;\n    }\n    Py_DECREF(names);\n    ADDOP_I(c, loc, KW_NAMES, arg);\n    return SUCCESS;\n}\n\n\n/* shared code between compiler_call and compiler_class */\nstatic int\ncompiler_call_helper(struct compiler *c, location loc,\n                     int n, /* Args already pushed */\n                     asdl_expr_seq *args,\n                     asdl_keyword_seq *keywords)\n{\n    Py_ssize_t i, nseen, nelts, nkwelts;\n\n    RETURN_IF_ERROR(validate_keywords(c, keywords));\n\n    nelts = asdl_seq_LEN(args);\n    nkwelts = asdl_seq_LEN(keywords);\n\n    if (nelts + nkwelts*2 > STACK_USE_GUIDELINE) {\n         goto ex_call;\n    }\n    for (i = 0; i < nelts; i++) {\n        expr_ty elt = asdl_seq_GET(args, i);\n        if (elt->kind == Starred_kind) {\n            goto ex_call;\n        }\n    }\n    for (i = 0; i < nkwelts; i++) {\n        keyword_ty kw = asdl_seq_GET(keywords, i);\n        if (kw->arg == NULL) {\n            goto ex_call;\n        }\n    }\n\n    /* No * or ** args, so can use faster calling sequence */\n    for (i = 0; i < nelts; i++) {\n        expr_ty elt = asdl_seq_GET(args, i);\n        assert(elt->kind != Starred_kind);\n        VISIT(c, expr, elt);\n    }\n    if (nkwelts) {\n        VISIT_SEQ(c, keyword, keywords);\n        RETURN_IF_ERROR(\n            compiler_call_simple_kw_helper(c, loc, keywords, nkwelts));\n    }\n    ADDOP_I(c, loc, CALL, n + nelts + nkwelts);\n    return SUCCESS;\n\nex_call:\n\n    /* Do positional arguments. */\n    if (n ==0 && nelts == 1 && ((expr_ty)asdl_seq_GET(args, 0))->kind == Starred_kind) {\n        VISIT(c, expr, ((expr_ty)asdl_seq_GET(args, 0))->v.Starred.value);\n    }\n    else {\n        RETURN_IF_ERROR(starunpack_helper(c, loc, args, n, BUILD_LIST,\n                                          LIST_APPEND, LIST_EXTEND, 1));\n    }\n    /* Then keyword arguments */\n    if (nkwelts) {\n        /* Has a new dict been pushed */\n        int have_dict = 0;\n\n        nseen = 0;  /* the number of keyword arguments on the stack following */\n        for (i = 0; i < nkwelts; i++) {\n            keyword_ty kw = asdl_seq_GET(keywords, i);\n            if (kw->arg == NULL) {\n                /* A keyword argument unpacking. */\n                if (nseen) {\n                    RETURN_IF_ERROR(compiler_subkwargs(c, loc, keywords, i - nseen, i));\n                    if (have_dict) {\n                        ADDOP_I(c, loc, DICT_MERGE, 1);\n                    }\n                    have_dict = 1;\n                    nseen = 0;\n                }\n                if (!have_dict) {\n                    ADDOP_I(c, loc, BUILD_MAP, 0);\n                    have_dict = 1;\n                }\n                VISIT(c, expr, kw->value);\n                ADDOP_I(c, loc, DICT_MERGE, 1);\n            }\n            else {\n                nseen++;\n            }\n        }\n        if (nseen) {\n            /* Pack up any trailing keyword arguments. */\n            RETURN_IF_ERROR(compiler_subkwargs(c, loc, keywords, nkwelts - nseen, nkwelts));\n            if (have_dict) {\n                ADDOP_I(c, loc, DICT_MERGE, 1);\n            }\n            have_dict = 1;\n        }\n        assert(have_dict);\n    }\n    ADDOP_I(c, loc, CALL_FUNCTION_EX, nkwelts > 0);\n    return SUCCESS;\n}\n\n\n/* List and set comprehensions and generator expressions work by creating a\n  nested function to perform the actual iteration. This means that the\n  iteration variables don't leak into the current scope.\n  The defined function is called immediately following its definition, with the\n  result of that call being the result of the expression.\n  The LC/SC version returns the populated container, while the GE version is\n  flagged in symtable.c as a generator, so it returns the generator object\n  when the function is called.\n\n  Possible cleanups:\n    - iterate over the generator sequence instead of using recursion\n*/\n\n\nstatic int\ncompiler_comprehension_generator(struct compiler *c, location loc,\n                                 asdl_comprehension_seq *generators, int gen_index,\n                                 int depth,\n                                 expr_ty elt, expr_ty val, int type,\n                                 int iter_on_stack)\n{\n    comprehension_ty gen;\n    gen = (comprehension_ty)asdl_seq_GET(generators, gen_index);\n    if (gen->is_async) {\n        return compiler_async_comprehension_generator(\n            c, loc, generators, gen_index, depth, elt, val, type,\n            iter_on_stack);\n    } else {\n        return compiler_sync_comprehension_generator(\n            c, loc, generators, gen_index, depth, elt, val, type,\n            iter_on_stack);\n    }\n}\n\nstatic int\ncompiler_sync_comprehension_generator(struct compiler *c, location loc,\n                                      asdl_comprehension_seq *generators,\n                                      int gen_index, int depth,\n                                      expr_ty elt, expr_ty val, int type,\n                                      int iter_on_stack)\n{\n    /* generate code for the iterator, then each of the ifs,\n       and then write to the element */\n\n    NEW_JUMP_TARGET_LABEL(c, start);\n    NEW_JUMP_TARGET_LABEL(c, if_cleanup);\n    NEW_JUMP_TARGET_LABEL(c, anchor);\n\n    comprehension_ty gen = (comprehension_ty)asdl_seq_GET(generators,\n                                                          gen_index);\n\n    if (!iter_on_stack) {\n        if (gen_index == 0) {\n            /* Receive outermost iter as an implicit argument */\n            c->u->u_metadata.u_argcount = 1;\n            ADDOP_I(c, loc, LOAD_FAST, 0);\n        }\n        else {\n            /* Sub-iter - calculate on the fly */\n            /* Fast path for the temporary variable assignment idiom:\n                for y in [f(x)]\n            */\n            asdl_expr_seq *elts;\n            switch (gen->iter->kind) {\n                case List_kind:\n                    elts = gen->iter->v.List.elts;\n                    break;\n                case Tuple_kind:\n                    elts = gen->iter->v.Tuple.elts;\n                    break;\n                default:\n                    elts = NULL;\n            }\n            if (asdl_seq_LEN(elts) == 1) {\n                expr_ty elt = asdl_seq_GET(elts, 0);\n                if (elt->kind != Starred_kind) {\n                    VISIT(c, expr, elt);\n                    start = NO_LABEL;\n                }\n            }\n            if (IS_LABEL(start)) {\n                VISIT(c, expr, gen->iter);\n                ADDOP(c, loc, GET_ITER);\n            }\n        }\n    }\n    if (IS_LABEL(start)) {\n        depth++;\n        USE_LABEL(c, start);\n        ADDOP_JUMP(c, loc, FOR_ITER, anchor);\n    }\n    VISIT(c, expr, gen->target);\n\n    /* XXX this needs to be cleaned up...a lot! */\n    Py_ssize_t n = asdl_seq_LEN(gen->ifs);\n    for (Py_ssize_t i = 0; i < n; i++) {\n        expr_ty e = (expr_ty)asdl_seq_GET(gen->ifs, i);\n        RETURN_IF_ERROR(compiler_jump_if(c, loc, e, if_cleanup, 0));\n    }\n\n    if (++gen_index < asdl_seq_LEN(generators)) {\n        RETURN_IF_ERROR(\n            compiler_comprehension_generator(c, loc,\n                                             generators, gen_index, depth,\n                                             elt, val, type, 0));\n    }\n\n    location elt_loc = LOC(elt);\n\n    /* only append after the last for generator */\n    if (gen_index >= asdl_seq_LEN(generators)) {\n        /* comprehension specific code */\n        switch (type) {\n        case COMP_GENEXP:\n            VISIT(c, expr, elt);\n            ADDOP_YIELD(c, elt_loc);\n            ADDOP(c, elt_loc, POP_TOP);\n            break;\n        case COMP_LISTCOMP:\n            VISIT(c, expr, elt);\n            ADDOP_I(c, elt_loc, LIST_APPEND, depth + 1);\n            break;\n        case COMP_SETCOMP:\n            VISIT(c, expr, elt);\n            ADDOP_I(c, elt_loc, SET_ADD, depth + 1);\n            break;\n        case COMP_DICTCOMP:\n            /* With '{k: v}', k is evaluated before v, so we do\n               the same. */\n            VISIT(c, expr, elt);\n            VISIT(c, expr, val);\n            elt_loc = LOCATION(elt->lineno,\n                               val->end_lineno,\n                               elt->col_offset,\n                               val->end_col_offset);\n            ADDOP_I(c, elt_loc, MAP_ADD, depth + 1);\n            break;\n        default:\n            return ERROR;\n        }\n    }\n\n    USE_LABEL(c, if_cleanup);\n    if (IS_LABEL(start)) {\n        ADDOP_JUMP(c, elt_loc, JUMP, start);\n\n        USE_LABEL(c, anchor);\n        ADDOP(c, NO_LOCATION, END_FOR);\n    }\n\n    return SUCCESS;\n}\n\nstatic int\ncompiler_async_comprehension_generator(struct compiler *c, location loc,\n                                      asdl_comprehension_seq *generators,\n                                      int gen_index, int depth,\n                                      expr_ty elt, expr_ty val, int type,\n                                      int iter_on_stack)\n{\n    NEW_JUMP_TARGET_LABEL(c, start);\n    NEW_JUMP_TARGET_LABEL(c, except);\n    NEW_JUMP_TARGET_LABEL(c, if_cleanup);\n\n    comprehension_ty gen = (comprehension_ty)asdl_seq_GET(generators,\n                                                          gen_index);\n\n    if (!iter_on_stack) {\n        if (gen_index == 0) {\n            /* Receive outermost iter as an implicit argument */\n            c->u->u_metadata.u_argcount = 1;\n            ADDOP_I(c, loc, LOAD_FAST, 0);\n        }\n        else {\n            /* Sub-iter - calculate on the fly */\n            VISIT(c, expr, gen->iter);\n            ADDOP(c, loc, GET_AITER);\n        }\n    }\n\n    USE_LABEL(c, start);\n    /* Runtime will push a block here, so we need to account for that */\n    RETURN_IF_ERROR(\n        compiler_push_fblock(c, loc, ASYNC_COMPREHENSION_GENERATOR,\n                             start, NO_LABEL, NULL));\n\n    ADDOP_JUMP(c, loc, SETUP_FINALLY, except);\n    ADDOP(c, loc, GET_ANEXT);\n    ADDOP_LOAD_CONST(c, loc, Py_None);\n    ADD_YIELD_FROM(c, loc, 1);\n    ADDOP(c, loc, POP_BLOCK);\n    VISIT(c, expr, gen->target);\n\n    Py_ssize_t n = asdl_seq_LEN(gen->ifs);\n    for (Py_ssize_t i = 0; i < n; i++) {\n        expr_ty e = (expr_ty)asdl_seq_GET(gen->ifs, i);\n        RETURN_IF_ERROR(compiler_jump_if(c, loc, e, if_cleanup, 0));\n    }\n\n    depth++;\n    if (++gen_index < asdl_seq_LEN(generators)) {\n        RETURN_IF_ERROR(\n            compiler_comprehension_generator(c, loc,\n                                             generators, gen_index, depth,\n                                             elt, val, type, 0));\n    }\n\n    location elt_loc = LOC(elt);\n    /* only append after the last for generator */\n    if (gen_index >= asdl_seq_LEN(generators)) {\n        /* comprehension specific code */\n        switch (type) {\n        case COMP_GENEXP:\n            VISIT(c, expr, elt);\n            ADDOP_YIELD(c, elt_loc);\n            ADDOP(c, elt_loc, POP_TOP);\n            break;\n        case COMP_LISTCOMP:\n            VISIT(c, expr, elt);\n            ADDOP_I(c, elt_loc, LIST_APPEND, depth + 1);\n            break;\n        case COMP_SETCOMP:\n            VISIT(c, expr, elt);\n            ADDOP_I(c, elt_loc, SET_ADD, depth + 1);\n            break;\n        case COMP_DICTCOMP:\n            /* With '{k: v}', k is evaluated before v, so we do\n               the same. */\n            VISIT(c, expr, elt);\n            VISIT(c, expr, val);\n            elt_loc = LOCATION(elt->lineno,\n                               val->end_lineno,\n                               elt->col_offset,\n                               val->end_col_offset);\n            ADDOP_I(c, elt_loc, MAP_ADD, depth + 1);\n            break;\n        default:\n            return ERROR;\n        }\n    }\n\n    USE_LABEL(c, if_cleanup);\n    ADDOP_JUMP(c, elt_loc, JUMP, start);\n\n    compiler_pop_fblock(c, ASYNC_COMPREHENSION_GENERATOR, start);\n\n    USE_LABEL(c, except);\n\n    ADDOP(c, loc, END_ASYNC_FOR);\n\n    return SUCCESS;\n}\n\ntypedef struct {\n    PyObject *pushed_locals;\n    PyObject *temp_symbols;\n    PyObject *fast_hidden;\n} inlined_comprehension_state;\n\nstatic int\npush_inlined_comprehension_state(struct compiler *c, location loc,\n                                 PySTEntryObject *entry,\n                                 inlined_comprehension_state *state)\n{\n    int in_class_block = (c->u->u_ste->ste_type == ClassBlock) && !c->u->u_in_inlined_comp;\n    c->u->u_in_inlined_comp++;\n    // iterate over names bound in the comprehension and ensure we isolate\n    // them from the outer scope as needed\n    PyObject *k, *v;\n    Py_ssize_t pos = 0;\n    while (PyDict_Next(entry->ste_symbols, &pos, &k, &v)) {\n        assert(PyLong_Check(v));\n        long symbol = PyLong_AS_LONG(v);\n        // only values bound in the comprehension (DEF_LOCAL) need to be handled\n        // at all; DEF_LOCAL | DEF_NONLOCAL can occur in the case of an\n        // assignment expression to a nonlocal in the comprehension, these don't\n        // need handling here since they shouldn't be isolated\n        if ((symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) || in_class_block) {\n            if (!_PyST_IsFunctionLike(c->u->u_ste)) {\n                // non-function scope: override this name to use fast locals\n                PyObject *orig = PyDict_GetItem(c->u->u_metadata.u_fasthidden, k);\n                if (orig != Py_True) {\n                    if (PyDict_SetItem(c->u->u_metadata.u_fasthidden, k, Py_True) < 0) {\n                        return ERROR;\n                    }\n                    if (state->fast_hidden == NULL) {\n                        state->fast_hidden = PySet_New(NULL);\n                        if (state->fast_hidden == NULL) {\n                            return ERROR;\n                        }\n                    }\n                    if (PySet_Add(state->fast_hidden, k) < 0) {\n                        return ERROR;\n                    }\n                }\n            }\n            long scope = (symbol >> SCOPE_OFFSET) & SCOPE_MASK;\n            PyObject *outv = PyDict_GetItemWithError(c->u->u_ste->ste_symbols, k);\n            if (outv == NULL) {\n                outv = _PyLong_GetZero();\n            }\n            assert(PyLong_Check(outv));\n            long outsc = (PyLong_AS_LONG(outv) >> SCOPE_OFFSET) & SCOPE_MASK;\n            if (scope != outsc && !(scope == CELL && outsc == FREE)) {\n                // If a name has different scope inside than outside the\n                // comprehension, we need to temporarily handle it with the\n                // right scope while compiling the comprehension. (If it's free\n                // in outer scope and cell in inner scope, we can't treat it as\n                // both cell and free in the same function, but treating it as\n                // free throughout is fine; it's *_DEREF either way.)\n\n                if (state->temp_symbols == NULL) {\n                    state->temp_symbols = PyDict_New();\n                    if (state->temp_symbols == NULL) {\n                        return ERROR;\n                    }\n                }\n                // update the symbol to the in-comprehension version and save\n                // the outer version; we'll restore it after running the\n                // comprehension\n                Py_INCREF(outv);\n                if (PyDict_SetItem(c->u->u_ste->ste_symbols, k, v) < 0) {\n                    Py_DECREF(outv);\n                    return ERROR;\n                }\n                if (PyDict_SetItem(state->temp_symbols, k, outv) < 0) {\n                    Py_DECREF(outv);\n                    return ERROR;\n                }\n                Py_DECREF(outv);\n            }\n            // local names bound in comprehension must be isolated from\n            // outer scope; push existing value (which may be NULL if\n            // not defined) on stack\n            if (state->pushed_locals == NULL) {\n                state->pushed_locals = PyList_New(0);\n                if (state->pushed_locals == NULL) {\n                    return ERROR;\n                }\n            }\n            // in the case of a cell, this will actually push the cell\n            // itself to the stack, then we'll create a new one for the\n            // comprehension and restore the original one after\n            ADDOP_NAME(c, loc, LOAD_FAST_AND_CLEAR, k, varnames);\n            if (scope == CELL) {\n                if (outsc == FREE) {\n                    ADDOP_NAME(c, loc, MAKE_CELL, k, freevars);\n                } else {\n                    ADDOP_NAME(c, loc, MAKE_CELL, k, cellvars);\n                }\n            }\n            if (PyList_Append(state->pushed_locals, k) < 0) {\n                return ERROR;\n            }\n        }\n    }\n    if (state->pushed_locals) {\n        // Outermost iterable expression was already evaluated and is on the\n        // stack, we need to swap it back to TOS. This also rotates the order of\n        // `pushed_locals` on the stack, but this will be reversed when we swap\n        // out the comprehension result in pop_inlined_comprehension_state\n        ADDOP_I(c, loc, SWAP, PyList_GET_SIZE(state->pushed_locals) + 1);\n    }\n\n    return SUCCESS;\n}\n\nstatic int\npop_inlined_comprehension_state(struct compiler *c, location loc,\n                                inlined_comprehension_state state)\n{\n    c->u->u_in_inlined_comp--;\n    PyObject *k, *v;\n    Py_ssize_t pos = 0;\n    if (state.temp_symbols) {\n        while (PyDict_Next(state.temp_symbols, &pos, &k, &v)) {\n            if (PyDict_SetItem(c->u->u_ste->ste_symbols, k, v)) {\n                return ERROR;\n            }\n        }\n        Py_CLEAR(state.temp_symbols);\n    }\n    if (state.pushed_locals) {\n        // pop names we pushed to stack earlier\n        Py_ssize_t npops = PyList_GET_SIZE(state.pushed_locals);\n        // Preserve the list/dict/set result of the comprehension as TOS. This\n        // reverses the SWAP we did in push_inlined_comprehension_state to get\n        // the outermost iterable to TOS, so we can still just iterate\n        // pushed_locals in simple reverse order\n        ADDOP_I(c, loc, SWAP, npops + 1);\n        for (Py_ssize_t i = npops - 1; i >= 0; --i) {\n            k = PyList_GetItem(state.pushed_locals, i);\n            if (k == NULL) {\n                return ERROR;\n            }\n            ADDOP_NAME(c, loc, STORE_FAST_MAYBE_NULL, k, varnames);\n        }\n        Py_CLEAR(state.pushed_locals);\n    }\n    if (state.fast_hidden) {\n        while (PySet_Size(state.fast_hidden) > 0) {\n            PyObject *k = PySet_Pop(state.fast_hidden);\n            if (k == NULL) {\n                return ERROR;\n            }\n            // we set to False instead of clearing, so we can track which names\n            // were temporarily fast-locals and should use CO_FAST_HIDDEN\n            if (PyDict_SetItem(c->u->u_metadata.u_fasthidden, k, Py_False)) {\n                Py_DECREF(k);\n                return ERROR;\n            }\n            Py_DECREF(k);\n        }\n        Py_CLEAR(state.fast_hidden);\n    }\n    return SUCCESS;\n}\n\nstatic inline int\ncompiler_comprehension_iter(struct compiler *c, location loc,\n                            comprehension_ty comp)\n{\n    VISIT(c, expr, comp->iter);\n    if (comp->is_async) {\n        ADDOP(c, loc, GET_AITER);\n    }\n    else {\n        ADDOP(c, loc, GET_ITER);\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_comprehension(struct compiler *c, expr_ty e, int type,\n                       identifier name, asdl_comprehension_seq *generators, expr_ty elt,\n                       expr_ty val)\n{\n    PyCodeObject *co = NULL;\n    inlined_comprehension_state inline_state = {NULL, NULL};\n    comprehension_ty outermost;\n    int scope_type = c->u->u_scope_type;\n    int is_top_level_await = IS_TOP_LEVEL_AWAIT(c);\n    PySTEntryObject *entry = PySymtable_Lookup(c->c_st, (void *)e);\n    if (entry == NULL) {\n        goto error;\n    }\n    int is_inlined = entry->ste_comp_inlined;\n    int is_async_generator = entry->ste_coroutine;\n\n    location loc = LOC(e);\n\n    outermost = (comprehension_ty) asdl_seq_GET(generators, 0);\n    if (is_inlined) {\n        if (compiler_comprehension_iter(c, loc, outermost)) {\n            goto error;\n        }\n        if (push_inlined_comprehension_state(c, loc, entry, &inline_state)) {\n            goto error;\n        }\n    }\n    else {\n        if (compiler_enter_scope(c, name, COMPILER_SCOPE_COMPREHENSION,\n                                (void *)e, e->lineno) < 0)\n        {\n            goto error;\n        }\n    }\n    Py_CLEAR(entry);\n\n    if (is_async_generator && type != COMP_GENEXP &&\n        scope_type != COMPILER_SCOPE_ASYNC_FUNCTION &&\n        scope_type != COMPILER_SCOPE_COMPREHENSION &&\n        !is_top_level_await)\n    {\n        compiler_error(c, loc, \"asynchronous comprehension outside of \"\n                               \"an asynchronous function\");\n        goto error_in_scope;\n    }\n\n    if (type != COMP_GENEXP) {\n        int op;\n        switch (type) {\n        case COMP_LISTCOMP:\n            op = BUILD_LIST;\n            break;\n        case COMP_SETCOMP:\n            op = BUILD_SET;\n            break;\n        case COMP_DICTCOMP:\n            op = BUILD_MAP;\n            break;\n        default:\n            PyErr_Format(PyExc_SystemError,\n                         \"unknown comprehension type %d\", type);\n            goto error_in_scope;\n        }\n\n        ADDOP_I(c, loc, op, 0);\n        if (is_inlined) {\n            ADDOP_I(c, loc, SWAP, 2);\n        }\n    }\n\n    if (compiler_comprehension_generator(c, loc, generators, 0, 0,\n                                         elt, val, type, is_inlined) < 0) {\n        goto error_in_scope;\n    }\n\n    if (is_inlined) {\n        if (pop_inlined_comprehension_state(c, loc, inline_state)) {\n            goto error;\n        }\n        return SUCCESS;\n    }\n\n    if (type != COMP_GENEXP) {\n        ADDOP(c, LOC(e), RETURN_VALUE);\n    }\n    if (type == COMP_GENEXP) {\n        if (wrap_in_stopiteration_handler(c) < 0) {\n            goto error_in_scope;\n        }\n    }\n\n    co = optimize_and_assemble(c, 1);\n    compiler_exit_scope(c);\n    if (is_top_level_await && is_async_generator){\n        c->u->u_ste->ste_coroutine = 1;\n    }\n    if (co == NULL) {\n        goto error;\n    }\n\n    loc = LOC(e);\n    if (compiler_make_closure(c, loc, co, 0) < 0) {\n        goto error;\n    }\n    Py_CLEAR(co);\n\n    if (compiler_comprehension_iter(c, loc, outermost)) {\n        goto error;\n    }\n\n    ADDOP_I(c, loc, CALL, 0);\n\n    if (is_async_generator && type != COMP_GENEXP) {\n        ADDOP_I(c, loc, GET_AWAITABLE, 0);\n        ADDOP_LOAD_CONST(c, loc, Py_None);\n        ADD_YIELD_FROM(c, loc, 1);\n    }\n\n    return SUCCESS;\nerror_in_scope:\n    if (!is_inlined) {\n        compiler_exit_scope(c);\n    }\nerror:\n    Py_XDECREF(co);\n    Py_XDECREF(entry);\n    Py_XDECREF(inline_state.pushed_locals);\n    Py_XDECREF(inline_state.temp_symbols);\n    Py_XDECREF(inline_state.fast_hidden);\n    return ERROR;\n}\n\nstatic int\ncompiler_genexp(struct compiler *c, expr_ty e)\n{\n    assert(e->kind == GeneratorExp_kind);\n    _Py_DECLARE_STR(anon_genexpr, \"<genexpr>\");\n    return compiler_comprehension(c, e, COMP_GENEXP, &_Py_STR(anon_genexpr),\n                                  e->v.GeneratorExp.generators,\n                                  e->v.GeneratorExp.elt, NULL);\n}\n\nstatic int\ncompiler_listcomp(struct compiler *c, expr_ty e)\n{\n    assert(e->kind == ListComp_kind);\n    _Py_DECLARE_STR(anon_listcomp, \"<listcomp>\");\n    return compiler_comprehension(c, e, COMP_LISTCOMP, &_Py_STR(anon_listcomp),\n                                  e->v.ListComp.generators,\n                                  e->v.ListComp.elt, NULL);\n}\n\nstatic int\ncompiler_setcomp(struct compiler *c, expr_ty e)\n{\n    assert(e->kind == SetComp_kind);\n    _Py_DECLARE_STR(anon_setcomp, \"<setcomp>\");\n    return compiler_comprehension(c, e, COMP_SETCOMP, &_Py_STR(anon_setcomp),\n                                  e->v.SetComp.generators,\n                                  e->v.SetComp.elt, NULL);\n}\n\n\nstatic int\ncompiler_dictcomp(struct compiler *c, expr_ty e)\n{\n    assert(e->kind == DictComp_kind);\n    _Py_DECLARE_STR(anon_dictcomp, \"<dictcomp>\");\n    return compiler_comprehension(c, e, COMP_DICTCOMP, &_Py_STR(anon_dictcomp),\n                                  e->v.DictComp.generators,\n                                  e->v.DictComp.key, e->v.DictComp.value);\n}\n\n\nstatic int\ncompiler_visit_keyword(struct compiler *c, keyword_ty k)\n{\n    VISIT(c, expr, k->value);\n    return SUCCESS;\n}\n\n\nstatic int\ncompiler_with_except_finish(struct compiler *c, jump_target_label cleanup) {\n    NEW_JUMP_TARGET_LABEL(c, suppress);\n    ADDOP_JUMP(c, NO_LOCATION, POP_JUMP_IF_TRUE, suppress);\n    ADDOP_I(c, NO_LOCATION, RERAISE, 2);\n\n    USE_LABEL(c, suppress);\n    ADDOP(c, NO_LOCATION, POP_TOP); /* exc_value */\n    ADDOP(c, NO_LOCATION, POP_BLOCK);\n    ADDOP(c, NO_LOCATION, POP_EXCEPT);\n    ADDOP(c, NO_LOCATION, POP_TOP);\n    ADDOP(c, NO_LOCATION, POP_TOP);\n    NEW_JUMP_TARGET_LABEL(c, exit);\n    ADDOP_JUMP(c, NO_LOCATION, JUMP, exit);\n\n    USE_LABEL(c, cleanup);\n    POP_EXCEPT_AND_RERAISE(c, NO_LOCATION);\n\n    USE_LABEL(c, exit);\n    return SUCCESS;\n}\n\n/*\n   Implements the async with statement.\n\n   The semantics outlined in that PEP are as follows:\n\n   async with EXPR as VAR:\n       BLOCK\n\n   It is implemented roughly as:\n\n   context = EXPR\n   exit = context.__aexit__  # not calling it\n   value = await context.__aenter__()\n   try:\n       VAR = value  # if VAR present in the syntax\n       BLOCK\n   finally:\n       if an exception was raised:\n           exc = copy of (exception, instance, traceback)\n       else:\n           exc = (None, None, None)\n       if not (await exit(*exc)):\n           raise\n */\nstatic int\ncompiler_async_with(struct compiler *c, stmt_ty s, int pos)\n{\n    location loc = LOC(s);\n    withitem_ty item = asdl_seq_GET(s->v.AsyncWith.items, pos);\n\n    assert(s->kind == AsyncWith_kind);\n    if (IS_TOP_LEVEL_AWAIT(c)){\n        c->u->u_ste->ste_coroutine = 1;\n    } else if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION){\n        return compiler_error(c, loc, \"'async with' outside async function\");\n    }\n\n    NEW_JUMP_TARGET_LABEL(c, block);\n    NEW_JUMP_TARGET_LABEL(c, final);\n    NEW_JUMP_TARGET_LABEL(c, exit);\n    NEW_JUMP_TARGET_LABEL(c, cleanup);\n\n    /* Evaluate EXPR */\n    VISIT(c, expr, item->context_expr);\n\n    ADDOP(c, loc, BEFORE_ASYNC_WITH);\n    ADDOP_I(c, loc, GET_AWAITABLE, 1);\n    ADDOP_LOAD_CONST(c, loc, Py_None);\n    ADD_YIELD_FROM(c, loc, 1);\n\n    ADDOP_JUMP(c, loc, SETUP_WITH, final);\n\n    /* SETUP_WITH pushes a finally block. */\n    USE_LABEL(c, block);\n    RETURN_IF_ERROR(compiler_push_fblock(c, loc, ASYNC_WITH, block, final, s));\n\n    if (item->optional_vars) {\n        VISIT(c, expr, item->optional_vars);\n    }\n    else {\n        /* Discard result from context.__aenter__() */\n        ADDOP(c, loc, POP_TOP);\n    }\n\n    pos++;\n    if (pos == asdl_seq_LEN(s->v.AsyncWith.items)) {\n        /* BLOCK code */\n        VISIT_SEQ(c, stmt, s->v.AsyncWith.body)\n    }\n    else {\n        RETURN_IF_ERROR(compiler_async_with(c, s, pos));\n    }\n\n    compiler_pop_fblock(c, ASYNC_WITH, block);\n\n    ADDOP(c, loc, POP_BLOCK);\n    /* End of body; start the cleanup */\n\n    /* For successful outcome:\n     * call __exit__(None, None, None)\n     */\n    RETURN_IF_ERROR(compiler_call_exit_with_nones(c, loc));\n    ADDOP_I(c, loc, GET_AWAITABLE, 2);\n    ADDOP_LOAD_CONST(c, loc, Py_None);\n    ADD_YIELD_FROM(c, loc, 1);\n\n    ADDOP(c, loc, POP_TOP);\n\n    ADDOP_JUMP(c, loc, JUMP, exit);\n\n    /* For exceptional outcome: */\n    USE_LABEL(c, final);\n\n    ADDOP_JUMP(c, loc, SETUP_CLEANUP, cleanup);\n    ADDOP(c, loc, PUSH_EXC_INFO);\n    ADDOP(c, loc, WITH_EXCEPT_START);\n    ADDOP_I(c, loc, GET_AWAITABLE, 2);\n    ADDOP_LOAD_CONST(c, loc, Py_None);\n    ADD_YIELD_FROM(c, loc, 1);\n    RETURN_IF_ERROR(compiler_with_except_finish(c, cleanup));\n\n    USE_LABEL(c, exit);\n    return SUCCESS;\n}\n\n\n/*\n   Implements the with statement from PEP 343.\n   with EXPR as VAR:\n       BLOCK\n   is implemented as:\n        <code for EXPR>\n        SETUP_WITH  E\n        <code to store to VAR> or POP_TOP\n        <code for BLOCK>\n        LOAD_CONST (None, None, None)\n        CALL_FUNCTION_EX 0\n        JUMP  EXIT\n    E:  WITH_EXCEPT_START (calls EXPR.__exit__)\n        POP_JUMP_IF_TRUE T:\n        RERAISE\n    T:  POP_TOP (remove exception from stack)\n        POP_EXCEPT\n        POP_TOP\n    EXIT:\n */\n\nstatic int\ncompiler_with(struct compiler *c, stmt_ty s, int pos)\n{\n    withitem_ty item = asdl_seq_GET(s->v.With.items, pos);\n\n    assert(s->kind == With_kind);\n\n    NEW_JUMP_TARGET_LABEL(c, block);\n    NEW_JUMP_TARGET_LABEL(c, final);\n    NEW_JUMP_TARGET_LABEL(c, exit);\n    NEW_JUMP_TARGET_LABEL(c, cleanup);\n\n    /* Evaluate EXPR */\n    VISIT(c, expr, item->context_expr);\n    /* Will push bound __exit__ */\n    location loc = LOC(s);\n    ADDOP(c, loc, BEFORE_WITH);\n    ADDOP_JUMP(c, loc, SETUP_WITH, final);\n\n    /* SETUP_WITH pushes a finally block. */\n    USE_LABEL(c, block);\n    RETURN_IF_ERROR(compiler_push_fblock(c, loc, WITH, block, final, s));\n\n    if (item->optional_vars) {\n        VISIT(c, expr, item->optional_vars);\n    }\n    else {\n    /* Discard result from context.__enter__() */\n        ADDOP(c, loc, POP_TOP);\n    }\n\n    pos++;\n    if (pos == asdl_seq_LEN(s->v.With.items)) {\n        /* BLOCK code */\n        VISIT_SEQ(c, stmt, s->v.With.body)\n    }\n    else {\n        RETURN_IF_ERROR(compiler_with(c, s, pos));\n    }\n\n    ADDOP(c, NO_LOCATION, POP_BLOCK);\n    compiler_pop_fblock(c, WITH, block);\n\n    /* End of body; start the cleanup. */\n\n    /* For successful outcome:\n     * call __exit__(None, None, None)\n     */\n    loc = LOC(s);\n    RETURN_IF_ERROR(compiler_call_exit_with_nones(c, loc));\n    ADDOP(c, loc, POP_TOP);\n    ADDOP_JUMP(c, loc, JUMP, exit);\n\n    /* For exceptional outcome: */\n    USE_LABEL(c, final);\n\n    ADDOP_JUMP(c, loc, SETUP_CLEANUP, cleanup);\n    ADDOP(c, loc, PUSH_EXC_INFO);\n    ADDOP(c, loc, WITH_EXCEPT_START);\n    RETURN_IF_ERROR(compiler_with_except_finish(c, cleanup));\n\n    USE_LABEL(c, exit);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_visit_expr1(struct compiler *c, expr_ty e)\n{\n    location loc = LOC(e);\n    switch (e->kind) {\n    case NamedExpr_kind:\n        VISIT(c, expr, e->v.NamedExpr.value);\n        ADDOP_I(c, loc, COPY, 1);\n        VISIT(c, expr, e->v.NamedExpr.target);\n        break;\n    case BoolOp_kind:\n        return compiler_boolop(c, e);\n    case BinOp_kind:\n        VISIT(c, expr, e->v.BinOp.left);\n        VISIT(c, expr, e->v.BinOp.right);\n        ADDOP_BINARY(c, loc, e->v.BinOp.op);\n        break;\n    case UnaryOp_kind:\n        VISIT(c, expr, e->v.UnaryOp.operand);\n        if (e->v.UnaryOp.op == UAdd) {\n            ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_UNARY_POSITIVE);\n        }\n        else {\n            ADDOP(c, loc, unaryop(e->v.UnaryOp.op));\n        }\n        break;\n    case Lambda_kind:\n        return compiler_lambda(c, e);\n    case IfExp_kind:\n        return compiler_ifexp(c, e);\n    case Dict_kind:\n        return compiler_dict(c, e);\n    case Set_kind:\n        return compiler_set(c, e);\n    case GeneratorExp_kind:\n        return compiler_genexp(c, e);\n    case ListComp_kind:\n        return compiler_listcomp(c, e);\n    case SetComp_kind:\n        return compiler_setcomp(c, e);\n    case DictComp_kind:\n        return compiler_dictcomp(c, e);\n    case Yield_kind:\n        if (!_PyST_IsFunctionLike(c->u->u_ste)) {\n            return compiler_error(c, loc, \"'yield' outside function\");\n        }\n        if (e->v.Yield.value) {\n            VISIT(c, expr, e->v.Yield.value);\n        }\n        else {\n            ADDOP_LOAD_CONST(c, loc, Py_None);\n        }\n        ADDOP_YIELD(c, loc);\n        break;\n    case YieldFrom_kind:\n        if (!_PyST_IsFunctionLike(c->u->u_ste)) {\n            return compiler_error(c, loc, \"'yield' outside function\");\n        }\n        if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION) {\n            return compiler_error(c, loc, \"'yield from' inside async function\");\n        }\n        VISIT(c, expr, e->v.YieldFrom.value);\n        ADDOP(c, loc, GET_YIELD_FROM_ITER);\n        ADDOP_LOAD_CONST(c, loc, Py_None);\n        ADD_YIELD_FROM(c, loc, 0);\n        break;\n    case Await_kind:\n        if (!IS_TOP_LEVEL_AWAIT(c)){\n            if (!_PyST_IsFunctionLike(c->u->u_ste)) {\n                return compiler_error(c, loc, \"'await' outside function\");\n            }\n\n            if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION &&\n                    c->u->u_scope_type != COMPILER_SCOPE_COMPREHENSION) {\n                return compiler_error(c, loc, \"'await' outside async function\");\n            }\n        }\n\n        VISIT(c, expr, e->v.Await.value);\n        ADDOP_I(c, loc, GET_AWAITABLE, 0);\n        ADDOP_LOAD_CONST(c, loc, Py_None);\n        ADD_YIELD_FROM(c, loc, 1);\n        break;\n    case Compare_kind:\n        return compiler_compare(c, e);\n    case Call_kind:\n        return compiler_call(c, e);\n    case Constant_kind:\n        ADDOP_LOAD_CONST(c, loc, e->v.Constant.value);\n        break;\n    case JoinedStr_kind:\n        return compiler_joined_str(c, e);\n    case FormattedValue_kind:\n        return compiler_formatted_value(c, e);\n    /* The following exprs can be assignment targets. */\n    case Attribute_kind:\n        if (e->v.Attribute.ctx == Load && can_optimize_super_call(c, e)) {\n            RETURN_IF_ERROR(load_args_for_super(c, e->v.Attribute.value));\n            int opcode = asdl_seq_LEN(e->v.Attribute.value->v.Call.args) ?\n                LOAD_SUPER_ATTR : LOAD_ZERO_SUPER_ATTR;\n            ADDOP_NAME(c, loc, opcode, e->v.Attribute.attr, names);\n            loc = update_start_location_to_match_attr(c, loc, e);\n            ADDOP(c, loc, NOP);\n            return SUCCESS;\n        }\n        VISIT(c, expr, e->v.Attribute.value);\n        loc = LOC(e);\n        loc = update_start_location_to_match_attr(c, loc, e);\n        switch (e->v.Attribute.ctx) {\n        case Load:\n            ADDOP_NAME(c, loc, LOAD_ATTR, e->v.Attribute.attr, names);\n            break;\n        case Store:\n            if (forbidden_name(c, loc, e->v.Attribute.attr, e->v.Attribute.ctx)) {\n                return ERROR;\n            }\n            ADDOP_NAME(c, loc, STORE_ATTR, e->v.Attribute.attr, names);\n            break;\n        case Del:\n            ADDOP_NAME(c, loc, DELETE_ATTR, e->v.Attribute.attr, names);\n            break;\n        }\n        break;\n    case Subscript_kind:\n        return compiler_subscript(c, e);\n    case Starred_kind:\n        switch (e->v.Starred.ctx) {\n        case Store:\n            /* In all legitimate cases, the Starred node was already replaced\n             * by compiler_list/compiler_tuple. XXX: is that okay? */\n            return compiler_error(c, loc,\n                \"starred assignment target must be in a list or tuple\");\n        default:\n            return compiler_error(c, loc,\n                \"can't use starred expression here\");\n        }\n        break;\n    case Slice_kind:\n    {\n        int n = compiler_slice(c, e);\n        RETURN_IF_ERROR(n);\n        ADDOP_I(c, loc, BUILD_SLICE, n);\n        break;\n    }\n    case Name_kind:\n        return compiler_nameop(c, loc, e->v.Name.id, e->v.Name.ctx);\n    /* child nodes of List and Tuple will have expr_context set */\n    case List_kind:\n        return compiler_list(c, e);\n    case Tuple_kind:\n        return compiler_tuple(c, e);\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_visit_expr(struct compiler *c, expr_ty e)\n{\n    int res = compiler_visit_expr1(c, e);\n    return res;\n}\n\nstatic bool\nis_two_element_slice(expr_ty s)\n{\n    return s->kind == Slice_kind &&\n           s->v.Slice.step == NULL;\n}\n\nstatic int\ncompiler_augassign(struct compiler *c, stmt_ty s)\n{\n    assert(s->kind == AugAssign_kind);\n    expr_ty e = s->v.AugAssign.target;\n\n    location loc = LOC(e);\n\n    switch (e->kind) {\n    case Attribute_kind:\n        VISIT(c, expr, e->v.Attribute.value);\n        ADDOP_I(c, loc, COPY, 1);\n        loc = update_start_location_to_match_attr(c, loc, e);\n        ADDOP_NAME(c, loc, LOAD_ATTR, e->v.Attribute.attr, names);\n        break;\n    case Subscript_kind:\n        VISIT(c, expr, e->v.Subscript.value);\n        if (is_two_element_slice(e->v.Subscript.slice)) {\n            RETURN_IF_ERROR(compiler_slice(c, e->v.Subscript.slice));\n            ADDOP_I(c, loc, COPY, 3);\n            ADDOP_I(c, loc, COPY, 3);\n            ADDOP_I(c, loc, COPY, 3);\n            ADDOP(c, loc, BINARY_SLICE);\n        }\n        else {\n            VISIT(c, expr, e->v.Subscript.slice);\n            ADDOP_I(c, loc, COPY, 2);\n            ADDOP_I(c, loc, COPY, 2);\n            ADDOP(c, loc, BINARY_SUBSCR);\n        }\n        break;\n    case Name_kind:\n        RETURN_IF_ERROR(compiler_nameop(c, loc, e->v.Name.id, Load));\n        break;\n    default:\n        PyErr_Format(PyExc_SystemError,\n            \"invalid node type (%d) for augmented assignment\",\n            e->kind);\n        return ERROR;\n    }\n\n    loc = LOC(s);\n\n    VISIT(c, expr, s->v.AugAssign.value);\n    ADDOP_INPLACE(c, loc, s->v.AugAssign.op);\n\n    loc = LOC(e);\n\n    switch (e->kind) {\n    case Attribute_kind:\n        loc = update_start_location_to_match_attr(c, loc, e);\n        ADDOP_I(c, loc, SWAP, 2);\n        ADDOP_NAME(c, loc, STORE_ATTR, e->v.Attribute.attr, names);\n        break;\n    case Subscript_kind:\n        if (is_two_element_slice(e->v.Subscript.slice)) {\n            ADDOP_I(c, loc, SWAP, 4);\n            ADDOP_I(c, loc, SWAP, 3);\n            ADDOP_I(c, loc, SWAP, 2);\n            ADDOP(c, loc, STORE_SLICE);\n        }\n        else {\n            ADDOP_I(c, loc, SWAP, 3);\n            ADDOP_I(c, loc, SWAP, 2);\n            ADDOP(c, loc, STORE_SUBSCR);\n        }\n        break;\n    case Name_kind:\n        return compiler_nameop(c, loc, e->v.Name.id, Store);\n    default:\n        Py_UNREACHABLE();\n    }\n    return SUCCESS;\n}\n\nstatic int\ncheck_ann_expr(struct compiler *c, expr_ty e)\n{\n    VISIT(c, expr, e);\n    ADDOP(c, LOC(e), POP_TOP);\n    return SUCCESS;\n}\n\nstatic int\ncheck_annotation(struct compiler *c, stmt_ty s)\n{\n    /* Annotations of complex targets does not produce anything\n       under annotations future */\n    if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) {\n        return SUCCESS;\n    }\n\n    /* Annotations are only evaluated in a module or class. */\n    if (c->u->u_scope_type == COMPILER_SCOPE_MODULE ||\n        c->u->u_scope_type == COMPILER_SCOPE_CLASS) {\n        return check_ann_expr(c, s->v.AnnAssign.annotation);\n    }\n    return SUCCESS;\n}\n\nstatic int\ncheck_ann_subscr(struct compiler *c, expr_ty e)\n{\n    /* We check that everything in a subscript is defined at runtime. */\n    switch (e->kind) {\n    case Slice_kind:\n        if (e->v.Slice.lower && check_ann_expr(c, e->v.Slice.lower) < 0) {\n            return ERROR;\n        }\n        if (e->v.Slice.upper && check_ann_expr(c, e->v.Slice.upper) < 0) {\n            return ERROR;\n        }\n        if (e->v.Slice.step && check_ann_expr(c, e->v.Slice.step) < 0) {\n            return ERROR;\n        }\n        return SUCCESS;\n    case Tuple_kind: {\n        /* extended slice */\n        asdl_expr_seq *elts = e->v.Tuple.elts;\n        Py_ssize_t i, n = asdl_seq_LEN(elts);\n        for (i = 0; i < n; i++) {\n            RETURN_IF_ERROR(check_ann_subscr(c, asdl_seq_GET(elts, i)));\n        }\n        return SUCCESS;\n    }\n    default:\n        return check_ann_expr(c, e);\n    }\n}\n\nstatic int\ncompiler_annassign(struct compiler *c, stmt_ty s)\n{\n    location loc = LOC(s);\n    expr_ty targ = s->v.AnnAssign.target;\n    PyObject* mangled;\n\n    assert(s->kind == AnnAssign_kind);\n\n    /* We perform the actual assignment first. */\n    if (s->v.AnnAssign.value) {\n        VISIT(c, expr, s->v.AnnAssign.value);\n        VISIT(c, expr, targ);\n    }\n    switch (targ->kind) {\n    case Name_kind:\n        if (forbidden_name(c, loc, targ->v.Name.id, Store)) {\n            return ERROR;\n        }\n        /* If we have a simple name in a module or class, store annotation. */\n        if (s->v.AnnAssign.simple &&\n            (c->u->u_scope_type == COMPILER_SCOPE_MODULE ||\n             c->u->u_scope_type == COMPILER_SCOPE_CLASS)) {\n            if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) {\n                VISIT(c, annexpr, s->v.AnnAssign.annotation)\n            }\n            else {\n                VISIT(c, expr, s->v.AnnAssign.annotation);\n            }\n            ADDOP_NAME(c, loc, LOAD_NAME, &_Py_ID(__annotations__), names);\n            mangled = _Py_Mangle(c->u->u_private, targ->v.Name.id);\n            ADDOP_LOAD_CONST_NEW(c, loc, mangled);\n            ADDOP(c, loc, STORE_SUBSCR);\n        }\n        break;\n    case Attribute_kind:\n        if (forbidden_name(c, loc, targ->v.Attribute.attr, Store)) {\n            return ERROR;\n        }\n        if (!s->v.AnnAssign.value &&\n            check_ann_expr(c, targ->v.Attribute.value) < 0) {\n            return ERROR;\n        }\n        break;\n    case Subscript_kind:\n        if (!s->v.AnnAssign.value &&\n            (check_ann_expr(c, targ->v.Subscript.value) < 0 ||\n             check_ann_subscr(c, targ->v.Subscript.slice) < 0)) {\n                return ERROR;\n        }\n        break;\n    default:\n        PyErr_Format(PyExc_SystemError,\n                     \"invalid node type (%d) for annotated assignment\",\n                     targ->kind);\n        return ERROR;\n    }\n    /* Annotation is evaluated last. */\n    if (!s->v.AnnAssign.simple && check_annotation(c, s) < 0) {\n        return ERROR;\n    }\n    return SUCCESS;\n}\n\n/* Raises a SyntaxError and returns 0.\n   If something goes wrong, a different exception may be raised.\n*/\n\nstatic int\ncompiler_error(struct compiler *c, location loc,\n               const char *format, ...)\n{\n    va_list vargs;\n    va_start(vargs, format);\n    PyObject *msg = PyUnicode_FromFormatV(format, vargs);\n    va_end(vargs);\n    if (msg == NULL) {\n        return ERROR;\n    }\n    PyObject *loc_obj = PyErr_ProgramTextObject(c->c_filename, loc.lineno);\n    if (loc_obj == NULL) {\n        loc_obj = Py_None;\n    }\n    PyObject *args = Py_BuildValue(\"O(OiiOii)\", msg, c->c_filename,\n                                   loc.lineno, loc.col_offset + 1, loc_obj,\n                                   loc.end_lineno, loc.end_col_offset + 1);\n    Py_DECREF(msg);\n    if (args == NULL) {\n        goto exit;\n    }\n    PyErr_SetObject(PyExc_SyntaxError, args);\n exit:\n    Py_DECREF(loc_obj);\n    Py_XDECREF(args);\n    return ERROR;\n}\n\n/* Emits a SyntaxWarning and returns 1 on success.\n   If a SyntaxWarning raised as error, replaces it with a SyntaxError\n   and returns 0.\n*/\nstatic int\ncompiler_warn(struct compiler *c, location loc,\n              const char *format, ...)\n{\n    va_list vargs;\n    va_start(vargs, format);\n    PyObject *msg = PyUnicode_FromFormatV(format, vargs);\n    va_end(vargs);\n    if (msg == NULL) {\n        return ERROR;\n    }\n    if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, c->c_filename,\n                                 loc.lineno, NULL, NULL) < 0)\n    {\n        if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {\n            /* Replace the SyntaxWarning exception with a SyntaxError\n               to get a more accurate error report */\n            PyErr_Clear();\n            assert(PyUnicode_AsUTF8(msg) != NULL);\n            compiler_error(c, loc, PyUnicode_AsUTF8(msg));\n        }\n        Py_DECREF(msg);\n        return ERROR;\n    }\n    Py_DECREF(msg);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_subscript(struct compiler *c, expr_ty e)\n{\n    location loc = LOC(e);\n    expr_context_ty ctx = e->v.Subscript.ctx;\n    int op = 0;\n\n    if (ctx == Load) {\n        RETURN_IF_ERROR(check_subscripter(c, e->v.Subscript.value));\n        RETURN_IF_ERROR(check_index(c, e->v.Subscript.value, e->v.Subscript.slice));\n    }\n\n    VISIT(c, expr, e->v.Subscript.value);\n    if (is_two_element_slice(e->v.Subscript.slice) && ctx != Del) {\n        RETURN_IF_ERROR(compiler_slice(c, e->v.Subscript.slice));\n        if (ctx == Load) {\n            ADDOP(c, loc, BINARY_SLICE);\n        }\n        else {\n            assert(ctx == Store);\n            ADDOP(c, loc, STORE_SLICE);\n        }\n    }\n    else {\n        VISIT(c, expr, e->v.Subscript.slice);\n        switch (ctx) {\n            case Load:    op = BINARY_SUBSCR; break;\n            case Store:   op = STORE_SUBSCR; break;\n            case Del:     op = DELETE_SUBSCR; break;\n        }\n        assert(op);\n        ADDOP(c, loc, op);\n    }\n    return SUCCESS;\n}\n\n/* Returns the number of the values emitted,\n * thus are needed to build the slice, or -1 if there is an error. */\nstatic int\ncompiler_slice(struct compiler *c, expr_ty s)\n{\n    int n = 2;\n    assert(s->kind == Slice_kind);\n\n    /* only handles the cases where BUILD_SLICE is emitted */\n    if (s->v.Slice.lower) {\n        VISIT(c, expr, s->v.Slice.lower);\n    }\n    else {\n        ADDOP_LOAD_CONST(c, LOC(s), Py_None);\n    }\n\n    if (s->v.Slice.upper) {\n        VISIT(c, expr, s->v.Slice.upper);\n    }\n    else {\n        ADDOP_LOAD_CONST(c, LOC(s), Py_None);\n    }\n\n    if (s->v.Slice.step) {\n        n++;\n        VISIT(c, expr, s->v.Slice.step);\n    }\n    return n;\n}\n\n\n// PEP 634: Structural Pattern Matching\n\n// To keep things simple, all compiler_pattern_* and pattern_helper_* routines\n// follow the convention of consuming TOS (the subject for the given pattern)\n// and calling jump_to_fail_pop on failure (no match).\n\n// When calling into these routines, it's important that pc->on_top be kept\n// updated to reflect the current number of items that we are using on the top\n// of the stack: they will be popped on failure, and any name captures will be\n// stored *underneath* them on success. This lets us defer all names stores\n// until the *entire* pattern matches.\n\n#define WILDCARD_CHECK(N) \\\n    ((N)->kind == MatchAs_kind && !(N)->v.MatchAs.name)\n\n#define WILDCARD_STAR_CHECK(N) \\\n    ((N)->kind == MatchStar_kind && !(N)->v.MatchStar.name)\n\n// Limit permitted subexpressions, even if the parser & AST validator let them through\n#define MATCH_VALUE_EXPR(N) \\\n    ((N)->kind == Constant_kind || (N)->kind == Attribute_kind)\n\n// Allocate or resize pc->fail_pop to allow for n items to be popped on failure.\nstatic int\nensure_fail_pop(struct compiler *c, pattern_context *pc, Py_ssize_t n)\n{\n    Py_ssize_t size = n + 1;\n    if (size <= pc->fail_pop_size) {\n        return SUCCESS;\n    }\n    Py_ssize_t needed = sizeof(jump_target_label) * size;\n    jump_target_label *resized = PyObject_Realloc(pc->fail_pop, needed);\n    if (resized == NULL) {\n        PyErr_NoMemory();\n        return ERROR;\n    }\n    pc->fail_pop = resized;\n    while (pc->fail_pop_size < size) {\n        NEW_JUMP_TARGET_LABEL(c, new_block);\n        pc->fail_pop[pc->fail_pop_size++] = new_block;\n    }\n    return SUCCESS;\n}\n\n// Use op to jump to the correct fail_pop block.\nstatic int\njump_to_fail_pop(struct compiler *c, location loc,\n                 pattern_context *pc, int op)\n{\n    // Pop any items on the top of the stack, plus any objects we were going to\n    // capture on success:\n    Py_ssize_t pops = pc->on_top + PyList_GET_SIZE(pc->stores);\n    RETURN_IF_ERROR(ensure_fail_pop(c, pc, pops));\n    ADDOP_JUMP(c, loc, op, pc->fail_pop[pops]);\n    return SUCCESS;\n}\n\n// Build all of the fail_pop blocks and reset fail_pop.\nstatic int\nemit_and_reset_fail_pop(struct compiler *c, location loc,\n                        pattern_context *pc)\n{\n    if (!pc->fail_pop_size) {\n        assert(pc->fail_pop == NULL);\n        return SUCCESS;\n    }\n    while (--pc->fail_pop_size) {\n        USE_LABEL(c, pc->fail_pop[pc->fail_pop_size]);\n        if (codegen_addop_noarg(INSTR_SEQUENCE(c), POP_TOP, loc) < 0) {\n            pc->fail_pop_size = 0;\n            PyObject_Free(pc->fail_pop);\n            pc->fail_pop = NULL;\n            return ERROR;\n        }\n    }\n    USE_LABEL(c, pc->fail_pop[0]);\n    PyObject_Free(pc->fail_pop);\n    pc->fail_pop = NULL;\n    return SUCCESS;\n}\n\nstatic int\ncompiler_error_duplicate_store(struct compiler *c, location loc, identifier n)\n{\n    return compiler_error(c, loc,\n        \"multiple assignments to name %R in pattern\", n);\n}\n\n// Duplicate the effect of 3.10's ROT_* instructions using SWAPs.\nstatic int\npattern_helper_rotate(struct compiler *c, location loc, Py_ssize_t count)\n{\n    while (1 < count) {\n        ADDOP_I(c, loc, SWAP, count--);\n    }\n    return SUCCESS;\n}\n\nstatic int\npattern_helper_store_name(struct compiler *c, location loc,\n                          identifier n, pattern_context *pc)\n{\n    if (n == NULL) {\n        ADDOP(c, loc, POP_TOP);\n        return SUCCESS;\n    }\n    if (forbidden_name(c, loc, n, Store)) {\n        return ERROR;\n    }\n    // Can't assign to the same name twice:\n    int duplicate = PySequence_Contains(pc->stores, n);\n    RETURN_IF_ERROR(duplicate);\n    if (duplicate) {\n        return compiler_error_duplicate_store(c, loc, n);\n    }\n    // Rotate this object underneath any items we need to preserve:\n    Py_ssize_t rotations = pc->on_top + PyList_GET_SIZE(pc->stores) + 1;\n    RETURN_IF_ERROR(pattern_helper_rotate(c, loc, rotations));\n    RETURN_IF_ERROR(PyList_Append(pc->stores, n));\n    return SUCCESS;\n}\n\n\nstatic int\npattern_unpack_helper(struct compiler *c, location loc,\n                      asdl_pattern_seq *elts)\n{\n    Py_ssize_t n = asdl_seq_LEN(elts);\n    int seen_star = 0;\n    for (Py_ssize_t i = 0; i < n; i++) {\n        pattern_ty elt = asdl_seq_GET(elts, i);\n        if (elt->kind == MatchStar_kind && !seen_star) {\n            if ((i >= (1 << 8)) ||\n                (n-i-1 >= (INT_MAX >> 8))) {\n                return compiler_error(c, loc,\n                    \"too many expressions in \"\n                    \"star-unpacking sequence pattern\");\n            }\n            ADDOP_I(c, loc, UNPACK_EX, (i + ((n-i-1) << 8)));\n            seen_star = 1;\n        }\n        else if (elt->kind == MatchStar_kind) {\n            return compiler_error(c, loc,\n                \"multiple starred expressions in sequence pattern\");\n        }\n    }\n    if (!seen_star) {\n        ADDOP_I(c, loc, UNPACK_SEQUENCE, n);\n    }\n    return SUCCESS;\n}\n\nstatic int\npattern_helper_sequence_unpack(struct compiler *c, location loc,\n                               asdl_pattern_seq *patterns, Py_ssize_t star,\n                               pattern_context *pc)\n{\n    RETURN_IF_ERROR(pattern_unpack_helper(c, loc, patterns));\n    Py_ssize_t size = asdl_seq_LEN(patterns);\n    // We've now got a bunch of new subjects on the stack. They need to remain\n    // there after each subpattern match:\n    pc->on_top += size;\n    for (Py_ssize_t i = 0; i < size; i++) {\n        // One less item to keep track of each time we loop through:\n        pc->on_top--;\n        pattern_ty pattern = asdl_seq_GET(patterns, i);\n        RETURN_IF_ERROR(compiler_pattern_subpattern(c, pattern, pc));\n    }\n    return SUCCESS;\n}\n\n// Like pattern_helper_sequence_unpack, but uses BINARY_SUBSCR instead of\n// UNPACK_SEQUENCE / UNPACK_EX. This is more efficient for patterns with a\n// starred wildcard like [first, *_] / [first, *_, last] / [*_, last] / etc.\nstatic int\npattern_helper_sequence_subscr(struct compiler *c, location loc,\n                               asdl_pattern_seq *patterns, Py_ssize_t star,\n                               pattern_context *pc)\n{\n    // We need to keep the subject around for extracting elements:\n    pc->on_top++;\n    Py_ssize_t size = asdl_seq_LEN(patterns);\n    for (Py_ssize_t i = 0; i < size; i++) {\n        pattern_ty pattern = asdl_seq_GET(patterns, i);\n        if (WILDCARD_CHECK(pattern)) {\n            continue;\n        }\n        if (i == star) {\n            assert(WILDCARD_STAR_CHECK(pattern));\n            continue;\n        }\n        ADDOP_I(c, loc, COPY, 1);\n        if (i < star) {\n            ADDOP_LOAD_CONST_NEW(c, loc, PyLong_FromSsize_t(i));\n        }\n        else {\n            // The subject may not support negative indexing! Compute a\n            // nonnegative index:\n            ADDOP(c, loc, GET_LEN);\n            ADDOP_LOAD_CONST_NEW(c, loc, PyLong_FromSsize_t(size - i));\n            ADDOP_BINARY(c, loc, Sub);\n        }\n        ADDOP(c, loc, BINARY_SUBSCR);\n        RETURN_IF_ERROR(compiler_pattern_subpattern(c, pattern, pc));\n    }\n    // Pop the subject, we're done with it:\n    pc->on_top--;\n    ADDOP(c, loc, POP_TOP);\n    return SUCCESS;\n}\n\n// Like compiler_pattern, but turn off checks for irrefutability.\nstatic int\ncompiler_pattern_subpattern(struct compiler *c,\n                            pattern_ty p, pattern_context *pc)\n{\n    int allow_irrefutable = pc->allow_irrefutable;\n    pc->allow_irrefutable = 1;\n    RETURN_IF_ERROR(compiler_pattern(c, p, pc));\n    pc->allow_irrefutable = allow_irrefutable;\n    return SUCCESS;\n}\n\nstatic int\ncompiler_pattern_as(struct compiler *c, pattern_ty p, pattern_context *pc)\n{\n    assert(p->kind == MatchAs_kind);\n    if (p->v.MatchAs.pattern == NULL) {\n        // An irrefutable match:\n        if (!pc->allow_irrefutable) {\n            if (p->v.MatchAs.name) {\n                const char *e = \"name capture %R makes remaining patterns unreachable\";\n                return compiler_error(c, LOC(p), e, p->v.MatchAs.name);\n            }\n            const char *e = \"wildcard makes remaining patterns unreachable\";\n            return compiler_error(c, LOC(p), e);\n        }\n        return pattern_helper_store_name(c, LOC(p), p->v.MatchAs.name, pc);\n    }\n    // Need to make a copy for (possibly) storing later:\n    pc->on_top++;\n    ADDOP_I(c, LOC(p), COPY, 1);\n    RETURN_IF_ERROR(compiler_pattern(c, p->v.MatchAs.pattern, pc));\n    // Success! Store it:\n    pc->on_top--;\n    RETURN_IF_ERROR(pattern_helper_store_name(c, LOC(p), p->v.MatchAs.name, pc));\n    return SUCCESS;\n}\n\nstatic int\ncompiler_pattern_star(struct compiler *c, pattern_ty p, pattern_context *pc)\n{\n    assert(p->kind == MatchStar_kind);\n    RETURN_IF_ERROR(\n        pattern_helper_store_name(c, LOC(p), p->v.MatchStar.name, pc));\n    return SUCCESS;\n}\n\nstatic int\nvalidate_kwd_attrs(struct compiler *c, asdl_identifier_seq *attrs, asdl_pattern_seq* patterns)\n{\n    // Any errors will point to the pattern rather than the arg name as the\n    // parser is only supplying identifiers rather than Name or keyword nodes\n    Py_ssize_t nattrs = asdl_seq_LEN(attrs);\n    for (Py_ssize_t i = 0; i < nattrs; i++) {\n        identifier attr = ((identifier)asdl_seq_GET(attrs, i));\n        location loc = LOC((pattern_ty) asdl_seq_GET(patterns, i));\n        if (forbidden_name(c, loc, attr, Store)) {\n            return ERROR;\n        }\n        for (Py_ssize_t j = i + 1; j < nattrs; j++) {\n            identifier other = ((identifier)asdl_seq_GET(attrs, j));\n            if (!PyUnicode_Compare(attr, other)) {\n                location loc = LOC((pattern_ty) asdl_seq_GET(patterns, j));\n                compiler_error(c, loc, \"attribute name repeated in class pattern: %U\", attr);\n                return ERROR;\n            }\n        }\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_pattern_class(struct compiler *c, pattern_ty p, pattern_context *pc)\n{\n    assert(p->kind == MatchClass_kind);\n    asdl_pattern_seq *patterns = p->v.MatchClass.patterns;\n    asdl_identifier_seq *kwd_attrs = p->v.MatchClass.kwd_attrs;\n    asdl_pattern_seq *kwd_patterns = p->v.MatchClass.kwd_patterns;\n    Py_ssize_t nargs = asdl_seq_LEN(patterns);\n    Py_ssize_t nattrs = asdl_seq_LEN(kwd_attrs);\n    Py_ssize_t nkwd_patterns = asdl_seq_LEN(kwd_patterns);\n    if (nattrs != nkwd_patterns) {\n        // AST validator shouldn't let this happen, but if it does,\n        // just fail, don't crash out of the interpreter\n        const char * e = \"kwd_attrs (%d) / kwd_patterns (%d) length mismatch in class pattern\";\n        return compiler_error(c, LOC(p), e, nattrs, nkwd_patterns);\n    }\n    if (INT_MAX < nargs || INT_MAX < nargs + nattrs - 1) {\n        const char *e = \"too many sub-patterns in class pattern %R\";\n        return compiler_error(c, LOC(p), e, p->v.MatchClass.cls);\n    }\n    if (nattrs) {\n        RETURN_IF_ERROR(validate_kwd_attrs(c, kwd_attrs, kwd_patterns));\n    }\n    VISIT(c, expr, p->v.MatchClass.cls);\n    PyObject *attr_names = PyTuple_New(nattrs);\n    if (attr_names == NULL) {\n        return ERROR;\n    }\n    Py_ssize_t i;\n    for (i = 0; i < nattrs; i++) {\n        PyObject *name = asdl_seq_GET(kwd_attrs, i);\n        PyTuple_SET_ITEM(attr_names, i, Py_NewRef(name));\n    }\n    ADDOP_LOAD_CONST_NEW(c, LOC(p), attr_names);\n    ADDOP_I(c, LOC(p), MATCH_CLASS, nargs);\n    ADDOP_I(c, LOC(p), COPY, 1);\n    ADDOP_LOAD_CONST(c, LOC(p), Py_None);\n    ADDOP_I(c, LOC(p), IS_OP, 1);\n    // TOS is now a tuple of (nargs + nattrs) attributes (or None):\n    pc->on_top++;\n    RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));\n    ADDOP_I(c, LOC(p), UNPACK_SEQUENCE, nargs + nattrs);\n    pc->on_top += nargs + nattrs - 1;\n    for (i = 0; i < nargs + nattrs; i++) {\n        pc->on_top--;\n        pattern_ty pattern;\n        if (i < nargs) {\n            // Positional:\n            pattern = asdl_seq_GET(patterns, i);\n        }\n        else {\n            // Keyword:\n            pattern = asdl_seq_GET(kwd_patterns, i - nargs);\n        }\n        if (WILDCARD_CHECK(pattern)) {\n            ADDOP(c, LOC(p), POP_TOP);\n            continue;\n        }\n        RETURN_IF_ERROR(compiler_pattern_subpattern(c, pattern, pc));\n    }\n    // Success! Pop the tuple of attributes:\n    return SUCCESS;\n}\n\nstatic int\ncompiler_pattern_mapping(struct compiler *c, pattern_ty p,\n                         pattern_context *pc)\n{\n    assert(p->kind == MatchMapping_kind);\n    asdl_expr_seq *keys = p->v.MatchMapping.keys;\n    asdl_pattern_seq *patterns = p->v.MatchMapping.patterns;\n    Py_ssize_t size = asdl_seq_LEN(keys);\n    Py_ssize_t npatterns = asdl_seq_LEN(patterns);\n    if (size != npatterns) {\n        // AST validator shouldn't let this happen, but if it does,\n        // just fail, don't crash out of the interpreter\n        const char * e = \"keys (%d) / patterns (%d) length mismatch in mapping pattern\";\n        return compiler_error(c, LOC(p), e, size, npatterns);\n    }\n    // We have a double-star target if \"rest\" is set\n    PyObject *star_target = p->v.MatchMapping.rest;\n    // We need to keep the subject on top during the mapping and length checks:\n    pc->on_top++;\n    ADDOP(c, LOC(p), MATCH_MAPPING);\n    RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));\n    if (!size && !star_target) {\n        // If the pattern is just \"{}\", we're done! Pop the subject:\n        pc->on_top--;\n        ADDOP(c, LOC(p), POP_TOP);\n        return SUCCESS;\n    }\n    if (size) {\n        // If the pattern has any keys in it, perform a length check:\n        ADDOP(c, LOC(p), GET_LEN);\n        ADDOP_LOAD_CONST_NEW(c, LOC(p), PyLong_FromSsize_t(size));\n        ADDOP_COMPARE(c, LOC(p), GtE);\n        RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));\n    }\n    if (INT_MAX < size - 1) {\n        return compiler_error(c, LOC(p), \"too many sub-patterns in mapping pattern\");\n    }\n    // Collect all of the keys into a tuple for MATCH_KEYS and\n    // **rest. They can either be dotted names or literals:\n\n    // Maintaining a set of Constant_kind kind keys allows us to raise a\n    // SyntaxError in the case of duplicates.\n    PyObject *seen = PySet_New(NULL);\n    if (seen == NULL) {\n        return ERROR;\n    }\n\n    // NOTE: goto error on failure in the loop below to avoid leaking `seen`\n    for (Py_ssize_t i = 0; i < size; i++) {\n        expr_ty key = asdl_seq_GET(keys, i);\n        if (key == NULL) {\n            const char *e = \"can't use NULL keys in MatchMapping \"\n                            \"(set 'rest' parameter instead)\";\n            location loc = LOC((pattern_ty) asdl_seq_GET(patterns, i));\n            compiler_error(c, loc, e);\n            goto error;\n        }\n\n        if (key->kind == Constant_kind) {\n            int in_seen = PySet_Contains(seen, key->v.Constant.value);\n            if (in_seen < 0) {\n                goto error;\n            }\n            if (in_seen) {\n                const char *e = \"mapping pattern checks duplicate key (%R)\";\n                compiler_error(c, LOC(p), e, key->v.Constant.value);\n                goto error;\n            }\n            if (PySet_Add(seen, key->v.Constant.value)) {\n                goto error;\n            }\n        }\n\n        else if (key->kind != Attribute_kind) {\n            const char *e = \"mapping pattern keys may only match literals and attribute lookups\";\n            compiler_error(c, LOC(p), e);\n            goto error;\n        }\n        if (compiler_visit_expr(c, key) < 0) {\n            goto error;\n        }\n    }\n\n    // all keys have been checked; there are no duplicates\n    Py_DECREF(seen);\n\n    ADDOP_I(c, LOC(p), BUILD_TUPLE, size);\n    ADDOP(c, LOC(p), MATCH_KEYS);\n    // There's now a tuple of keys and a tuple of values on top of the subject:\n    pc->on_top += 2;\n    ADDOP_I(c, LOC(p), COPY, 1);\n    ADDOP_LOAD_CONST(c, LOC(p), Py_None);\n    ADDOP_I(c, LOC(p), IS_OP, 1);\n    RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));\n    // So far so good. Use that tuple of values on the stack to match\n    // sub-patterns against:\n    ADDOP_I(c, LOC(p), UNPACK_SEQUENCE, size);\n    pc->on_top += size - 1;\n    for (Py_ssize_t i = 0; i < size; i++) {\n        pc->on_top--;\n        pattern_ty pattern = asdl_seq_GET(patterns, i);\n        RETURN_IF_ERROR(compiler_pattern_subpattern(c, pattern, pc));\n    }\n    // If we get this far, it's a match! Whatever happens next should consume\n    // the tuple of keys and the subject:\n    pc->on_top -= 2;\n    if (star_target) {\n        // If we have a starred name, bind a dict of remaining items to it (this may\n        // seem a bit inefficient, but keys is rarely big enough to actually impact\n        // runtime):\n        // rest = dict(TOS1)\n        // for key in TOS:\n        //     del rest[key]\n        ADDOP_I(c, LOC(p), BUILD_MAP, 0);           // [subject, keys, empty]\n        ADDOP_I(c, LOC(p), SWAP, 3);                // [empty, keys, subject]\n        ADDOP_I(c, LOC(p), DICT_UPDATE, 2);         // [copy, keys]\n        ADDOP_I(c, LOC(p), UNPACK_SEQUENCE, size);  // [copy, keys...]\n        while (size) {\n            ADDOP_I(c, LOC(p), COPY, 1 + size--);   // [copy, keys..., copy]\n            ADDOP_I(c, LOC(p), SWAP, 2);            // [copy, keys..., copy, key]\n            ADDOP(c, LOC(p), DELETE_SUBSCR);        // [copy, keys...]\n        }\n        RETURN_IF_ERROR(pattern_helper_store_name(c, LOC(p), star_target, pc));\n    }\n    else {\n        ADDOP(c, LOC(p), POP_TOP);  // Tuple of keys.\n        ADDOP(c, LOC(p), POP_TOP);  // Subject.\n    }\n    return SUCCESS;\n\nerror:\n    Py_DECREF(seen);\n    return ERROR;\n}\n\nstatic int\ncompiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc)\n{\n    assert(p->kind == MatchOr_kind);\n    NEW_JUMP_TARGET_LABEL(c, end);\n    Py_ssize_t size = asdl_seq_LEN(p->v.MatchOr.patterns);\n    assert(size > 1);\n    // We're going to be messing with pc. Keep the original info handy:\n    pattern_context old_pc = *pc;\n    Py_INCREF(pc->stores);\n    // control is the list of names bound by the first alternative. It is used\n    // for checking different name bindings in alternatives, and for correcting\n    // the order in which extracted elements are placed on the stack.\n    PyObject *control = NULL;\n    // NOTE: We can't use returning macros anymore! goto error on error.\n    for (Py_ssize_t i = 0; i < size; i++) {\n        pattern_ty alt = asdl_seq_GET(p->v.MatchOr.patterns, i);\n        PyObject *pc_stores = PyList_New(0);\n        if (pc_stores == NULL) {\n            goto error;\n        }\n        Py_SETREF(pc->stores, pc_stores);\n        // An irrefutable sub-pattern must be last, if it is allowed at all:\n        pc->allow_irrefutable = (i == size - 1) && old_pc.allow_irrefutable;\n        pc->fail_pop = NULL;\n        pc->fail_pop_size = 0;\n        pc->on_top = 0;\n        if (codegen_addop_i(INSTR_SEQUENCE(c), COPY, 1, LOC(alt)) < 0 ||\n            compiler_pattern(c, alt, pc) < 0) {\n            goto error;\n        }\n        // Success!\n        Py_ssize_t nstores = PyList_GET_SIZE(pc->stores);\n        if (!i) {\n            // This is the first alternative, so save its stores as a \"control\"\n            // for the others (they can't bind a different set of names, and\n            // might need to be reordered):\n            assert(control == NULL);\n            control = Py_NewRef(pc->stores);\n        }\n        else if (nstores != PyList_GET_SIZE(control)) {\n            goto diff;\n        }\n        else if (nstores) {\n            // There were captures. Check to see if we differ from control:\n            Py_ssize_t icontrol = nstores;\n            while (icontrol--) {\n                PyObject *name = PyList_GET_ITEM(control, icontrol);\n                Py_ssize_t istores = PySequence_Index(pc->stores, name);\n                if (istores < 0) {\n                    PyErr_Clear();\n                    goto diff;\n                }\n                if (icontrol != istores) {\n                    // Reorder the names on the stack to match the order of the\n                    // names in control. There's probably a better way of doing\n                    // this; the current solution is potentially very\n                    // inefficient when each alternative subpattern binds lots\n                    // of names in different orders. It's fine for reasonable\n                    // cases, though, and the peephole optimizer will ensure\n                    // that the final code is as efficient as possible.\n                    assert(istores < icontrol);\n                    Py_ssize_t rotations = istores + 1;\n                    // Perform the same rotation on pc->stores:\n                    PyObject *rotated = PyList_GetSlice(pc->stores, 0,\n                                                        rotations);\n                    if (rotated == NULL ||\n                        PyList_SetSlice(pc->stores, 0, rotations, NULL) ||\n                        PyList_SetSlice(pc->stores, icontrol - istores,\n                                        icontrol - istores, rotated))\n                    {\n                        Py_XDECREF(rotated);\n                        goto error;\n                    }\n                    Py_DECREF(rotated);\n                    // That just did:\n                    // rotated = pc_stores[:rotations]\n                    // del pc_stores[:rotations]\n                    // pc_stores[icontrol-istores:icontrol-istores] = rotated\n                    // Do the same thing to the stack, using several\n                    // rotations:\n                    while (rotations--) {\n                        if (pattern_helper_rotate(c, LOC(alt), icontrol + 1) < 0) {\n                            goto error;\n                        }\n                    }\n                }\n            }\n        }\n        assert(control);\n        if (codegen_addop_j(INSTR_SEQUENCE(c), LOC(alt), JUMP, end) < 0 ||\n            emit_and_reset_fail_pop(c, LOC(alt), pc) < 0)\n        {\n            goto error;\n        }\n    }\n    Py_DECREF(pc->stores);\n    *pc = old_pc;\n    Py_INCREF(pc->stores);\n    // Need to NULL this for the PyObject_Free call in the error block.\n    old_pc.fail_pop = NULL;\n    // No match. Pop the remaining copy of the subject and fail:\n    if (codegen_addop_noarg(INSTR_SEQUENCE(c), POP_TOP, LOC(p)) < 0 ||\n        jump_to_fail_pop(c, LOC(p), pc, JUMP) < 0) {\n        goto error;\n    }\n\n    USE_LABEL(c, end);\n    Py_ssize_t nstores = PyList_GET_SIZE(control);\n    // There's a bunch of stuff on the stack between where the new stores\n    // are and where they need to be:\n    // - The other stores.\n    // - A copy of the subject.\n    // - Anything else that may be on top of the stack.\n    // - Any previous stores we've already stashed away on the stack.\n    Py_ssize_t nrots = nstores + 1 + pc->on_top + PyList_GET_SIZE(pc->stores);\n    for (Py_ssize_t i = 0; i < nstores; i++) {\n        // Rotate this capture to its proper place on the stack:\n        if (pattern_helper_rotate(c, LOC(p), nrots) < 0) {\n            goto error;\n        }\n        // Update the list of previous stores with this new name, checking for\n        // duplicates:\n        PyObject *name = PyList_GET_ITEM(control, i);\n        int dupe = PySequence_Contains(pc->stores, name);\n        if (dupe < 0) {\n            goto error;\n        }\n        if (dupe) {\n            compiler_error_duplicate_store(c, LOC(p), name);\n            goto error;\n        }\n        if (PyList_Append(pc->stores, name)) {\n            goto error;\n        }\n    }\n    Py_DECREF(old_pc.stores);\n    Py_DECREF(control);\n    // NOTE: Returning macros are safe again.\n    // Pop the copy of the subject:\n    ADDOP(c, LOC(p), POP_TOP);\n    return SUCCESS;\ndiff:\n    compiler_error(c, LOC(p), \"alternative patterns bind different names\");\nerror:\n    PyObject_Free(old_pc.fail_pop);\n    Py_DECREF(old_pc.stores);\n    Py_XDECREF(control);\n    return ERROR;\n}\n\n\nstatic int\ncompiler_pattern_sequence(struct compiler *c, pattern_ty p,\n                          pattern_context *pc)\n{\n    assert(p->kind == MatchSequence_kind);\n    asdl_pattern_seq *patterns = p->v.MatchSequence.patterns;\n    Py_ssize_t size = asdl_seq_LEN(patterns);\n    Py_ssize_t star = -1;\n    int only_wildcard = 1;\n    int star_wildcard = 0;\n    // Find a starred name, if it exists. There may be at most one:\n    for (Py_ssize_t i = 0; i < size; i++) {\n        pattern_ty pattern = asdl_seq_GET(patterns, i);\n        if (pattern->kind == MatchStar_kind) {\n            if (star >= 0) {\n                const char *e = \"multiple starred names in sequence pattern\";\n                return compiler_error(c, LOC(p), e);\n            }\n            star_wildcard = WILDCARD_STAR_CHECK(pattern);\n            only_wildcard &= star_wildcard;\n            star = i;\n            continue;\n        }\n        only_wildcard &= WILDCARD_CHECK(pattern);\n    }\n    // We need to keep the subject on top during the sequence and length checks:\n    pc->on_top++;\n    ADDOP(c, LOC(p), MATCH_SEQUENCE);\n    RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));\n    if (star < 0) {\n        // No star: len(subject) == size\n        ADDOP(c, LOC(p), GET_LEN);\n        ADDOP_LOAD_CONST_NEW(c, LOC(p), PyLong_FromSsize_t(size));\n        ADDOP_COMPARE(c, LOC(p), Eq);\n        RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));\n    }\n    else if (size > 1) {\n        // Star: len(subject) >= size - 1\n        ADDOP(c, LOC(p), GET_LEN);\n        ADDOP_LOAD_CONST_NEW(c, LOC(p), PyLong_FromSsize_t(size - 1));\n        ADDOP_COMPARE(c, LOC(p), GtE);\n        RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));\n    }\n    // Whatever comes next should consume the subject:\n    pc->on_top--;\n    if (only_wildcard) {\n        // Patterns like: [] / [_] / [_, _] / [*_] / [_, *_] / [_, _, *_] / etc.\n        ADDOP(c, LOC(p), POP_TOP);\n    }\n    else if (star_wildcard) {\n        RETURN_IF_ERROR(pattern_helper_sequence_subscr(c, LOC(p), patterns, star, pc));\n    }\n    else {\n        RETURN_IF_ERROR(pattern_helper_sequence_unpack(c, LOC(p), patterns, star, pc));\n    }\n    return SUCCESS;\n}\n\nstatic int\ncompiler_pattern_value(struct compiler *c, pattern_ty p, pattern_context *pc)\n{\n    assert(p->kind == MatchValue_kind);\n    expr_ty value = p->v.MatchValue.value;\n    if (!MATCH_VALUE_EXPR(value)) {\n        const char *e = \"patterns may only match literals and attribute lookups\";\n        return compiler_error(c, LOC(p), e);\n    }\n    VISIT(c, expr, value);\n    ADDOP_COMPARE(c, LOC(p), Eq);\n    RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));\n    return SUCCESS;\n}\n\nstatic int\ncompiler_pattern_singleton(struct compiler *c, pattern_ty p, pattern_context *pc)\n{\n    assert(p->kind == MatchSingleton_kind);\n    ADDOP_LOAD_CONST(c, LOC(p), p->v.MatchSingleton.value);\n    ADDOP_COMPARE(c, LOC(p), Is);\n    RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE));\n    return SUCCESS;\n}\n\nstatic int\ncompiler_pattern(struct compiler *c, pattern_ty p, pattern_context *pc)\n{\n    switch (p->kind) {\n        case MatchValue_kind:\n            return compiler_pattern_value(c, p, pc);\n        case MatchSingleton_kind:\n            return compiler_pattern_singleton(c, p, pc);\n        case MatchSequence_kind:\n            return compiler_pattern_sequence(c, p, pc);\n        case MatchMapping_kind:\n            return compiler_pattern_mapping(c, p, pc);\n        case MatchClass_kind:\n            return compiler_pattern_class(c, p, pc);\n        case MatchStar_kind:\n            return compiler_pattern_star(c, p, pc);\n        case MatchAs_kind:\n            return compiler_pattern_as(c, p, pc);\n        case MatchOr_kind:\n            return compiler_pattern_or(c, p, pc);\n    }\n    // AST validator shouldn't let this happen, but if it does,\n    // just fail, don't crash out of the interpreter\n    const char *e = \"invalid match pattern node in AST (kind=%d)\";\n    return compiler_error(c, LOC(p), e, p->kind);\n}\n\nstatic int\ncompiler_match_inner(struct compiler *c, stmt_ty s, pattern_context *pc)\n{\n    VISIT(c, expr, s->v.Match.subject);\n    NEW_JUMP_TARGET_LABEL(c, end);\n    Py_ssize_t cases = asdl_seq_LEN(s->v.Match.cases);\n    assert(cases > 0);\n    match_case_ty m = asdl_seq_GET(s->v.Match.cases, cases - 1);\n    int has_default = WILDCARD_CHECK(m->pattern) && 1 < cases;\n    for (Py_ssize_t i = 0; i < cases - has_default; i++) {\n        m = asdl_seq_GET(s->v.Match.cases, i);\n        // Only copy the subject if we're *not* on the last case:\n        if (i != cases - has_default - 1) {\n            ADDOP_I(c, LOC(m->pattern), COPY, 1);\n        }\n        pc->stores = PyList_New(0);\n        if (pc->stores == NULL) {\n            return ERROR;\n        }\n        // Irrefutable cases must be either guarded, last, or both:\n        pc->allow_irrefutable = m->guard != NULL || i == cases - 1;\n        pc->fail_pop = NULL;\n        pc->fail_pop_size = 0;\n        pc->on_top = 0;\n        // NOTE: Can't use returning macros here (they'll leak pc->stores)!\n        if (compiler_pattern(c, m->pattern, pc) < 0) {\n            Py_DECREF(pc->stores);\n            return ERROR;\n        }\n        assert(!pc->on_top);\n        // It's a match! Store all of the captured names (they're on the stack).\n        Py_ssize_t nstores = PyList_GET_SIZE(pc->stores);\n        for (Py_ssize_t n = 0; n < nstores; n++) {\n            PyObject *name = PyList_GET_ITEM(pc->stores, n);\n            if (compiler_nameop(c, LOC(m->pattern), name, Store) < 0) {\n                Py_DECREF(pc->stores);\n                return ERROR;\n            }\n        }\n        Py_DECREF(pc->stores);\n        // NOTE: Returning macros are safe again.\n        if (m->guard) {\n            RETURN_IF_ERROR(ensure_fail_pop(c, pc, 0));\n            RETURN_IF_ERROR(compiler_jump_if(c, LOC(m->pattern), m->guard, pc->fail_pop[0], 0));\n        }\n        // Success! Pop the subject off, we're done with it:\n        if (i != cases - has_default - 1) {\n            ADDOP(c, LOC(m->pattern), POP_TOP);\n        }\n        VISIT_SEQ(c, stmt, m->body);\n        ADDOP_JUMP(c, NO_LOCATION, JUMP, end);\n        // If the pattern fails to match, we want the line number of the\n        // cleanup to be associated with the failed pattern, not the last line\n        // of the body\n        RETURN_IF_ERROR(emit_and_reset_fail_pop(c, LOC(m->pattern), pc));\n    }\n    if (has_default) {\n        // A trailing \"case _\" is common, and lets us save a bit of redundant\n        // pushing and popping in the loop above:\n        m = asdl_seq_GET(s->v.Match.cases, cases - 1);\n        if (cases == 1) {\n            // No matches. Done with the subject:\n            ADDOP(c, LOC(m->pattern), POP_TOP);\n        }\n        else {\n            // Show line coverage for default case (it doesn't create bytecode)\n            ADDOP(c, LOC(m->pattern), NOP);\n        }\n        if (m->guard) {\n            RETURN_IF_ERROR(compiler_jump_if(c, LOC(m->pattern), m->guard, end, 0));\n        }\n        VISIT_SEQ(c, stmt, m->body);\n    }\n    USE_LABEL(c, end);\n    return SUCCESS;\n}\n\nstatic int\ncompiler_match(struct compiler *c, stmt_ty s)\n{\n    pattern_context pc;\n    pc.fail_pop = NULL;\n    int result = compiler_match_inner(c, s, &pc);\n    PyObject_Free(pc.fail_pop);\n    return result;\n}\n\n#undef WILDCARD_CHECK\n#undef WILDCARD_STAR_CHECK\n\nstatic PyObject *\nconsts_dict_keys_inorder(PyObject *dict)\n{\n    PyObject *consts, *k, *v;\n    Py_ssize_t i, pos = 0, size = PyDict_GET_SIZE(dict);\n\n    consts = PyList_New(size);   /* PyCode_Optimize() requires a list */\n    if (consts == NULL)\n        return NULL;\n    while (PyDict_Next(dict, &pos, &k, &v)) {\n        i = PyLong_AS_LONG(v);\n        /* The keys of the dictionary can be tuples wrapping a constant.\n         * (see dict_add_o and _PyCode_ConstantKey). In that case\n         * the object we want is always second. */\n        if (PyTuple_CheckExact(k)) {\n            k = PyTuple_GET_ITEM(k, 1);\n        }\n        assert(i < size);\n        assert(i >= 0);\n        PyList_SET_ITEM(consts, i, Py_NewRef(k));\n    }\n    return consts;\n}\n\nstatic int\ncompute_code_flags(struct compiler *c)\n{\n    PySTEntryObject *ste = c->u->u_ste;\n    int flags = 0;\n    if (_PyST_IsFunctionLike(c->u->u_ste)) {\n        flags |= CO_NEWLOCALS | CO_OPTIMIZED;\n        if (ste->ste_nested)\n            flags |= CO_NESTED;\n        if (ste->ste_generator && !ste->ste_coroutine)\n            flags |= CO_GENERATOR;\n        if (!ste->ste_generator && ste->ste_coroutine)\n            flags |= CO_COROUTINE;\n        if (ste->ste_generator && ste->ste_coroutine)\n            flags |= CO_ASYNC_GENERATOR;\n        if (ste->ste_varargs)\n            flags |= CO_VARARGS;\n        if (ste->ste_varkeywords)\n            flags |= CO_VARKEYWORDS;\n    }\n\n    /* (Only) inherit compilerflags in PyCF_MASK */\n    flags |= (c->c_flags.cf_flags & PyCF_MASK);\n\n    if ((IS_TOP_LEVEL_AWAIT(c)) &&\n         ste->ste_coroutine &&\n         !ste->ste_generator) {\n        flags |= CO_COROUTINE;\n    }\n\n    return flags;\n}\n\n// Merge *obj* with constant cache.\n// Unlike merge_consts_recursive(), this function doesn't work recursively.\nint\n_PyCompile_ConstCacheMergeOne(PyObject *const_cache, PyObject **obj)\n{\n    assert(PyDict_CheckExact(const_cache));\n    PyObject *key = _PyCode_ConstantKey(*obj);\n    if (key == NULL) {\n        return ERROR;\n    }\n\n    // t is borrowed reference\n    PyObject *t = PyDict_SetDefault(const_cache, key, key);\n    Py_DECREF(key);\n    if (t == NULL) {\n        return ERROR;\n    }\n    if (t == key) {  // obj is new constant.\n        return SUCCESS;\n    }\n\n    if (PyTuple_CheckExact(t)) {\n        // t is still borrowed reference\n        t = PyTuple_GET_ITEM(t, 1);\n    }\n\n    Py_SETREF(*obj, Py_NewRef(t));\n    return SUCCESS;\n}\n\n\nstatic int *\nbuild_cellfixedoffsets(_PyCompile_CodeUnitMetadata *umd)\n{\n    int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);\n    int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars);\n    int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars);\n\n    int noffsets = ncellvars + nfreevars;\n    int *fixed = PyMem_New(int, noffsets);\n    if (fixed == NULL) {\n        PyErr_NoMemory();\n        return NULL;\n    }\n    for (int i = 0; i < noffsets; i++) {\n        fixed[i] = nlocals + i;\n    }\n\n    PyObject *varname, *cellindex;\n    Py_ssize_t pos = 0;\n    while (PyDict_Next(umd->u_cellvars, &pos, &varname, &cellindex)) {\n        PyObject *varindex = PyDict_GetItem(umd->u_varnames, varname);\n        if (varindex != NULL) {\n            assert(PyLong_AS_LONG(cellindex) < INT_MAX);\n            assert(PyLong_AS_LONG(varindex) < INT_MAX);\n            int oldindex = (int)PyLong_AS_LONG(cellindex);\n            int argoffset = (int)PyLong_AS_LONG(varindex);\n            fixed[oldindex] = argoffset;\n        }\n    }\n\n    return fixed;\n}\n\nstatic int\ninsert_prefix_instructions(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock,\n                           int *fixed, int nfreevars, int code_flags)\n{\n    assert(umd->u_firstlineno > 0);\n\n    /* Add the generator prefix instructions. */\n    if (code_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) {\n        cfg_instr make_gen = {\n            .i_opcode = RETURN_GENERATOR,\n            .i_oparg = 0,\n            .i_loc = LOCATION(umd->u_firstlineno, umd->u_firstlineno, -1, -1),\n            .i_target = NULL,\n        };\n        RETURN_IF_ERROR(_PyBasicblock_InsertInstruction(entryblock, 0, &make_gen));\n        cfg_instr pop_top = {\n            .i_opcode = POP_TOP,\n            .i_oparg = 0,\n            .i_loc = NO_LOCATION,\n            .i_target = NULL,\n        };\n        RETURN_IF_ERROR(_PyBasicblock_InsertInstruction(entryblock, 1, &pop_top));\n    }\n\n    /* Set up cells for any variable that escapes, to be put in a closure. */\n    const int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars);\n    if (ncellvars) {\n        // umd->u_cellvars has the cells out of order so we sort them\n        // before adding the MAKE_CELL instructions.  Note that we\n        // adjust for arg cells, which come first.\n        const int nvars = ncellvars + (int)PyDict_GET_SIZE(umd->u_varnames);\n        int *sorted = PyMem_RawCalloc(nvars, sizeof(int));\n        if (sorted == NULL) {\n            PyErr_NoMemory();\n            return ERROR;\n        }\n        for (int i = 0; i < ncellvars; i++) {\n            sorted[fixed[i]] = i + 1;\n        }\n        for (int i = 0, ncellsused = 0; ncellsused < ncellvars; i++) {\n            int oldindex = sorted[i] - 1;\n            if (oldindex == -1) {\n                continue;\n            }\n            cfg_instr make_cell = {\n                .i_opcode = MAKE_CELL,\n                // This will get fixed in offset_derefs().\n                .i_oparg = oldindex,\n                .i_loc = NO_LOCATION,\n                .i_target = NULL,\n            };\n            if (_PyBasicblock_InsertInstruction(entryblock, ncellsused, &make_cell) < 0) {\n                PyMem_RawFree(sorted);\n                return ERROR;\n            }\n            ncellsused += 1;\n        }\n        PyMem_RawFree(sorted);\n    }\n\n    if (nfreevars) {\n        cfg_instr copy_frees = {\n            .i_opcode = COPY_FREE_VARS,\n            .i_oparg = nfreevars,\n            .i_loc = NO_LOCATION,\n            .i_target = NULL,\n        };\n        RETURN_IF_ERROR(_PyBasicblock_InsertInstruction(entryblock, 0, &copy_frees));\n    }\n\n    return SUCCESS;\n}\n\nstatic int\nfix_cell_offsets(_PyCompile_CodeUnitMetadata *umd, basicblock *entryblock, int *fixedmap)\n{\n    int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);\n    int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars);\n    int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars);\n    int noffsets = ncellvars + nfreevars;\n\n    // First deal with duplicates (arg cells).\n    int numdropped = 0;\n    for (int i = 0; i < noffsets ; i++) {\n        if (fixedmap[i] == i + nlocals) {\n            fixedmap[i] -= numdropped;\n        }\n        else {\n            // It was a duplicate (cell/arg).\n            numdropped += 1;\n        }\n    }\n\n    // Then update offsets, either relative to locals or by cell2arg.\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        for (int i = 0; i < b->b_iused; i++) {\n            cfg_instr *inst = &b->b_instr[i];\n            // This is called before extended args are generated.\n            assert(inst->i_opcode != EXTENDED_ARG);\n            int oldoffset = inst->i_oparg;\n            switch(inst->i_opcode) {\n                case MAKE_CELL:\n                case LOAD_CLOSURE:\n                case LOAD_DEREF:\n                case STORE_DEREF:\n                case DELETE_DEREF:\n                case LOAD_FROM_DICT_OR_DEREF:\n                    assert(oldoffset >= 0);\n                    assert(oldoffset < noffsets);\n                    assert(fixedmap[oldoffset] >= 0);\n                    inst->i_oparg = fixedmap[oldoffset];\n            }\n        }\n    }\n\n    return numdropped;\n}\n\n\nstatic int\nprepare_localsplus(_PyCompile_CodeUnitMetadata *umd, cfg_builder *g, int code_flags)\n{\n    assert(PyDict_GET_SIZE(umd->u_varnames) < INT_MAX);\n    assert(PyDict_GET_SIZE(umd->u_cellvars) < INT_MAX);\n    assert(PyDict_GET_SIZE(umd->u_freevars) < INT_MAX);\n    int nlocals = (int)PyDict_GET_SIZE(umd->u_varnames);\n    int ncellvars = (int)PyDict_GET_SIZE(umd->u_cellvars);\n    int nfreevars = (int)PyDict_GET_SIZE(umd->u_freevars);\n    assert(INT_MAX - nlocals - ncellvars > 0);\n    assert(INT_MAX - nlocals - ncellvars - nfreevars > 0);\n    int nlocalsplus = nlocals + ncellvars + nfreevars;\n    int* cellfixedoffsets = build_cellfixedoffsets(umd);\n    if (cellfixedoffsets == NULL) {\n        return ERROR;\n    }\n\n\n    // This must be called before fix_cell_offsets().\n    if (insert_prefix_instructions(umd, g->g_entryblock, cellfixedoffsets, nfreevars, code_flags)) {\n        PyMem_Free(cellfixedoffsets);\n        return ERROR;\n    }\n\n    int numdropped = fix_cell_offsets(umd, g->g_entryblock, cellfixedoffsets);\n    PyMem_Free(cellfixedoffsets);  // At this point we're done with it.\n    cellfixedoffsets = NULL;\n    if (numdropped < 0) {\n        return ERROR;\n    }\n\n    nlocalsplus -= numdropped;\n    return nlocalsplus;\n}\n\nstatic int\nadd_return_at_end(struct compiler *c, int addNone)\n{\n    /* Make sure every instruction stream that falls off the end returns None.\n     * This also ensures that no jump target offsets are out of bounds.\n     */\n    if (addNone) {\n        ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None);\n    }\n    ADDOP(c, NO_LOCATION, RETURN_VALUE);\n    return SUCCESS;\n}\n\nstatic int cfg_to_instr_sequence(cfg_builder *g, instr_sequence *seq);\n\nstatic PyCodeObject *\noptimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache,\n                   int code_flags, PyObject *filename)\n{\n    instr_sequence optimized_instrs;\n    memset(&optimized_instrs, 0, sizeof(instr_sequence));\n\n    PyCodeObject *co = NULL;\n    PyObject *consts = consts_dict_keys_inorder(u->u_metadata.u_consts);\n    if (consts == NULL) {\n        goto error;\n    }\n    cfg_builder g;\n    if (instr_sequence_to_cfg(&u->u_instr_sequence, &g) < 0) {\n        goto error;\n    }\n    int nparams = (int)PyList_GET_SIZE(u->u_ste->ste_varnames);\n    int nlocals = (int)PyDict_GET_SIZE(u->u_metadata.u_varnames);\n    assert(u->u_metadata.u_firstlineno);\n    if (_PyCfg_OptimizeCodeUnit(&g, consts, const_cache, code_flags, nlocals,\n                                nparams, u->u_metadata.u_firstlineno) < 0) {\n        goto error;\n    }\n\n    /** Assembly **/\n    int nlocalsplus = prepare_localsplus(&u->u_metadata, &g, code_flags);\n    if (nlocalsplus < 0) {\n        goto error;\n    }\n\n    int maxdepth = _PyCfg_Stackdepth(g.g_entryblock, code_flags);\n    if (maxdepth < 0) {\n        goto error;\n    }\n\n    _PyCfg_ConvertPseudoOps(g.g_entryblock);\n\n    /* Order of basic blocks must have been determined by now */\n\n    if (_PyCfg_ResolveJumps(&g) < 0) {\n        goto error;\n    }\n\n    /* Can't modify the bytecode after computing jump offsets. */\n\n    if (cfg_to_instr_sequence(&g, &optimized_instrs) < 0) {\n        goto error;\n    }\n\n    co = _PyAssemble_MakeCodeObject(&u->u_metadata, const_cache, consts,\n                                    maxdepth, &optimized_instrs, nlocalsplus,\n                                    code_flags, filename);\n\nerror:\n    Py_XDECREF(consts);\n    instr_sequence_fini(&optimized_instrs);\n    _PyCfgBuilder_Fini(&g);\n    return co;\n}\n\nstatic PyCodeObject *\noptimize_and_assemble(struct compiler *c, int addNone)\n{\n    struct compiler_unit *u = c->u;\n    PyObject *const_cache = c->c_const_cache;\n    PyObject *filename = c->c_filename;\n\n    int code_flags = compute_code_flags(c);\n    if (code_flags < 0) {\n        return NULL;\n    }\n\n    if (add_return_at_end(c, addNone) < 0) {\n        return NULL;\n    }\n\n    return optimize_and_assemble_code_unit(u, const_cache, code_flags, filename);\n}\n\nstatic int\ncfg_to_instr_sequence(cfg_builder *g, instr_sequence *seq)\n{\n    int lbl = 0;\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        b->b_label = (jump_target_label){lbl};\n        lbl += b->b_iused;\n    }\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        RETURN_IF_ERROR(instr_sequence_use_label(seq, b->b_label.id));\n        for (int i = 0; i < b->b_iused; i++) {\n            cfg_instr *instr = &b->b_instr[i];\n            RETURN_IF_ERROR(\n                instr_sequence_addop(seq, instr->i_opcode, instr->i_oparg, instr->i_loc));\n\n            _PyCompile_ExceptHandlerInfo *hi = &seq->s_instrs[seq->s_used-1].i_except_handler_info;\n            if (instr->i_except != NULL) {\n                hi->h_offset = instr->i_except->b_offset;\n                hi->h_startdepth = instr->i_except->b_startdepth;\n                hi->h_preserve_lasti = instr->i_except->b_preserve_lasti;\n            }\n            else {\n                hi->h_offset = -1;\n            }\n        }\n    }\n    return SUCCESS;\n}\n\n\n/* Access to compiler optimizations for unit tests.\n *\n * _PyCompile_CodeGen takes and AST, applies code-gen and\n * returns the unoptimized CFG as an instruction list.\n *\n * _PyCompile_OptimizeCfg takes an instruction list, constructs\n * a CFG, optimizes it and converts back to an instruction list.\n *\n * An instruction list is a PyList where each item is either\n * a tuple describing a single instruction:\n * (opcode, oparg, lineno, end_lineno, col, end_col), or\n * a jump target label marking the beginning of a basic block.\n */\n\nstatic int\ninstructions_to_instr_sequence(PyObject *instructions, instr_sequence *seq)\n{\n    assert(PyList_Check(instructions));\n\n    Py_ssize_t num_insts = PyList_GET_SIZE(instructions);\n    bool *is_target = PyMem_Calloc(num_insts, sizeof(bool));\n    if (is_target == NULL) {\n        return ERROR;\n    }\n    for (Py_ssize_t i = 0; i < num_insts; i++) {\n        PyObject *item = PyList_GET_ITEM(instructions, i);\n        if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 6) {\n            PyErr_SetString(PyExc_ValueError, \"expected a 6-tuple\");\n            goto error;\n        }\n        int opcode = PyLong_AsLong(PyTuple_GET_ITEM(item, 0));\n        if (PyErr_Occurred()) {\n            goto error;\n        }\n        if (HAS_TARGET(opcode)) {\n            int oparg = PyLong_AsLong(PyTuple_GET_ITEM(item, 1));\n            if (PyErr_Occurred()) {\n                goto error;\n            }\n            if (oparg < 0 || oparg >= num_insts) {\n                PyErr_SetString(PyExc_ValueError, \"label out of range\");\n                goto error;\n            }\n            is_target[oparg] = true;\n        }\n    }\n\n    for (int i = 0; i < num_insts; i++) {\n        if (is_target[i]) {\n            if (instr_sequence_use_label(seq, i) < 0) {\n                goto error;\n            }\n        }\n        PyObject *item = PyList_GET_ITEM(instructions, i);\n        if (!PyTuple_Check(item) || PyTuple_GET_SIZE(item) != 6) {\n            PyErr_SetString(PyExc_ValueError, \"expected a 6-tuple\");\n            goto error;\n        }\n        int opcode = PyLong_AsLong(PyTuple_GET_ITEM(item, 0));\n        if (PyErr_Occurred()) {\n            goto error;\n        }\n        int oparg;\n        if (HAS_ARG(opcode)) {\n            oparg = PyLong_AsLong(PyTuple_GET_ITEM(item, 1));\n            if (PyErr_Occurred()) {\n                goto error;\n            }\n        }\n        else {\n            oparg = 0;\n        }\n        location loc;\n        loc.lineno = PyLong_AsLong(PyTuple_GET_ITEM(item, 2));\n        if (PyErr_Occurred()) {\n            goto error;\n        }\n        loc.end_lineno = PyLong_AsLong(PyTuple_GET_ITEM(item, 3));\n        if (PyErr_Occurred()) {\n            goto error;\n        }\n        loc.col_offset = PyLong_AsLong(PyTuple_GET_ITEM(item, 4));\n        if (PyErr_Occurred()) {\n            goto error;\n        }\n        loc.end_col_offset = PyLong_AsLong(PyTuple_GET_ITEM(item, 5));\n        if (PyErr_Occurred()) {\n            goto error;\n        }\n        if (instr_sequence_addop(seq, opcode, oparg, loc) < 0) {\n            goto error;\n        }\n    }\n    PyMem_Free(is_target);\n    return SUCCESS;\nerror:\n    PyMem_Free(is_target);\n    return ERROR;\n}\n\nstatic int\ninstructions_to_cfg(PyObject *instructions, cfg_builder *g)\n{\n    instr_sequence seq;\n    memset(&seq, 0, sizeof(instr_sequence));\n\n    if (instructions_to_instr_sequence(instructions, &seq) < 0) {\n        goto error;\n    }\n    if (instr_sequence_to_cfg(&seq, g) < 0) {\n        goto error;\n    }\n    instr_sequence_fini(&seq);\n    return SUCCESS;\nerror:\n    instr_sequence_fini(&seq);\n    return ERROR;\n}\n\nstatic PyObject *\ninstr_sequence_to_instructions(instr_sequence *seq)\n{\n    PyObject *instructions = PyList_New(0);\n    if (instructions == NULL) {\n        return NULL;\n    }\n    for (int i = 0; i < seq->s_used; i++) {\n        instruction *instr = &seq->s_instrs[i];\n        location loc = instr->i_loc;\n        int arg = HAS_TARGET(instr->i_opcode) ?\n                  seq->s_labelmap[instr->i_oparg] : instr->i_oparg;\n\n        PyObject *inst_tuple = Py_BuildValue(\n            \"(iiiiii)\", instr->i_opcode, arg,\n            loc.lineno, loc.end_lineno,\n            loc.col_offset, loc.end_col_offset);\n        if (inst_tuple == NULL) {\n            goto error;\n        }\n\n        int res = PyList_Append(instructions, inst_tuple);\n        Py_DECREF(inst_tuple);\n        if (res != 0) {\n            goto error;\n        }\n    }\n    return instructions;\nerror:\n    Py_XDECREF(instructions);\n    return NULL;\n}\n\nstatic PyObject *\ncfg_to_instructions(cfg_builder *g)\n{\n    PyObject *instructions = PyList_New(0);\n    if (instructions == NULL) {\n        return NULL;\n    }\n    int lbl = 0;\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        b->b_label = (jump_target_label){lbl};\n        lbl += b->b_iused;\n    }\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        for (int i = 0; i < b->b_iused; i++) {\n            cfg_instr *instr = &b->b_instr[i];\n            location loc = instr->i_loc;\n            int arg = HAS_TARGET(instr->i_opcode) ?\n                      instr->i_target->b_label.id : instr->i_oparg;\n\n            PyObject *inst_tuple = Py_BuildValue(\n                \"(iiiiii)\", instr->i_opcode, arg,\n                loc.lineno, loc.end_lineno,\n                loc.col_offset, loc.end_col_offset);\n            if (inst_tuple == NULL) {\n                goto error;\n            }\n\n            if (PyList_Append(instructions, inst_tuple) != 0) {\n                Py_DECREF(inst_tuple);\n                goto error;\n            }\n            Py_DECREF(inst_tuple);\n        }\n    }\n\n    return instructions;\nerror:\n    Py_DECREF(instructions);\n    return NULL;\n}\n\nPyObject *\n_PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags,\n                   int optimize, int compile_mode)\n{\n    PyObject *res = NULL;\n    PyObject *metadata = NULL;\n\n    if (!PyAST_Check(ast)) {\n        PyErr_SetString(PyExc_TypeError, \"expected an AST\");\n        return NULL;\n    }\n\n    PyArena *arena = _PyArena_New();\n    if (arena == NULL) {\n        return NULL;\n    }\n\n    mod_ty mod = PyAST_obj2mod(ast, arena, compile_mode);\n    if (mod == NULL || !_PyAST_Validate(mod)) {\n        _PyArena_Free(arena);\n        return NULL;\n    }\n\n    struct compiler *c = new_compiler(mod, filename, pflags, optimize, arena);\n    if (c == NULL) {\n        _PyArena_Free(arena);\n        return NULL;\n    }\n\n    if (compiler_codegen(c, mod) < 0) {\n        goto finally;\n    }\n\n    _PyCompile_CodeUnitMetadata *umd = &c->u->u_metadata;\n    metadata = PyDict_New();\n    if (metadata == NULL) {\n        goto finally;\n    }\n#define SET_MATADATA_ITEM(key, value) \\\n    if (value != NULL) { \\\n        if (PyDict_SetItemString(metadata, key, value) < 0) goto finally; \\\n    }\n\n    SET_MATADATA_ITEM(\"name\", umd->u_name);\n    SET_MATADATA_ITEM(\"qualname\", umd->u_qualname);\n    SET_MATADATA_ITEM(\"consts\", umd->u_consts);\n    SET_MATADATA_ITEM(\"names\", umd->u_names);\n    SET_MATADATA_ITEM(\"varnames\", umd->u_varnames);\n    SET_MATADATA_ITEM(\"cellvars\", umd->u_cellvars);\n    SET_MATADATA_ITEM(\"freevars\", umd->u_freevars);\n#undef SET_MATADATA_ITEM\n\n#define SET_MATADATA_INT(key, value) do { \\\n        PyObject *v = PyLong_FromLong((long)value); \\\n        if (v == NULL) goto finally; \\\n        int res = PyDict_SetItemString(metadata, key, v); \\\n        Py_XDECREF(v); \\\n        if (res < 0) goto finally; \\\n    } while (0);\n\n    SET_MATADATA_INT(\"argcount\", umd->u_argcount);\n    SET_MATADATA_INT(\"posonlyargcount\", umd->u_posonlyargcount);\n    SET_MATADATA_INT(\"kwonlyargcount\", umd->u_kwonlyargcount);\n#undef SET_MATADATA_INT\n\n    int addNone = mod->kind != Expression_kind;\n    if (add_return_at_end(c, addNone) < 0) {\n        goto finally;\n    }\n\n    PyObject *insts = instr_sequence_to_instructions(INSTR_SEQUENCE(c));\n    if (insts == NULL) {\n        goto finally;\n    }\n    res = PyTuple_Pack(2, insts, metadata);\n    Py_DECREF(insts);\n\nfinally:\n    Py_XDECREF(metadata);\n    compiler_exit_scope(c);\n    compiler_free(c);\n    _PyArena_Free(arena);\n    return res;\n}\n\nPyObject *\n_PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts, int nlocals)\n{\n    PyObject *res = NULL;\n    PyObject *const_cache = PyDict_New();\n    if (const_cache == NULL) {\n        return NULL;\n    }\n\n    cfg_builder g;\n    if (instructions_to_cfg(instructions, &g) < 0) {\n        goto error;\n    }\n    int code_flags = 0, nparams = 0, firstlineno = 1;\n    if (_PyCfg_OptimizeCodeUnit(&g, consts, const_cache, code_flags, nlocals,\n                                nparams, firstlineno) < 0) {\n        goto error;\n    }\n    res = cfg_to_instructions(&g);\nerror:\n    Py_DECREF(const_cache);\n    _PyCfgBuilder_Fini(&g);\n    return res;\n}\n\nint _PyCfg_JumpLabelsToTargets(basicblock *entryblock);\n\nPyCodeObject *\n_PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename,\n                    PyObject *instructions)\n{\n    PyCodeObject *co = NULL;\n    instr_sequence optimized_instrs;\n    memset(&optimized_instrs, 0, sizeof(instr_sequence));\n\n    PyObject *const_cache = PyDict_New();\n    if (const_cache == NULL) {\n        return NULL;\n    }\n\n    cfg_builder g;\n    if (instructions_to_cfg(instructions, &g) < 0) {\n        goto error;\n    }\n\n    if (_PyCfg_JumpLabelsToTargets(g.g_entryblock) < 0) {\n        goto error;\n    }\n\n    int code_flags = 0;\n    int nlocalsplus = prepare_localsplus(umd, &g, code_flags);\n    if (nlocalsplus < 0) {\n        goto error;\n    }\n\n    int maxdepth = _PyCfg_Stackdepth(g.g_entryblock, code_flags);\n    if (maxdepth < 0) {\n        goto error;\n    }\n\n    _PyCfg_ConvertPseudoOps(g.g_entryblock);\n\n    /* Order of basic blocks must have been determined by now */\n\n    if (_PyCfg_ResolveJumps(&g) < 0) {\n        goto error;\n    }\n\n    /* Can't modify the bytecode after computing jump offsets. */\n\n    if (cfg_to_instr_sequence(&g, &optimized_instrs) < 0) {\n        goto error;\n    }\n\n    PyObject *consts = consts_dict_keys_inorder(umd->u_consts);\n    if (consts == NULL) {\n        goto error;\n    }\n    co = _PyAssemble_MakeCodeObject(umd, const_cache,\n                                    consts, maxdepth, &optimized_instrs,\n                                    nlocalsplus, code_flags, filename);\n    Py_DECREF(consts);\n\nerror:\n    Py_DECREF(const_cache);\n    _PyCfgBuilder_Fini(&g);\n    instr_sequence_fini(&optimized_instrs);\n    return co;\n}\n\n\n/* Retained for API compatibility.\n * Optimization is now done in _PyCfg_OptimizeCodeUnit */\n\nPyObject *\nPyCode_Optimize(PyObject *code, PyObject* Py_UNUSED(consts),\n                PyObject *Py_UNUSED(names), PyObject *Py_UNUSED(lnotab_obj))\n{\n    return Py_NewRef(code);\n}\n"
  },
  {
    "path": "Condvar.h",
    "content": "\n\n#ifndef _CONDVAR_IMPL_H_\n#define _CONDVAR_IMPL_H_\n\n#include \"Python.h\"\n#include \"pycore_condvar.h\"\n\n#ifdef _POSIX_THREADS\n/*\n * POSIX support\n */\n\n/* These private functions are implemented in Python/thread_pthread.h */\nint _PyThread_cond_init(PyCOND_T *cond);\nvoid _PyThread_cond_after(long long us, struct timespec *abs);\n\n/* The following functions return 0 on success, nonzero on error */\n#define PyMUTEX_INIT(mut)       pthread_mutex_init((mut), NULL)\n#define PyMUTEX_FINI(mut)       pthread_mutex_destroy(mut)\n#define PyMUTEX_LOCK(mut)       pthread_mutex_lock(mut)\n#define PyMUTEX_UNLOCK(mut)     pthread_mutex_unlock(mut)\n\n#define PyCOND_INIT(cond)       _PyThread_cond_init(cond)\n#define PyCOND_FINI(cond)       pthread_cond_destroy(cond)\n#define PyCOND_SIGNAL(cond)     pthread_cond_signal(cond)\n#define PyCOND_BROADCAST(cond)  pthread_cond_broadcast(cond)\n#define PyCOND_WAIT(cond, mut)  pthread_cond_wait((cond), (mut))\n\n/* return 0 for success, 1 on timeout, -1 on error */\nPy_LOCAL_INLINE(int)\nPyCOND_TIMEDWAIT(PyCOND_T *cond, PyMUTEX_T *mut, long long us)\n{\n    struct timespec abs_timeout;\n    _PyThread_cond_after(us, &abs_timeout);\n    int ret = pthread_cond_timedwait(cond, mut, &abs_timeout);\n    if (ret == ETIMEDOUT) {\n        return 1;\n    }\n    if (ret) {\n        return -1;\n    }\n    return 0;\n}\n\n#elif defined(NT_THREADS)\n/*\n * Windows (XP, 2003 server and later, as well as (hopefully) CE) support\n *\n * Emulated condition variables ones that work with XP and later, plus\n * example native support on VISTA and onwards.\n */\n\n#if _PY_EMULATED_WIN_CV\n\n/* The mutex is a CriticalSection object and\n   The condition variables is emulated with the help of a semaphore.\n\n   This implementation still has the problem that the threads woken\n   with a \"signal\" aren't necessarily those that are already\n   waiting.  It corresponds to listing 2 in:\n   http://birrell.org/andrew/papers/ImplementingCVs.pdf\n\n   Generic emulations of the pthread_cond_* API using\n   earlier Win32 functions can be found on the web.\n   The following read can be give background information to these issues,\n   but the implementations are all broken in some way.\n   http://www.cse.wustl.edu/~schmidt/win32-cv-1.html\n*/\n\nPy_LOCAL_INLINE(int)\nPyMUTEX_INIT(PyMUTEX_T *cs)\n{\n    InitializeCriticalSection(cs);\n    return 0;\n}\n\nPy_LOCAL_INLINE(int)\nPyMUTEX_FINI(PyMUTEX_T *cs)\n{\n    DeleteCriticalSection(cs);\n    return 0;\n}\n\nPy_LOCAL_INLINE(int)\nPyMUTEX_LOCK(PyMUTEX_T *cs)\n{\n    EnterCriticalSection(cs);\n    return 0;\n}\n\nPy_LOCAL_INLINE(int)\nPyMUTEX_UNLOCK(PyMUTEX_T *cs)\n{\n    LeaveCriticalSection(cs);\n    return 0;\n}\n\n\nPy_LOCAL_INLINE(int)\nPyCOND_INIT(PyCOND_T *cv)\n{\n    /* A semaphore with a \"large\" max value,  The positive value\n     * is only needed to catch those \"lost wakeup\" events and\n     * race conditions when a timed wait elapses.\n     */\n    cv->sem = CreateSemaphore(NULL, 0, 100000, NULL);\n    if (cv->sem==NULL)\n        return -1;\n    cv->waiting = 0;\n    return 0;\n}\n\nPy_LOCAL_INLINE(int)\nPyCOND_FINI(PyCOND_T *cv)\n{\n    return CloseHandle(cv->sem) ? 0 : -1;\n}\n\n/* this implementation can detect a timeout.  Returns 1 on timeout,\n * 0 otherwise (and -1 on error)\n */\nPy_LOCAL_INLINE(int)\n_PyCOND_WAIT_MS(PyCOND_T *cv, PyMUTEX_T *cs, DWORD ms)\n{\n    DWORD wait;\n    cv->waiting++;\n    PyMUTEX_UNLOCK(cs);\n    /* \"lost wakeup bug\" would occur if the caller were interrupted here,\n     * but we are safe because we are using a semaphore which has an internal\n     * count.\n     */\n    wait = WaitForSingleObjectEx(cv->sem, ms, FALSE);\n    PyMUTEX_LOCK(cs);\n    if (wait != WAIT_OBJECT_0)\n        --cv->waiting;\n        /* Here we have a benign race condition with PyCOND_SIGNAL.\n         * When failure occurs or timeout, it is possible that\n         * PyCOND_SIGNAL also decrements this value\n         * and signals releases the mutex.  This is benign because it\n         * just means an extra spurious wakeup for a waiting thread.\n         * ('waiting' corresponds to the semaphore's \"negative\" count and\n         * we may end up with e.g. (waiting == -1 && sem.count == 1).  When\n         * a new thread comes along, it will pass right through, having\n         * adjusted it to (waiting == 0 && sem.count == 0).\n         */\n\n    if (wait == WAIT_FAILED)\n        return -1;\n    /* return 0 on success, 1 on timeout */\n    return wait != WAIT_OBJECT_0;\n}\n\nPy_LOCAL_INLINE(int)\nPyCOND_WAIT(PyCOND_T *cv, PyMUTEX_T *cs)\n{\n    int result = _PyCOND_WAIT_MS(cv, cs, INFINITE);\n    return result >= 0 ? 0 : result;\n}\n\nPy_LOCAL_INLINE(int)\nPyCOND_TIMEDWAIT(PyCOND_T *cv, PyMUTEX_T *cs, long long us)\n{\n    return _PyCOND_WAIT_MS(cv, cs, (DWORD)(us/1000));\n}\n\nPy_LOCAL_INLINE(int)\nPyCOND_SIGNAL(PyCOND_T *cv)\n{\n    /* this test allows PyCOND_SIGNAL to be a no-op unless required\n     * to wake someone up, thus preventing an unbounded increase of\n     * the semaphore's internal counter.\n     */\n    if (cv->waiting > 0) {\n        /* notifying thread decreases the cv->waiting count so that\n         * a delay between notify and actual wakeup of the target thread\n         * doesn't cause a number of extra ReleaseSemaphore calls.\n         */\n        cv->waiting--;\n        return ReleaseSemaphore(cv->sem, 1, NULL) ? 0 : -1;\n    }\n    return 0;\n}\n\nPy_LOCAL_INLINE(int)\nPyCOND_BROADCAST(PyCOND_T *cv)\n{\n    int waiting = cv->waiting;\n    if (waiting > 0) {\n        cv->waiting = 0;\n        return ReleaseSemaphore(cv->sem, waiting, NULL) ? 0 : -1;\n    }\n    return 0;\n}\n\n#else /* !_PY_EMULATED_WIN_CV */\n\nPy_LOCAL_INLINE(int)\nPyMUTEX_INIT(PyMUTEX_T *cs)\n{\n    InitializeSRWLock(cs);\n    return 0;\n}\n\nPy_LOCAL_INLINE(int)\nPyMUTEX_FINI(PyMUTEX_T *cs)\n{\n    return 0;\n}\n\nPy_LOCAL_INLINE(int)\nPyMUTEX_LOCK(PyMUTEX_T *cs)\n{\n    AcquireSRWLockExclusive(cs);\n    return 0;\n}\n\nPy_LOCAL_INLINE(int)\nPyMUTEX_UNLOCK(PyMUTEX_T *cs)\n{\n    ReleaseSRWLockExclusive(cs);\n    return 0;\n}\n\n\nPy_LOCAL_INLINE(int)\nPyCOND_INIT(PyCOND_T *cv)\n{\n    InitializeConditionVariable(cv);\n    return 0;\n}\nPy_LOCAL_INLINE(int)\nPyCOND_FINI(PyCOND_T *cv)\n{\n    return 0;\n}\n\nPy_LOCAL_INLINE(int)\nPyCOND_WAIT(PyCOND_T *cv, PyMUTEX_T *cs)\n{\n    return SleepConditionVariableSRW(cv, cs, INFINITE, 0) ? 0 : -1;\n}\n\n/* This implementation makes no distinction about timeouts.  Signal\n * 2 to indicate that we don't know.\n */\nPy_LOCAL_INLINE(int)\nPyCOND_TIMEDWAIT(PyCOND_T *cv, PyMUTEX_T *cs, long long us)\n{\n    return SleepConditionVariableSRW(cv, cs, (DWORD)(us/1000), 0) ? 2 : -1;\n}\n\nPy_LOCAL_INLINE(int)\nPyCOND_SIGNAL(PyCOND_T *cv)\n{\n     WakeConditionVariable(cv);\n     return 0;\n}\n\nPy_LOCAL_INLINE(int)\nPyCOND_BROADCAST(PyCOND_T *cv)\n{\n     WakeAllConditionVariable(cv);\n     return 0;\n}\n\n\n#endif /* _PY_EMULATED_WIN_CV */\n\n#endif /* _POSIX_THREADS, NT_THREADS */\n\n#endif /* _CONDVAR_IMPL_H_ */\n"
  },
  {
    "path": "Context.c",
    "content": "#include \"Python.h\"\n#include \"pycore_call.h\"          // _PyObject_VectorcallTstate()\n#include \"pycore_context.h\"\n#include \"pycore_gc.h\"            // _PyObject_GC_MAY_BE_TRACKED()\n#include \"pycore_hamt.h\"\n#include \"pycore_initconfig.h\"    // _PyStatus_OK()\n#include \"pycore_object.h\"\n#include \"pycore_pyerrors.h\"\n#include \"pycore_pystate.h\"       // _PyThreadState_GET()\n#include \"structmember.h\"         // PyMemberDef\n\n\n#include \"clinic/context.c.h\"\n/*[clinic input]\nmodule _contextvars\n[clinic start generated code]*/\n/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a0955718c8b8cea6]*/\n\n\n#define ENSURE_Context(o, err_ret)                                  \\\n    if (!PyContext_CheckExact(o)) {                                 \\\n        PyErr_SetString(PyExc_TypeError,                            \\\n                        \"an instance of Context was expected\");     \\\n        return err_ret;                                             \\\n    }\n\n#define ENSURE_ContextVar(o, err_ret)                               \\\n    if (!PyContextVar_CheckExact(o)) {                              \\\n        PyErr_SetString(PyExc_TypeError,                            \\\n                       \"an instance of ContextVar was expected\");   \\\n        return err_ret;                                             \\\n    }\n\n#define ENSURE_ContextToken(o, err_ret)                             \\\n    if (!PyContextToken_CheckExact(o)) {                            \\\n        PyErr_SetString(PyExc_TypeError,                            \\\n                        \"an instance of Token was expected\");       \\\n        return err_ret;                                             \\\n    }\n\n\n/////////////////////////// Context API\n\n\nstatic PyContext *\ncontext_new_empty(void);\n\nstatic PyContext *\ncontext_new_from_vars(PyHamtObject *vars);\n\nstatic inline PyContext *\ncontext_get(void);\n\nstatic PyContextToken *\ntoken_new(PyContext *ctx, PyContextVar *var, PyObject *val);\n\nstatic PyContextVar *\ncontextvar_new(PyObject *name, PyObject *def);\n\nstatic int\ncontextvar_set(PyContextVar *var, PyObject *val);\n\nstatic int\ncontextvar_del(PyContextVar *var);\n\n\n#if PyContext_MAXFREELIST > 0\nstatic struct _Py_context_state *\nget_context_state(void)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    return &interp->context;\n}\n#endif\n\n\nPyObject *\n_PyContext_NewHamtForTests(void)\n{\n    return (PyObject *)_PyHamt_New();\n}\n\n\nPyObject *\nPyContext_New(void)\n{\n    return (PyObject *)context_new_empty();\n}\n\n\nPyObject *\nPyContext_Copy(PyObject * octx)\n{\n    ENSURE_Context(octx, NULL)\n    PyContext *ctx = (PyContext *)octx;\n    return (PyObject *)context_new_from_vars(ctx->ctx_vars);\n}\n\n\nPyObject *\nPyContext_CopyCurrent(void)\n{\n    PyContext *ctx = context_get();\n    if (ctx == NULL) {\n        return NULL;\n    }\n\n    return (PyObject *)context_new_from_vars(ctx->ctx_vars);\n}\n\n\nstatic int\n_PyContext_Enter(PyThreadState *ts, PyObject *octx)\n{\n    ENSURE_Context(octx, -1)\n    PyContext *ctx = (PyContext *)octx;\n\n    if (ctx->ctx_entered) {\n        _PyErr_Format(ts, PyExc_RuntimeError,\n                      \"cannot enter context: %R is already entered\", ctx);\n        return -1;\n    }\n\n    ctx->ctx_prev = (PyContext *)ts->context;  /* borrow */\n    ctx->ctx_entered = 1;\n\n    ts->context = Py_NewRef(ctx);\n    ts->context_ver++;\n\n    return 0;\n}\n\n\nint\nPyContext_Enter(PyObject *octx)\n{\n    PyThreadState *ts = _PyThreadState_GET();\n    assert(ts != NULL);\n    return _PyContext_Enter(ts, octx);\n}\n\n\nstatic int\n_PyContext_Exit(PyThreadState *ts, PyObject *octx)\n{\n    ENSURE_Context(octx, -1)\n    PyContext *ctx = (PyContext *)octx;\n\n    if (!ctx->ctx_entered) {\n        PyErr_Format(PyExc_RuntimeError,\n                     \"cannot exit context: %R has not been entered\", ctx);\n        return -1;\n    }\n\n    if (ts->context != (PyObject *)ctx) {\n        /* Can only happen if someone misuses the C API */\n        PyErr_SetString(PyExc_RuntimeError,\n                        \"cannot exit context: thread state references \"\n                        \"a different context object\");\n        return -1;\n    }\n\n    Py_SETREF(ts->context, (PyObject *)ctx->ctx_prev);\n    ts->context_ver++;\n\n    ctx->ctx_prev = NULL;\n    ctx->ctx_entered = 0;\n\n    return 0;\n}\n\nint\nPyContext_Exit(PyObject *octx)\n{\n    PyThreadState *ts = _PyThreadState_GET();\n    assert(ts != NULL);\n    return _PyContext_Exit(ts, octx);\n}\n\n\nPyObject *\nPyContextVar_New(const char *name, PyObject *def)\n{\n    PyObject *pyname = PyUnicode_FromString(name);\n    if (pyname == NULL) {\n        return NULL;\n    }\n    PyContextVar *var = contextvar_new(pyname, def);\n    Py_DECREF(pyname);\n    return (PyObject *)var;\n}\n\n\nint\nPyContextVar_Get(PyObject *ovar, PyObject *def, PyObject **val)\n{\n    ENSURE_ContextVar(ovar, -1)\n    PyContextVar *var = (PyContextVar *)ovar;\n\n    PyThreadState *ts = _PyThreadState_GET();\n    assert(ts != NULL);\n    if (ts->context == NULL) {\n        goto not_found;\n    }\n\n    if (var->var_cached != NULL &&\n            var->var_cached_tsid == ts->id &&\n            var->var_cached_tsver == ts->context_ver)\n    {\n        *val = var->var_cached;\n        goto found;\n    }\n\n    assert(PyContext_CheckExact(ts->context));\n    PyHamtObject *vars = ((PyContext *)ts->context)->ctx_vars;\n\n    PyObject *found = NULL;\n    int res = _PyHamt_Find(vars, (PyObject*)var, &found);\n    if (res < 0) {\n        goto error;\n    }\n    if (res == 1) {\n        assert(found != NULL);\n        var->var_cached = found;  /* borrow */\n        var->var_cached_tsid = ts->id;\n        var->var_cached_tsver = ts->context_ver;\n\n        *val = found;\n        goto found;\n    }\n\nnot_found:\n    if (def == NULL) {\n        if (var->var_default != NULL) {\n            *val = var->var_default;\n            goto found;\n        }\n\n        *val = NULL;\n        goto found;\n    }\n    else {\n        *val = def;\n        goto found;\n   }\n\nfound:\n    Py_XINCREF(*val);\n    return 0;\n\nerror:\n    *val = NULL;\n    return -1;\n}\n\n\nPyObject *\nPyContextVar_Set(PyObject *ovar, PyObject *val)\n{\n    ENSURE_ContextVar(ovar, NULL)\n    PyContextVar *var = (PyContextVar *)ovar;\n\n    if (!PyContextVar_CheckExact(var)) {\n        PyErr_SetString(\n            PyExc_TypeError, \"an instance of ContextVar was expected\");\n        return NULL;\n    }\n\n    PyContext *ctx = context_get();\n    if (ctx == NULL) {\n        return NULL;\n    }\n\n    PyObject *old_val = NULL;\n    int found = _PyHamt_Find(ctx->ctx_vars, (PyObject *)var, &old_val);\n    if (found < 0) {\n        return NULL;\n    }\n\n    Py_XINCREF(old_val);\n    PyContextToken *tok = token_new(ctx, var, old_val);\n    Py_XDECREF(old_val);\n\n    if (contextvar_set(var, val)) {\n        Py_DECREF(tok);\n        return NULL;\n    }\n\n    return (PyObject *)tok;\n}\n\n\nint\nPyContextVar_Reset(PyObject *ovar, PyObject *otok)\n{\n    ENSURE_ContextVar(ovar, -1)\n    ENSURE_ContextToken(otok, -1)\n    PyContextVar *var = (PyContextVar *)ovar;\n    PyContextToken *tok = (PyContextToken *)otok;\n\n    if (tok->tok_used) {\n        PyErr_Format(PyExc_RuntimeError,\n                     \"%R has already been used once\", tok);\n        return -1;\n    }\n\n    if (var != tok->tok_var) {\n        PyErr_Format(PyExc_ValueError,\n                     \"%R was created by a different ContextVar\", tok);\n        return -1;\n    }\n\n    PyContext *ctx = context_get();\n    if (ctx != tok->tok_ctx) {\n        PyErr_Format(PyExc_ValueError,\n                     \"%R was created in a different Context\", tok);\n        return -1;\n    }\n\n    tok->tok_used = 1;\n\n    if (tok->tok_oldval == NULL) {\n        return contextvar_del(var);\n    }\n    else {\n        return contextvar_set(var, tok->tok_oldval);\n    }\n}\n\n\n/////////////////////////// PyContext\n\n/*[clinic input]\nclass _contextvars.Context \"PyContext *\" \"&PyContext_Type\"\n[clinic start generated code]*/\n/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bdf87f8e0cb580e8]*/\n\n\nstatic inline PyContext *\n_context_alloc(void)\n{\n    PyContext *ctx;\n#if PyContext_MAXFREELIST > 0\n    struct _Py_context_state *state = get_context_state();\n#ifdef Py_DEBUG\n    // _context_alloc() must not be called after _PyContext_Fini()\n    assert(state->numfree != -1);\n#endif\n    if (state->numfree) {\n        state->numfree--;\n        ctx = state->freelist;\n        state->freelist = (PyContext *)ctx->ctx_weakreflist;\n        OBJECT_STAT_INC(from_freelist);\n        ctx->ctx_weakreflist = NULL;\n        _Py_NewReference((PyObject *)ctx);\n    }\n    else\n#endif\n    {\n        ctx = PyObject_GC_New(PyContext, &PyContext_Type);\n        if (ctx == NULL) {\n            return NULL;\n        }\n    }\n\n    ctx->ctx_vars = NULL;\n    ctx->ctx_prev = NULL;\n    ctx->ctx_entered = 0;\n    ctx->ctx_weakreflist = NULL;\n\n    return ctx;\n}\n\n\nstatic PyContext *\ncontext_new_empty(void)\n{\n    PyContext *ctx = _context_alloc();\n    if (ctx == NULL) {\n        return NULL;\n    }\n\n    ctx->ctx_vars = _PyHamt_New();\n    if (ctx->ctx_vars == NULL) {\n        Py_DECREF(ctx);\n        return NULL;\n    }\n\n    _PyObject_GC_TRACK(ctx);\n    return ctx;\n}\n\n\nstatic PyContext *\ncontext_new_from_vars(PyHamtObject *vars)\n{\n    PyContext *ctx = _context_alloc();\n    if (ctx == NULL) {\n        return NULL;\n    }\n\n    ctx->ctx_vars = (PyHamtObject*)Py_NewRef(vars);\n\n    _PyObject_GC_TRACK(ctx);\n    return ctx;\n}\n\n\nstatic inline PyContext *\ncontext_get(void)\n{\n    PyThreadState *ts = _PyThreadState_GET();\n    assert(ts != NULL);\n    PyContext *current_ctx = (PyContext *)ts->context;\n    if (current_ctx == NULL) {\n        current_ctx = context_new_empty();\n        if (current_ctx == NULL) {\n            return NULL;\n        }\n        ts->context = (PyObject *)current_ctx;\n    }\n    return current_ctx;\n}\n\nstatic int\ncontext_check_key_type(PyObject *key)\n{\n    if (!PyContextVar_CheckExact(key)) {\n        // abort();\n        PyErr_Format(PyExc_TypeError,\n                     \"a ContextVar key was expected, got %R\", key);\n        return -1;\n    }\n    return 0;\n}\n\nstatic PyObject *\ncontext_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n{\n    if (PyTuple_Size(args) || (kwds != NULL && PyDict_Size(kwds))) {\n        PyErr_SetString(\n            PyExc_TypeError, \"Context() does not accept any arguments\");\n        return NULL;\n    }\n    return PyContext_New();\n}\n\nstatic int\ncontext_tp_clear(PyContext *self)\n{\n    Py_CLEAR(self->ctx_prev);\n    Py_CLEAR(self->ctx_vars);\n    return 0;\n}\n\nstatic int\ncontext_tp_traverse(PyContext *self, visitproc visit, void *arg)\n{\n    Py_VISIT(self->ctx_prev);\n    Py_VISIT(self->ctx_vars);\n    return 0;\n}\n\nstatic void\ncontext_tp_dealloc(PyContext *self)\n{\n    _PyObject_GC_UNTRACK(self);\n\n    if (self->ctx_weakreflist != NULL) {\n        PyObject_ClearWeakRefs((PyObject*)self);\n    }\n    (void)context_tp_clear(self);\n\n#if PyContext_MAXFREELIST > 0\n    struct _Py_context_state *state = get_context_state();\n#ifdef Py_DEBUG\n    // _context_alloc() must not be called after _PyContext_Fini()\n    assert(state->numfree != -1);\n#endif\n    if (state->numfree < PyContext_MAXFREELIST) {\n        state->numfree++;\n        self->ctx_weakreflist = (PyObject *)state->freelist;\n        state->freelist = self;\n        OBJECT_STAT_INC(to_freelist);\n    }\n    else\n#endif\n    {\n        Py_TYPE(self)->tp_free(self);\n    }\n}\n\nstatic PyObject *\ncontext_tp_iter(PyContext *self)\n{\n    return _PyHamt_NewIterKeys(self->ctx_vars);\n}\n\nstatic PyObject *\ncontext_tp_richcompare(PyObject *v, PyObject *w, int op)\n{\n    if (!PyContext_CheckExact(v) || !PyContext_CheckExact(w) ||\n            (op != Py_EQ && op != Py_NE))\n    {\n        Py_RETURN_NOTIMPLEMENTED;\n    }\n\n    int res = _PyHamt_Eq(\n        ((PyContext *)v)->ctx_vars, ((PyContext *)w)->ctx_vars);\n    if (res < 0) {\n        return NULL;\n    }\n\n    if (op == Py_NE) {\n        res = !res;\n    }\n\n    if (res) {\n        Py_RETURN_TRUE;\n    }\n    else {\n        Py_RETURN_FALSE;\n    }\n}\n\nstatic Py_ssize_t\ncontext_tp_len(PyContext *self)\n{\n    return _PyHamt_Len(self->ctx_vars);\n}\n\nstatic PyObject *\ncontext_tp_subscript(PyContext *self, PyObject *key)\n{\n    if (context_check_key_type(key)) {\n        return NULL;\n    }\n    PyObject *val = NULL;\n    int found = _PyHamt_Find(self->ctx_vars, key, &val);\n    if (found < 0) {\n        return NULL;\n    }\n    if (found == 0) {\n        PyErr_SetObject(PyExc_KeyError, key);\n        return NULL;\n    }\n    return Py_NewRef(val);\n}\n\nstatic int\ncontext_tp_contains(PyContext *self, PyObject *key)\n{\n    if (context_check_key_type(key)) {\n        return -1;\n    }\n    PyObject *val = NULL;\n    return _PyHamt_Find(self->ctx_vars, key, &val);\n}\n\n\n/*[clinic input]\n_contextvars.Context.get\n    key: object\n    default: object = None\n    /\n\nReturn the value for `key` if `key` has the value in the context object.\n\nIf `key` does not exist, return `default`. If `default` is not given,\nreturn None.\n[clinic start generated code]*/\n\nstatic PyObject *\n_contextvars_Context_get_impl(PyContext *self, PyObject *key,\n                              PyObject *default_value)\n/*[clinic end generated code: output=0c54aa7664268189 input=c8eeb81505023995]*/\n{\n    if (context_check_key_type(key)) {\n        return NULL;\n    }\n\n    PyObject *val = NULL;\n    int found = _PyHamt_Find(self->ctx_vars, key, &val);\n    if (found < 0) {\n        return NULL;\n    }\n    if (found == 0) {\n        return Py_NewRef(default_value);\n    }\n    return Py_NewRef(val);\n}\n\n\n/*[clinic input]\n_contextvars.Context.items\n\nReturn all variables and their values in the context object.\n\nThe result is returned as a list of 2-tuples (variable, value).\n[clinic start generated code]*/\n\nstatic PyObject *\n_contextvars_Context_items_impl(PyContext *self)\n/*[clinic end generated code: output=fa1655c8a08502af input=00db64ae379f9f42]*/\n{\n    return _PyHamt_NewIterItems(self->ctx_vars);\n}\n\n\n/*[clinic input]\n_contextvars.Context.keys\n\nReturn a list of all variables in the context object.\n[clinic start generated code]*/\n\nstatic PyObject *\n_contextvars_Context_keys_impl(PyContext *self)\n/*[clinic end generated code: output=177227c6b63ec0e2 input=114b53aebca3449c]*/\n{\n    return _PyHamt_NewIterKeys(self->ctx_vars);\n}\n\n\n/*[clinic input]\n_contextvars.Context.values\n\nReturn a list of all variables' values in the context object.\n[clinic start generated code]*/\n\nstatic PyObject *\n_contextvars_Context_values_impl(PyContext *self)\n/*[clinic end generated code: output=d286dabfc8db6dde input=ce8075d04a6ea526]*/\n{\n    return _PyHamt_NewIterValues(self->ctx_vars);\n}\n\n\n/*[clinic input]\n_contextvars.Context.copy\n\nReturn a shallow copy of the context object.\n[clinic start generated code]*/\n\nstatic PyObject *\n_contextvars_Context_copy_impl(PyContext *self)\n/*[clinic end generated code: output=30ba8896c4707a15 input=ebafdbdd9c72d592]*/\n{\n    return (PyObject *)context_new_from_vars(self->ctx_vars);\n}\n\n\nstatic PyObject *\ncontext_run(PyContext *self, PyObject *const *args,\n            Py_ssize_t nargs, PyObject *kwnames)\n{\n    PyThreadState *ts = _PyThreadState_GET();\n\n    if (nargs < 1) {\n        _PyErr_SetString(ts, PyExc_TypeError,\n                         \"run() missing 1 required positional argument\");\n        return NULL;\n    }\n\n    if (_PyContext_Enter(ts, (PyObject *)self)) {\n        return NULL;\n    }\n\n    PyObject *call_result = _PyObject_VectorcallTstate(\n        ts, args[0], args + 1, nargs - 1, kwnames);\n\n    if (_PyContext_Exit(ts, (PyObject *)self)) {\n        return NULL;\n    }\n\n    return call_result;\n}\n\n\nstatic PyMethodDef PyContext_methods[] = {\n    _CONTEXTVARS_CONTEXT_GET_METHODDEF\n    _CONTEXTVARS_CONTEXT_ITEMS_METHODDEF\n    _CONTEXTVARS_CONTEXT_KEYS_METHODDEF\n    _CONTEXTVARS_CONTEXT_VALUES_METHODDEF\n    _CONTEXTVARS_CONTEXT_COPY_METHODDEF\n    {\"run\", _PyCFunction_CAST(context_run), METH_FASTCALL | METH_KEYWORDS, NULL},\n    {NULL, NULL}\n};\n\nstatic PySequenceMethods PyContext_as_sequence = {\n    0,                                   /* sq_length */\n    0,                                   /* sq_concat */\n    0,                                   /* sq_repeat */\n    0,                                   /* sq_item */\n    0,                                   /* sq_slice */\n    0,                                   /* sq_ass_item */\n    0,                                   /* sq_ass_slice */\n    (objobjproc)context_tp_contains,     /* sq_contains */\n    0,                                   /* sq_inplace_concat */\n    0,                                   /* sq_inplace_repeat */\n};\n\nstatic PyMappingMethods PyContext_as_mapping = {\n    (lenfunc)context_tp_len,             /* mp_length */\n    (binaryfunc)context_tp_subscript,    /* mp_subscript */\n};\n\nPyTypeObject PyContext_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"_contextvars.Context\",\n    sizeof(PyContext),\n    .tp_methods = PyContext_methods,\n    .tp_as_mapping = &PyContext_as_mapping,\n    .tp_as_sequence = &PyContext_as_sequence,\n    .tp_iter = (getiterfunc)context_tp_iter,\n    .tp_dealloc = (destructor)context_tp_dealloc,\n    .tp_getattro = PyObject_GenericGetAttr,\n    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,\n    .tp_richcompare = context_tp_richcompare,\n    .tp_traverse = (traverseproc)context_tp_traverse,\n    .tp_clear = (inquiry)context_tp_clear,\n    .tp_new = context_tp_new,\n    .tp_weaklistoffset = offsetof(PyContext, ctx_weakreflist),\n    .tp_hash = PyObject_HashNotImplemented,\n};\n\n\n/////////////////////////// ContextVar\n\n\nstatic int\ncontextvar_set(PyContextVar *var, PyObject *val)\n{\n    var->var_cached = NULL;\n    PyThreadState *ts = _PyThreadState_GET();\n\n    PyContext *ctx = context_get();\n    if (ctx == NULL) {\n        return -1;\n    }\n\n    PyHamtObject *new_vars = _PyHamt_Assoc(\n        ctx->ctx_vars, (PyObject *)var, val);\n    if (new_vars == NULL) {\n        return -1;\n    }\n\n    Py_SETREF(ctx->ctx_vars, new_vars);\n\n    var->var_cached = val;  /* borrow */\n    var->var_cached_tsid = ts->id;\n    var->var_cached_tsver = ts->context_ver;\n    return 0;\n}\n\nstatic int\ncontextvar_del(PyContextVar *var)\n{\n    var->var_cached = NULL;\n\n    PyContext *ctx = context_get();\n    if (ctx == NULL) {\n        return -1;\n    }\n\n    PyHamtObject *vars = ctx->ctx_vars;\n    PyHamtObject *new_vars = _PyHamt_Without(vars, (PyObject *)var);\n    if (new_vars == NULL) {\n        return -1;\n    }\n\n    if (vars == new_vars) {\n        Py_DECREF(new_vars);\n        PyErr_SetObject(PyExc_LookupError, (PyObject *)var);\n        return -1;\n    }\n\n    Py_SETREF(ctx->ctx_vars, new_vars);\n    return 0;\n}\n\nstatic Py_hash_t\ncontextvar_generate_hash(void *addr, PyObject *name)\n{\n    /* Take hash of `name` and XOR it with the object's addr.\n\n       The structure of the tree is encoded in objects' hashes, which\n       means that sufficiently similar hashes would result in tall trees\n       with many Collision nodes.  Which would, in turn, result in slower\n       get and set operations.\n\n       The XORing helps to ensure that:\n\n       (1) sequentially allocated ContextVar objects have\n           different hashes;\n\n       (2) context variables with equal names have\n           different hashes.\n    */\n\n    Py_hash_t name_hash = PyObject_Hash(name);\n    if (name_hash == -1) {\n        return -1;\n    }\n\n    Py_hash_t res = _Py_HashPointer(addr) ^ name_hash;\n    return res == -1 ? -2 : res;\n}\n\nstatic PyContextVar *\ncontextvar_new(PyObject *name, PyObject *def)\n{\n    if (!PyUnicode_Check(name)) {\n        PyErr_SetString(PyExc_TypeError,\n                        \"context variable name must be a str\");\n        return NULL;\n    }\n\n    PyContextVar *var = PyObject_GC_New(PyContextVar, &PyContextVar_Type);\n    if (var == NULL) {\n        return NULL;\n    }\n\n    var->var_hash = contextvar_generate_hash(var, name);\n    if (var->var_hash == -1) {\n        Py_DECREF(var);\n        return NULL;\n    }\n\n    var->var_name = Py_NewRef(name);\n\n    var->var_default = Py_XNewRef(def);\n\n    var->var_cached = NULL;\n    var->var_cached_tsid = 0;\n    var->var_cached_tsver = 0;\n\n    if (_PyObject_GC_MAY_BE_TRACKED(name) ||\n            (def != NULL && _PyObject_GC_MAY_BE_TRACKED(def)))\n    {\n        PyObject_GC_Track(var);\n    }\n    return var;\n}\n\n\n/*[clinic input]\nclass _contextvars.ContextVar \"PyContextVar *\" \"&PyContextVar_Type\"\n[clinic start generated code]*/\n/*[clinic end generated code: output=da39a3ee5e6b4b0d input=445da935fa8883c3]*/\n\n\nstatic PyObject *\ncontextvar_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n{\n    static char *kwlist[] = {\"\", \"default\", NULL};\n    PyObject *name;\n    PyObject *def = NULL;\n\n    if (!PyArg_ParseTupleAndKeywords(\n            args, kwds, \"O|$O:ContextVar\", kwlist, &name, &def))\n    {\n        return NULL;\n    }\n\n    return (PyObject *)contextvar_new(name, def);\n}\n\nstatic int\ncontextvar_tp_clear(PyContextVar *self)\n{\n    Py_CLEAR(self->var_name);\n    Py_CLEAR(self->var_default);\n    self->var_cached = NULL;\n    self->var_cached_tsid = 0;\n    self->var_cached_tsver = 0;\n    return 0;\n}\n\nstatic int\ncontextvar_tp_traverse(PyContextVar *self, visitproc visit, void *arg)\n{\n    Py_VISIT(self->var_name);\n    Py_VISIT(self->var_default);\n    return 0;\n}\n\nstatic void\ncontextvar_tp_dealloc(PyContextVar *self)\n{\n    PyObject_GC_UnTrack(self);\n    (void)contextvar_tp_clear(self);\n    Py_TYPE(self)->tp_free(self);\n}\n\nstatic Py_hash_t\ncontextvar_tp_hash(PyContextVar *self)\n{\n    return self->var_hash;\n}\n\nstatic PyObject *\ncontextvar_tp_repr(PyContextVar *self)\n{\n    _PyUnicodeWriter writer;\n\n    _PyUnicodeWriter_Init(&writer);\n\n    if (_PyUnicodeWriter_WriteASCIIString(\n            &writer, \"<ContextVar name=\", 17) < 0)\n    {\n        goto error;\n    }\n\n    PyObject *name = PyObject_Repr(self->var_name);\n    if (name == NULL) {\n        goto error;\n    }\n    if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) {\n        Py_DECREF(name);\n        goto error;\n    }\n    Py_DECREF(name);\n\n    if (self->var_default != NULL) {\n        if (_PyUnicodeWriter_WriteASCIIString(&writer, \" default=\", 9) < 0) {\n            goto error;\n        }\n\n        PyObject *def = PyObject_Repr(self->var_default);\n        if (def == NULL) {\n            goto error;\n        }\n        if (_PyUnicodeWriter_WriteStr(&writer, def) < 0) {\n            Py_DECREF(def);\n            goto error;\n        }\n        Py_DECREF(def);\n    }\n\n    PyObject *addr = PyUnicode_FromFormat(\" at %p>\", self);\n    if (addr == NULL) {\n        goto error;\n    }\n    if (_PyUnicodeWriter_WriteStr(&writer, addr) < 0) {\n        Py_DECREF(addr);\n        goto error;\n    }\n    Py_DECREF(addr);\n\n    return _PyUnicodeWriter_Finish(&writer);\n\nerror:\n    _PyUnicodeWriter_Dealloc(&writer);\n    return NULL;\n}\n\n\n/*[clinic input]\n_contextvars.ContextVar.get\n    default: object = NULL\n    /\n\nReturn a value for the context variable for the current context.\n\nIf there is no value for the variable in the current context, the method will:\n * return the value of the default argument of the method, if provided; or\n * return the default value for the context variable, if it was created\n   with one; or\n * raise a LookupError.\n[clinic start generated code]*/\n\nstatic PyObject *\n_contextvars_ContextVar_get_impl(PyContextVar *self, PyObject *default_value)\n/*[clinic end generated code: output=0746bd0aa2ced7bf input=30aa2ab9e433e401]*/\n{\n    if (!PyContextVar_CheckExact(self)) {\n        PyErr_SetString(\n            PyExc_TypeError, \"an instance of ContextVar was expected\");\n        return NULL;\n    }\n\n    PyObject *val;\n    if (PyContextVar_Get((PyObject *)self, default_value, &val) < 0) {\n        return NULL;\n    }\n\n    if (val == NULL) {\n        PyErr_SetObject(PyExc_LookupError, (PyObject *)self);\n        return NULL;\n    }\n\n    return val;\n}\n\n/*[clinic input]\n_contextvars.ContextVar.set\n    value: object\n    /\n\nCall to set a new value for the context variable in the current context.\n\nThe required value argument is the new value for the context variable.\n\nReturns a Token object that can be used to restore the variable to its previous\nvalue via the `ContextVar.reset()` method.\n[clinic start generated code]*/\n\nstatic PyObject *\n_contextvars_ContextVar_set(PyContextVar *self, PyObject *value)\n/*[clinic end generated code: output=446ed5e820d6d60b input=c0a6887154227453]*/\n{\n    return PyContextVar_Set((PyObject *)self, value);\n}\n\n/*[clinic input]\n_contextvars.ContextVar.reset\n    token: object\n    /\n\nReset the context variable.\n\nThe variable is reset to the value it had before the `ContextVar.set()` that\ncreated the token was used.\n[clinic start generated code]*/\n\nstatic PyObject *\n_contextvars_ContextVar_reset(PyContextVar *self, PyObject *token)\n/*[clinic end generated code: output=d4ee34d0742d62ee input=ebe2881e5af4ffda]*/\n{\n    if (!PyContextToken_CheckExact(token)) {\n        PyErr_Format(PyExc_TypeError,\n                     \"expected an instance of Token, got %R\", token);\n        return NULL;\n    }\n\n    if (PyContextVar_Reset((PyObject *)self, token)) {\n        return NULL;\n    }\n\n    Py_RETURN_NONE;\n}\n\n\nstatic PyMemberDef PyContextVar_members[] = {\n    {\"name\", T_OBJECT, offsetof(PyContextVar, var_name), READONLY},\n    {NULL}\n};\n\nstatic PyMethodDef PyContextVar_methods[] = {\n    _CONTEXTVARS_CONTEXTVAR_GET_METHODDEF\n    _CONTEXTVARS_CONTEXTVAR_SET_METHODDEF\n    _CONTEXTVARS_CONTEXTVAR_RESET_METHODDEF\n    {\"__class_getitem__\", Py_GenericAlias,\n    METH_O|METH_CLASS,       PyDoc_STR(\"See PEP 585\")},\n    {NULL, NULL}\n};\n\nPyTypeObject PyContextVar_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"_contextvars.ContextVar\",\n    sizeof(PyContextVar),\n    .tp_methods = PyContextVar_methods,\n    .tp_members = PyContextVar_members,\n    .tp_dealloc = (destructor)contextvar_tp_dealloc,\n    .tp_getattro = PyObject_GenericGetAttr,\n    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,\n    .tp_traverse = (traverseproc)contextvar_tp_traverse,\n    .tp_clear = (inquiry)contextvar_tp_clear,\n    .tp_new = contextvar_tp_new,\n    .tp_free = PyObject_GC_Del,\n    .tp_hash = (hashfunc)contextvar_tp_hash,\n    .tp_repr = (reprfunc)contextvar_tp_repr,\n};\n\n\n/////////////////////////// Token\n\nstatic PyObject * get_token_missing(void);\n\n\n/*[clinic input]\nclass _contextvars.Token \"PyContextToken *\" \"&PyContextToken_Type\"\n[clinic start generated code]*/\n/*[clinic end generated code: output=da39a3ee5e6b4b0d input=338a5e2db13d3f5b]*/\n\n\nstatic PyObject *\ntoken_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n{\n    PyErr_SetString(PyExc_RuntimeError,\n                    \"Tokens can only be created by ContextVars\");\n    return NULL;\n}\n\nstatic int\ntoken_tp_clear(PyContextToken *self)\n{\n    Py_CLEAR(self->tok_ctx);\n    Py_CLEAR(self->tok_var);\n    Py_CLEAR(self->tok_oldval);\n    return 0;\n}\n\nstatic int\ntoken_tp_traverse(PyContextToken *self, visitproc visit, void *arg)\n{\n    Py_VISIT(self->tok_ctx);\n    Py_VISIT(self->tok_var);\n    Py_VISIT(self->tok_oldval);\n    return 0;\n}\n\nstatic void\ntoken_tp_dealloc(PyContextToken *self)\n{\n    PyObject_GC_UnTrack(self);\n    (void)token_tp_clear(self);\n    Py_TYPE(self)->tp_free(self);\n}\n\nstatic PyObject *\ntoken_tp_repr(PyContextToken *self)\n{\n    _PyUnicodeWriter writer;\n\n    _PyUnicodeWriter_Init(&writer);\n\n    if (_PyUnicodeWriter_WriteASCIIString(&writer, \"<Token\", 6) < 0) {\n        goto error;\n    }\n\n    if (self->tok_used) {\n        if (_PyUnicodeWriter_WriteASCIIString(&writer, \" used\", 5) < 0) {\n            goto error;\n        }\n    }\n\n    if (_PyUnicodeWriter_WriteASCIIString(&writer, \" var=\", 5) < 0) {\n        goto error;\n    }\n\n    PyObject *var = PyObject_Repr((PyObject *)self->tok_var);\n    if (var == NULL) {\n        goto error;\n    }\n    if (_PyUnicodeWriter_WriteStr(&writer, var) < 0) {\n        Py_DECREF(var);\n        goto error;\n    }\n    Py_DECREF(var);\n\n    PyObject *addr = PyUnicode_FromFormat(\" at %p>\", self);\n    if (addr == NULL) {\n        goto error;\n    }\n    if (_PyUnicodeWriter_WriteStr(&writer, addr) < 0) {\n        Py_DECREF(addr);\n        goto error;\n    }\n    Py_DECREF(addr);\n\n    return _PyUnicodeWriter_Finish(&writer);\n\nerror:\n    _PyUnicodeWriter_Dealloc(&writer);\n    return NULL;\n}\n\nstatic PyObject *\ntoken_get_var(PyContextToken *self, void *Py_UNUSED(ignored))\n{\n    return Py_NewRef(self->tok_var);;\n}\n\nstatic PyObject *\ntoken_get_old_value(PyContextToken *self, void *Py_UNUSED(ignored))\n{\n    if (self->tok_oldval == NULL) {\n        return get_token_missing();\n    }\n\n    return Py_NewRef(self->tok_oldval);\n}\n\nstatic PyGetSetDef PyContextTokenType_getsetlist[] = {\n    {\"var\", (getter)token_get_var, NULL, NULL},\n    {\"old_value\", (getter)token_get_old_value, NULL, NULL},\n    {NULL}\n};\n\nstatic PyMethodDef PyContextTokenType_methods[] = {\n    {\"__class_getitem__\",    Py_GenericAlias,\n    METH_O|METH_CLASS,       PyDoc_STR(\"See PEP 585\")},\n    {NULL}\n};\n\nPyTypeObject PyContextToken_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"_contextvars.Token\",\n    sizeof(PyContextToken),\n    .tp_methods = PyContextTokenType_methods,\n    .tp_getset = PyContextTokenType_getsetlist,\n    .tp_dealloc = (destructor)token_tp_dealloc,\n    .tp_getattro = PyObject_GenericGetAttr,\n    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,\n    .tp_traverse = (traverseproc)token_tp_traverse,\n    .tp_clear = (inquiry)token_tp_clear,\n    .tp_new = token_tp_new,\n    .tp_free = PyObject_GC_Del,\n    .tp_hash = PyObject_HashNotImplemented,\n    .tp_repr = (reprfunc)token_tp_repr,\n};\n\nstatic PyContextToken *\ntoken_new(PyContext *ctx, PyContextVar *var, PyObject *val)\n{\n    PyContextToken *tok = PyObject_GC_New(PyContextToken, &PyContextToken_Type);\n    if (tok == NULL) {\n        return NULL;\n    }\n\n    tok->tok_ctx = (PyContext*)Py_NewRef(ctx);\n\n    tok->tok_var = (PyContextVar*)Py_NewRef(var);\n\n    tok->tok_oldval = Py_XNewRef(val);\n\n    tok->tok_used = 0;\n\n    PyObject_GC_Track(tok);\n    return tok;\n}\n\n\n/////////////////////////// Token.MISSING\n\n\nstatic PyObject *\ncontext_token_missing_tp_repr(PyObject *self)\n{\n    return PyUnicode_FromString(\"<Token.MISSING>\");\n}\n\nstatic void\ncontext_token_missing_tp_dealloc(_PyContextTokenMissing *Py_UNUSED(self))\n{\n#ifdef Py_DEBUG\n    /* The singleton is statically allocated. */\n    _Py_FatalRefcountError(\"deallocating the token missing singleton\");\n#else\n    return;\n#endif\n}\n\n\nPyTypeObject _PyContextTokenMissing_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"Token.MISSING\",\n    sizeof(_PyContextTokenMissing),\n    .tp_dealloc = (destructor)context_token_missing_tp_dealloc,\n    .tp_getattro = PyObject_GenericGetAttr,\n    .tp_flags = Py_TPFLAGS_DEFAULT,\n    .tp_repr = context_token_missing_tp_repr,\n};\n\n\nstatic PyObject *\nget_token_missing(void)\n{\n    return Py_NewRef(&_Py_SINGLETON(context_token_missing));\n}\n\n\n///////////////////////////\n\n\nvoid\n_PyContext_ClearFreeList(PyInterpreterState *interp)\n{\n#if PyContext_MAXFREELIST > 0\n    struct _Py_context_state *state = &interp->context;\n    for (; state->numfree; state->numfree--) {\n        PyContext *ctx = state->freelist;\n        state->freelist = (PyContext *)ctx->ctx_weakreflist;\n        ctx->ctx_weakreflist = NULL;\n        PyObject_GC_Del(ctx);\n    }\n#endif\n}\n\n\nvoid\n_PyContext_Fini(PyInterpreterState *interp)\n{\n    _PyContext_ClearFreeList(interp);\n#if defined(Py_DEBUG) && PyContext_MAXFREELIST > 0\n    struct _Py_context_state *state = &interp->context;\n    state->numfree = -1;\n#endif\n}\n\n\nPyStatus\n_PyContext_Init(PyInterpreterState *interp)\n{\n    if (!_Py_IsMainInterpreter(interp)) {\n        return _PyStatus_OK();\n    }\n\n    PyObject *missing = get_token_missing();\n    if (PyDict_SetItemString(\n        _PyType_GetDict(&PyContextToken_Type), \"MISSING\", missing))\n    {\n        Py_DECREF(missing);\n        return _PyStatus_ERR(\"can't init context types\");\n    }\n    Py_DECREF(missing);\n\n    return _PyStatus_OK();\n}\n"
  },
  {
    "path": "Dtoa.c",
    "content": "/****************************************************************\n * This is dtoa.c by David M. Gay, downloaded from\n * http://www.netlib.org/fp/dtoa.c on April 15, 2009 and modified for\n * inclusion into the Python core by Mark E. T. Dickinson and Eric V. Smith.\n *\n * Please remember to check http://www.netlib.org/fp regularly (and especially\n * before any Python release) for bugfixes and updates.\n *\n * The major modifications from Gay's original code are as follows:\n *\n *  0. The original code has been specialized to Python's needs by removing\n *     many of the #ifdef'd sections.  In particular, code to support VAX and\n *     IBM floating-point formats, hex NaNs, hex floats, locale-aware\n *     treatment of the decimal point, and setting of the inexact flag have\n *     been removed.\n *\n *  1. We use PyMem_Malloc and PyMem_Free in place of malloc and free.\n *\n *  2. The public functions strtod, dtoa and freedtoa all now have\n *     a _Py_dg_ prefix.\n *\n *  3. Instead of assuming that PyMem_Malloc always succeeds, we thread\n *     PyMem_Malloc failures through the code.  The functions\n *\n *       Balloc, multadd, s2b, i2b, mult, pow5mult, lshift, diff, d2b\n *\n *     of return type *Bigint all return NULL to indicate a malloc failure.\n *     Similarly, rv_alloc and nrv_alloc (return type char *) return NULL on\n *     failure.  bigcomp now has return type int (it used to be void) and\n *     returns -1 on failure and 0 otherwise.  _Py_dg_dtoa returns NULL\n *     on failure.  _Py_dg_strtod indicates failure due to malloc failure\n *     by returning -1.0, setting errno=ENOMEM and *se to s00.\n *\n *  4. The static variable dtoa_result has been removed.  Callers of\n *     _Py_dg_dtoa are expected to call _Py_dg_freedtoa to free\n *     the memory allocated by _Py_dg_dtoa.\n *\n *  5. The code has been reformatted to better fit with Python's\n *     C style guide (PEP 7).\n *\n *  6. A bug in the memory allocation has been fixed: to avoid FREEing memory\n *     that hasn't been MALLOC'ed, private_mem should only be used when k <=\n *     Kmax.\n *\n *  7. _Py_dg_strtod has been modified so that it doesn't accept strings with\n *     leading whitespace.\n *\n *  8. A corner case where _Py_dg_dtoa didn't strip trailing zeros has been\n *     fixed. (bugs.python.org/issue40780)\n *\n ***************************************************************/\n\n/* Please send bug reports for the original dtoa.c code to David M. Gay (dmg\n * at acm dot org, with \" at \" changed at \"@\" and \" dot \" changed to \".\").\n * Please report bugs for this modified version using the Python issue tracker\n * (http://bugs.python.org). */\n\n/* On a machine with IEEE extended-precision registers, it is\n * necessary to specify double-precision (53-bit) rounding precision\n * before invoking strtod or dtoa.  If the machine uses (the equivalent\n * of) Intel 80x87 arithmetic, the call\n *      _control87(PC_53, MCW_PC);\n * does this with many compilers.  Whether this or another call is\n * appropriate depends on the compiler; for this to work, it may be\n * necessary to #include \"float.h\" or another system-dependent header\n * file.\n */\n\n/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.\n *\n * This strtod returns a nearest machine number to the input decimal\n * string (or sets errno to ERANGE).  With IEEE arithmetic, ties are\n * broken by the IEEE round-even rule.  Otherwise ties are broken by\n * biased rounding (add half and chop).\n *\n * Inspired loosely by William D. Clinger's paper \"How to Read Floating\n * Point Numbers Accurately\" [Proc. ACM SIGPLAN '90, pp. 92-101].\n *\n * Modifications:\n *\n *      1. We only require IEEE, IBM, or VAX double-precision\n *              arithmetic (not IEEE double-extended).\n *      2. We get by with floating-point arithmetic in a case that\n *              Clinger missed -- when we're computing d * 10^n\n *              for a small integer d and the integer n is not too\n *              much larger than 22 (the maximum integer k for which\n *              we can represent 10^k exactly), we may be able to\n *              compute (d*10^k) * 10^(e-k) with just one roundoff.\n *      3. Rather than a bit-at-a-time adjustment of the binary\n *              result in the hard case, we use floating-point\n *              arithmetic to determine the adjustment to within\n *              one bit; only in really hard cases do we need to\n *              compute a second residual.\n *      4. Because of 3., we don't need a large table of powers of 10\n *              for ten-to-e (just some small tables, e.g. of 10^k\n *              for 0 <= k <= 22).\n */\n\n/* Linking of Python's #defines to Gay's #defines starts here. */\n\n#include \"Python.h\"\n#include \"pycore_dtoa.h\"          // _PY_SHORT_FLOAT_REPR\n#include \"pycore_pystate.h\"       // _PyInterpreterState_GET()\n#include <stdlib.h>               // exit()\n\n/* if _PY_SHORT_FLOAT_REPR == 0, then don't even try to compile\n   the following code */\n#if _PY_SHORT_FLOAT_REPR == 1\n\n#include \"float.h\"\n\n#define MALLOC PyMem_Malloc\n#define FREE PyMem_Free\n\n/* This code should also work for ARM mixed-endian format on little-endian\n   machines, where doubles have byte order 45670123 (in increasing address\n   order, 0 being the least significant byte). */\n#ifdef DOUBLE_IS_LITTLE_ENDIAN_IEEE754\n#  define IEEE_8087\n#endif\n#if defined(DOUBLE_IS_BIG_ENDIAN_IEEE754) ||  \\\n  defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754)\n#  define IEEE_MC68k\n#endif\n#if defined(IEEE_8087) + defined(IEEE_MC68k) != 1\n#error \"Exactly one of IEEE_8087 or IEEE_MC68k should be defined.\"\n#endif\n\n/* The code below assumes that the endianness of integers matches the\n   endianness of the two 32-bit words of a double.  Check this. */\n#if defined(WORDS_BIGENDIAN) && (defined(DOUBLE_IS_LITTLE_ENDIAN_IEEE754) || \\\n                                 defined(DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754))\n#error \"doubles and ints have incompatible endianness\"\n#endif\n\n#if !defined(WORDS_BIGENDIAN) && defined(DOUBLE_IS_BIG_ENDIAN_IEEE754)\n#error \"doubles and ints have incompatible endianness\"\n#endif\n\n\n// ULong is defined in pycore_dtoa.h.\ntypedef int32_t Long;\ntypedef uint64_t ULLong;\n\n#undef DEBUG\n#ifdef Py_DEBUG\n#define DEBUG\n#endif\n\n/* End Python #define linking */\n\n#ifdef DEBUG\n#define Bug(x) {fprintf(stderr, \"%s\\n\", x); exit(1);}\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\ntypedef union { double d; ULong L[2]; } U;\n\n#ifdef IEEE_8087\n#define word0(x) (x)->L[1]\n#define word1(x) (x)->L[0]\n#else\n#define word0(x) (x)->L[0]\n#define word1(x) (x)->L[1]\n#endif\n#define dval(x) (x)->d\n\n#ifndef STRTOD_DIGLIM\n#define STRTOD_DIGLIM 40\n#endif\n\n/* maximum permitted exponent value for strtod; exponents larger than\n   MAX_ABS_EXP in absolute value get truncated to +-MAX_ABS_EXP.  MAX_ABS_EXP\n   should fit into an int. */\n#ifndef MAX_ABS_EXP\n#define MAX_ABS_EXP 1100000000U\n#endif\n/* Bound on length of pieces of input strings in _Py_dg_strtod; specifically,\n   this is used to bound the total number of digits ignoring leading zeros and\n   the number of digits that follow the decimal point.  Ideally, MAX_DIGITS\n   should satisfy MAX_DIGITS + 400 < MAX_ABS_EXP; that ensures that the\n   exponent clipping in _Py_dg_strtod can't affect the value of the output. */\n#ifndef MAX_DIGITS\n#define MAX_DIGITS 1000000000U\n#endif\n\n/* Guard against trying to use the above values on unusual platforms with ints\n * of width less than 32 bits. */\n#if MAX_ABS_EXP > INT_MAX\n#error \"MAX_ABS_EXP should fit in an int\"\n#endif\n#if MAX_DIGITS > INT_MAX\n#error \"MAX_DIGITS should fit in an int\"\n#endif\n\n/* The following definition of Storeinc is appropriate for MIPS processors.\n * An alternative that might be better on some machines is\n * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)\n */\n#if defined(IEEE_8087)\n#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b,  \\\n                         ((unsigned short *)a)[0] = (unsigned short)c, a++)\n#else\n#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b,  \\\n                         ((unsigned short *)a)[1] = (unsigned short)c, a++)\n#endif\n\n/* #define P DBL_MANT_DIG */\n/* Ten_pmax = floor(P*log(2)/log(5)) */\n/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */\n/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */\n/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */\n\n#define Exp_shift  20\n#define Exp_shift1 20\n#define Exp_msk1    0x100000\n#define Exp_msk11   0x100000\n#define Exp_mask  0x7ff00000\n#define P 53\n#define Nbits 53\n#define Bias 1023\n#define Emax 1023\n#define Emin (-1022)\n#define Etiny (-1074)  /* smallest denormal is 2**Etiny */\n#define Exp_1  0x3ff00000\n#define Exp_11 0x3ff00000\n#define Ebits 11\n#define Frac_mask  0xfffff\n#define Frac_mask1 0xfffff\n#define Ten_pmax 22\n#define Bletch 0x10\n#define Bndry_mask  0xfffff\n#define Bndry_mask1 0xfffff\n#define Sign_bit 0x80000000\n#define Log2P 1\n#define Tiny0 0\n#define Tiny1 1\n#define Quick_max 14\n#define Int_max 14\n\n#ifndef Flt_Rounds\n#ifdef FLT_ROUNDS\n#define Flt_Rounds FLT_ROUNDS\n#else\n#define Flt_Rounds 1\n#endif\n#endif /*Flt_Rounds*/\n\n#define Rounding Flt_Rounds\n\n#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))\n#define Big1 0xffffffff\n\n/* Bits of the representation of positive infinity. */\n\n#define POSINF_WORD0 0x7ff00000\n#define POSINF_WORD1 0\n\n/* struct BCinfo is used to pass information from _Py_dg_strtod to bigcomp */\n\ntypedef struct BCinfo BCinfo;\nstruct\nBCinfo {\n    int e0, nd, nd0, scale;\n};\n\n#define FFFFFFFF 0xffffffffUL\n\n/* struct Bigint is used to represent arbitrary-precision integers.  These\n   integers are stored in sign-magnitude format, with the magnitude stored as\n   an array of base 2**32 digits.  Bigints are always normalized: if x is a\n   Bigint then x->wds >= 1, and either x->wds == 1 or x[wds-1] is nonzero.\n\n   The Bigint fields are as follows:\n\n     - next is a header used by Balloc and Bfree to keep track of lists\n         of freed Bigints;  it's also used for the linked list of\n         powers of 5 of the form 5**2**i used by pow5mult.\n     - k indicates which pool this Bigint was allocated from\n     - maxwds is the maximum number of words space was allocated for\n       (usually maxwds == 2**k)\n     - sign is 1 for negative Bigints, 0 for positive.  The sign is unused\n       (ignored on inputs, set to 0 on outputs) in almost all operations\n       involving Bigints: a notable exception is the diff function, which\n       ignores signs on inputs but sets the sign of the output correctly.\n     - wds is the actual number of significant words\n     - x contains the vector of words (digits) for this Bigint, from least\n       significant (x[0]) to most significant (x[wds-1]).\n*/\n\n// struct Bigint is defined in pycore_dtoa.h.\ntypedef struct Bigint Bigint;\n\n#ifndef Py_USING_MEMORY_DEBUGGER\n\n/* Memory management: memory is allocated from, and returned to, Kmax+1 pools\n   of memory, where pool k (0 <= k <= Kmax) is for Bigints b with b->maxwds ==\n   1 << k.  These pools are maintained as linked lists, with freelist[k]\n   pointing to the head of the list for pool k.\n\n   On allocation, if there's no free slot in the appropriate pool, MALLOC is\n   called to get more memory.  This memory is not returned to the system until\n   Python quits.  There's also a private memory pool that's allocated from\n   in preference to using MALLOC.\n\n   For Bigints with more than (1 << Kmax) digits (which implies at least 1233\n   decimal digits), memory is directly allocated using MALLOC, and freed using\n   FREE.\n\n   XXX: it would be easy to bypass this memory-management system and\n   translate each call to Balloc into a call to PyMem_Malloc, and each\n   Bfree to PyMem_Free.  Investigate whether this has any significant\n   performance on impact. */\n\n#define freelist interp->dtoa.freelist\n#define private_mem interp->dtoa.preallocated\n#define pmem_next interp->dtoa.preallocated_next\n\n/* Allocate space for a Bigint with up to 1<<k digits */\n\nstatic Bigint *\nBalloc(int k)\n{\n    int x;\n    Bigint *rv;\n    unsigned int len;\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n\n    if (k <= Bigint_Kmax && (rv = freelist[k]))\n        freelist[k] = rv->next;\n    else {\n        x = 1 << k;\n        len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)\n            /sizeof(double);\n        if (k <= Bigint_Kmax &&\n            pmem_next - private_mem + len <= (Py_ssize_t)Bigint_PREALLOC_SIZE\n        ) {\n            rv = (Bigint*)pmem_next;\n            pmem_next += len;\n        }\n        else {\n            rv = (Bigint*)MALLOC(len*sizeof(double));\n            if (rv == NULL)\n                return NULL;\n        }\n        rv->k = k;\n        rv->maxwds = x;\n    }\n    rv->sign = rv->wds = 0;\n    return rv;\n}\n\n/* Free a Bigint allocated with Balloc */\n\nstatic void\nBfree(Bigint *v)\n{\n    if (v) {\n        if (v->k > Bigint_Kmax)\n            FREE((void*)v);\n        else {\n            PyInterpreterState *interp = _PyInterpreterState_GET();\n            v->next = freelist[v->k];\n            freelist[v->k] = v;\n        }\n    }\n}\n\n#undef pmem_next\n#undef private_mem\n#undef freelist\n\n#else\n\n/* Alternative versions of Balloc and Bfree that use PyMem_Malloc and\n   PyMem_Free directly in place of the custom memory allocation scheme above.\n   These are provided for the benefit of memory debugging tools like\n   Valgrind. */\n\n/* Allocate space for a Bigint with up to 1<<k digits */\n\nstatic Bigint *\nBalloc(int k)\n{\n    int x;\n    Bigint *rv;\n    unsigned int len;\n\n    x = 1 << k;\n    len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)\n        /sizeof(double);\n\n    rv = (Bigint*)MALLOC(len*sizeof(double));\n    if (rv == NULL)\n        return NULL;\n\n    rv->k = k;\n    rv->maxwds = x;\n    rv->sign = rv->wds = 0;\n    return rv;\n}\n\n/* Free a Bigint allocated with Balloc */\n\nstatic void\nBfree(Bigint *v)\n{\n    if (v) {\n        FREE((void*)v);\n    }\n}\n\n#endif /* Py_USING_MEMORY_DEBUGGER */\n\n#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign,   \\\n                          y->wds*sizeof(Long) + 2*sizeof(int))\n\n/* Multiply a Bigint b by m and add a.  Either modifies b in place and returns\n   a pointer to the modified b, or Bfrees b and returns a pointer to a copy.\n   On failure, return NULL.  In this case, b will have been already freed. */\n\nstatic Bigint *\nmultadd(Bigint *b, int m, int a)       /* multiply by m and add a */\n{\n    int i, wds;\n    ULong *x;\n    ULLong carry, y;\n    Bigint *b1;\n\n    wds = b->wds;\n    x = b->x;\n    i = 0;\n    carry = a;\n    do {\n        y = *x * (ULLong)m + carry;\n        carry = y >> 32;\n        *x++ = (ULong)(y & FFFFFFFF);\n    }\n    while(++i < wds);\n    if (carry) {\n        if (wds >= b->maxwds) {\n            b1 = Balloc(b->k+1);\n            if (b1 == NULL){\n                Bfree(b);\n                return NULL;\n            }\n            Bcopy(b1, b);\n            Bfree(b);\n            b = b1;\n        }\n        b->x[wds++] = (ULong)carry;\n        b->wds = wds;\n    }\n    return b;\n}\n\n/* convert a string s containing nd decimal digits (possibly containing a\n   decimal separator at position nd0, which is ignored) to a Bigint.  This\n   function carries on where the parsing code in _Py_dg_strtod leaves off: on\n   entry, y9 contains the result of converting the first 9 digits.  Returns\n   NULL on failure. */\n\nstatic Bigint *\ns2b(const char *s, int nd0, int nd, ULong y9)\n{\n    Bigint *b;\n    int i, k;\n    Long x, y;\n\n    x = (nd + 8) / 9;\n    for(k = 0, y = 1; x > y; y <<= 1, k++) ;\n    b = Balloc(k);\n    if (b == NULL)\n        return NULL;\n    b->x[0] = y9;\n    b->wds = 1;\n\n    if (nd <= 9)\n      return b;\n\n    s += 9;\n    for (i = 9; i < nd0; i++) {\n        b = multadd(b, 10, *s++ - '0');\n        if (b == NULL)\n            return NULL;\n    }\n    s++;\n    for(; i < nd; i++) {\n        b = multadd(b, 10, *s++ - '0');\n        if (b == NULL)\n            return NULL;\n    }\n    return b;\n}\n\n/* count leading 0 bits in the 32-bit integer x. */\n\nstatic int\nhi0bits(ULong x)\n{\n    int k = 0;\n\n    if (!(x & 0xffff0000)) {\n        k = 16;\n        x <<= 16;\n    }\n    if (!(x & 0xff000000)) {\n        k += 8;\n        x <<= 8;\n    }\n    if (!(x & 0xf0000000)) {\n        k += 4;\n        x <<= 4;\n    }\n    if (!(x & 0xc0000000)) {\n        k += 2;\n        x <<= 2;\n    }\n    if (!(x & 0x80000000)) {\n        k++;\n        if (!(x & 0x40000000))\n            return 32;\n    }\n    return k;\n}\n\n/* count trailing 0 bits in the 32-bit integer y, and shift y right by that\n   number of bits. */\n\nstatic int\nlo0bits(ULong *y)\n{\n    int k;\n    ULong x = *y;\n\n    if (x & 7) {\n        if (x & 1)\n            return 0;\n        if (x & 2) {\n            *y = x >> 1;\n            return 1;\n        }\n        *y = x >> 2;\n        return 2;\n    }\n    k = 0;\n    if (!(x & 0xffff)) {\n        k = 16;\n        x >>= 16;\n    }\n    if (!(x & 0xff)) {\n        k += 8;\n        x >>= 8;\n    }\n    if (!(x & 0xf)) {\n        k += 4;\n        x >>= 4;\n    }\n    if (!(x & 0x3)) {\n        k += 2;\n        x >>= 2;\n    }\n    if (!(x & 1)) {\n        k++;\n        x >>= 1;\n        if (!x)\n            return 32;\n    }\n    *y = x;\n    return k;\n}\n\n/* convert a small nonnegative integer to a Bigint */\n\nstatic Bigint *\ni2b(int i)\n{\n    Bigint *b;\n\n    b = Balloc(1);\n    if (b == NULL)\n        return NULL;\n    b->x[0] = i;\n    b->wds = 1;\n    return b;\n}\n\n/* multiply two Bigints.  Returns a new Bigint, or NULL on failure.  Ignores\n   the signs of a and b. */\n\nstatic Bigint *\nmult(Bigint *a, Bigint *b)\n{\n    Bigint *c;\n    int k, wa, wb, wc;\n    ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;\n    ULong y;\n    ULLong carry, z;\n\n    if ((!a->x[0] && a->wds == 1) || (!b->x[0] && b->wds == 1)) {\n        c = Balloc(0);\n        if (c == NULL)\n            return NULL;\n        c->wds = 1;\n        c->x[0] = 0;\n        return c;\n    }\n\n    if (a->wds < b->wds) {\n        c = a;\n        a = b;\n        b = c;\n    }\n    k = a->k;\n    wa = a->wds;\n    wb = b->wds;\n    wc = wa + wb;\n    if (wc > a->maxwds)\n        k++;\n    c = Balloc(k);\n    if (c == NULL)\n        return NULL;\n    for(x = c->x, xa = x + wc; x < xa; x++)\n        *x = 0;\n    xa = a->x;\n    xae = xa + wa;\n    xb = b->x;\n    xbe = xb + wb;\n    xc0 = c->x;\n    for(; xb < xbe; xc0++) {\n        if ((y = *xb++)) {\n            x = xa;\n            xc = xc0;\n            carry = 0;\n            do {\n                z = *x++ * (ULLong)y + *xc + carry;\n                carry = z >> 32;\n                *xc++ = (ULong)(z & FFFFFFFF);\n            }\n            while(x < xae);\n            *xc = (ULong)carry;\n        }\n    }\n    for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;\n    c->wds = wc;\n    return c;\n}\n\n#ifndef Py_USING_MEMORY_DEBUGGER\n\n/* multiply the Bigint b by 5**k.  Returns a pointer to the result, or NULL on\n   failure; if the returned pointer is distinct from b then the original\n   Bigint b will have been Bfree'd.   Ignores the sign of b. */\n\nstatic Bigint *\npow5mult(Bigint *b, int k)\n{\n    Bigint *b1, *p5, *p51;\n    int i;\n    static const int p05[3] = { 5, 25, 125 };\n\n    if ((i = k & 3)) {\n        b = multadd(b, p05[i-1], 0);\n        if (b == NULL)\n            return NULL;\n    }\n\n    if (!(k >>= 2))\n        return b;\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    p5 = interp->dtoa.p5s;\n    if (!p5) {\n        /* first time */\n        p5 = i2b(625);\n        if (p5 == NULL) {\n            Bfree(b);\n            return NULL;\n        }\n        interp->dtoa.p5s = p5;\n        p5->next = 0;\n    }\n    for(;;) {\n        if (k & 1) {\n            b1 = mult(b, p5);\n            Bfree(b);\n            b = b1;\n            if (b == NULL)\n                return NULL;\n        }\n        if (!(k >>= 1))\n            break;\n        p51 = p5->next;\n        if (!p51) {\n            p51 = mult(p5,p5);\n            if (p51 == NULL) {\n                Bfree(b);\n                return NULL;\n            }\n            p51->next = 0;\n            p5->next = p51;\n        }\n        p5 = p51;\n    }\n    return b;\n}\n\n#else\n\n/* Version of pow5mult that doesn't cache powers of 5. Provided for\n   the benefit of memory debugging tools like Valgrind. */\n\nstatic Bigint *\npow5mult(Bigint *b, int k)\n{\n    Bigint *b1, *p5, *p51;\n    int i;\n    static const int p05[3] = { 5, 25, 125 };\n\n    if ((i = k & 3)) {\n        b = multadd(b, p05[i-1], 0);\n        if (b == NULL)\n            return NULL;\n    }\n\n    if (!(k >>= 2))\n        return b;\n    p5 = i2b(625);\n    if (p5 == NULL) {\n        Bfree(b);\n        return NULL;\n    }\n\n    for(;;) {\n        if (k & 1) {\n            b1 = mult(b, p5);\n            Bfree(b);\n            b = b1;\n            if (b == NULL) {\n                Bfree(p5);\n                return NULL;\n            }\n        }\n        if (!(k >>= 1))\n            break;\n        p51 = mult(p5, p5);\n        Bfree(p5);\n        p5 = p51;\n        if (p5 == NULL) {\n            Bfree(b);\n            return NULL;\n        }\n    }\n    Bfree(p5);\n    return b;\n}\n\n#endif /* Py_USING_MEMORY_DEBUGGER */\n\n/* shift a Bigint b left by k bits.  Return a pointer to the shifted result,\n   or NULL on failure.  If the returned pointer is distinct from b then the\n   original b will have been Bfree'd.   Ignores the sign of b. */\n\nstatic Bigint *\nlshift(Bigint *b, int k)\n{\n    int i, k1, n, n1;\n    Bigint *b1;\n    ULong *x, *x1, *xe, z;\n\n    if (!k || (!b->x[0] && b->wds == 1))\n        return b;\n\n    n = k >> 5;\n    k1 = b->k;\n    n1 = n + b->wds + 1;\n    for(i = b->maxwds; n1 > i; i <<= 1)\n        k1++;\n    b1 = Balloc(k1);\n    if (b1 == NULL) {\n        Bfree(b);\n        return NULL;\n    }\n    x1 = b1->x;\n    for(i = 0; i < n; i++)\n        *x1++ = 0;\n    x = b->x;\n    xe = x + b->wds;\n    if (k &= 0x1f) {\n        k1 = 32 - k;\n        z = 0;\n        do {\n            *x1++ = *x << k | z;\n            z = *x++ >> k1;\n        }\n        while(x < xe);\n        if ((*x1 = z))\n            ++n1;\n    }\n    else do\n             *x1++ = *x++;\n        while(x < xe);\n    b1->wds = n1 - 1;\n    Bfree(b);\n    return b1;\n}\n\n/* Do a three-way compare of a and b, returning -1 if a < b, 0 if a == b and\n   1 if a > b.  Ignores signs of a and b. */\n\nstatic int\ncmp(Bigint *a, Bigint *b)\n{\n    ULong *xa, *xa0, *xb, *xb0;\n    int i, j;\n\n    i = a->wds;\n    j = b->wds;\n#ifdef DEBUG\n    if (i > 1 && !a->x[i-1])\n        Bug(\"cmp called with a->x[a->wds-1] == 0\");\n    if (j > 1 && !b->x[j-1])\n        Bug(\"cmp called with b->x[b->wds-1] == 0\");\n#endif\n    if (i -= j)\n        return i;\n    xa0 = a->x;\n    xa = xa0 + j;\n    xb0 = b->x;\n    xb = xb0 + j;\n    for(;;) {\n        if (*--xa != *--xb)\n            return *xa < *xb ? -1 : 1;\n        if (xa <= xa0)\n            break;\n    }\n    return 0;\n}\n\n/* Take the difference of Bigints a and b, returning a new Bigint.  Returns\n   NULL on failure.  The signs of a and b are ignored, but the sign of the\n   result is set appropriately. */\n\nstatic Bigint *\ndiff(Bigint *a, Bigint *b)\n{\n    Bigint *c;\n    int i, wa, wb;\n    ULong *xa, *xae, *xb, *xbe, *xc;\n    ULLong borrow, y;\n\n    i = cmp(a,b);\n    if (!i) {\n        c = Balloc(0);\n        if (c == NULL)\n            return NULL;\n        c->wds = 1;\n        c->x[0] = 0;\n        return c;\n    }\n    if (i < 0) {\n        c = a;\n        a = b;\n        b = c;\n        i = 1;\n    }\n    else\n        i = 0;\n    c = Balloc(a->k);\n    if (c == NULL)\n        return NULL;\n    c->sign = i;\n    wa = a->wds;\n    xa = a->x;\n    xae = xa + wa;\n    wb = b->wds;\n    xb = b->x;\n    xbe = xb + wb;\n    xc = c->x;\n    borrow = 0;\n    do {\n        y = (ULLong)*xa++ - *xb++ - borrow;\n        borrow = y >> 32 & (ULong)1;\n        *xc++ = (ULong)(y & FFFFFFFF);\n    }\n    while(xb < xbe);\n    while(xa < xae) {\n        y = *xa++ - borrow;\n        borrow = y >> 32 & (ULong)1;\n        *xc++ = (ULong)(y & FFFFFFFF);\n    }\n    while(!*--xc)\n        wa--;\n    c->wds = wa;\n    return c;\n}\n\n/* Given a positive normal double x, return the difference between x and the\n   next double up.  Doesn't give correct results for subnormals. */\n\nstatic double\nulp(U *x)\n{\n    Long L;\n    U u;\n\n    L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;\n    word0(&u) = L;\n    word1(&u) = 0;\n    return dval(&u);\n}\n\n/* Convert a Bigint to a double plus an exponent */\n\nstatic double\nb2d(Bigint *a, int *e)\n{\n    ULong *xa, *xa0, w, y, z;\n    int k;\n    U d;\n\n    xa0 = a->x;\n    xa = xa0 + a->wds;\n    y = *--xa;\n#ifdef DEBUG\n    if (!y) Bug(\"zero y in b2d\");\n#endif\n    k = hi0bits(y);\n    *e = 32 - k;\n    if (k < Ebits) {\n        word0(&d) = Exp_1 | y >> (Ebits - k);\n        w = xa > xa0 ? *--xa : 0;\n        word1(&d) = y << ((32-Ebits) + k) | w >> (Ebits - k);\n        goto ret_d;\n    }\n    z = xa > xa0 ? *--xa : 0;\n    if (k -= Ebits) {\n        word0(&d) = Exp_1 | y << k | z >> (32 - k);\n        y = xa > xa0 ? *--xa : 0;\n        word1(&d) = z << k | y >> (32 - k);\n    }\n    else {\n        word0(&d) = Exp_1 | y;\n        word1(&d) = z;\n    }\n  ret_d:\n    return dval(&d);\n}\n\n/* Convert a scaled double to a Bigint plus an exponent.  Similar to d2b,\n   except that it accepts the scale parameter used in _Py_dg_strtod (which\n   should be either 0 or 2*P), and the normalization for the return value is\n   different (see below).  On input, d should be finite and nonnegative, and d\n   / 2**scale should be exactly representable as an IEEE 754 double.\n\n   Returns a Bigint b and an integer e such that\n\n     dval(d) / 2**scale = b * 2**e.\n\n   Unlike d2b, b is not necessarily odd: b and e are normalized so\n   that either 2**(P-1) <= b < 2**P and e >= Etiny, or b < 2**P\n   and e == Etiny.  This applies equally to an input of 0.0: in that\n   case the return values are b = 0 and e = Etiny.\n\n   The above normalization ensures that for all possible inputs d,\n   2**e gives ulp(d/2**scale).\n\n   Returns NULL on failure.\n*/\n\nstatic Bigint *\nsd2b(U *d, int scale, int *e)\n{\n    Bigint *b;\n\n    b = Balloc(1);\n    if (b == NULL)\n        return NULL;\n\n    /* First construct b and e assuming that scale == 0. */\n    b->wds = 2;\n    b->x[0] = word1(d);\n    b->x[1] = word0(d) & Frac_mask;\n    *e = Etiny - 1 + (int)((word0(d) & Exp_mask) >> Exp_shift);\n    if (*e < Etiny)\n        *e = Etiny;\n    else\n        b->x[1] |= Exp_msk1;\n\n    /* Now adjust for scale, provided that b != 0. */\n    if (scale && (b->x[0] || b->x[1])) {\n        *e -= scale;\n        if (*e < Etiny) {\n            scale = Etiny - *e;\n            *e = Etiny;\n            /* We can't shift more than P-1 bits without shifting out a 1. */\n            assert(0 < scale && scale <= P - 1);\n            if (scale >= 32) {\n                /* The bits shifted out should all be zero. */\n                assert(b->x[0] == 0);\n                b->x[0] = b->x[1];\n                b->x[1] = 0;\n                scale -= 32;\n            }\n            if (scale) {\n                /* The bits shifted out should all be zero. */\n                assert(b->x[0] << (32 - scale) == 0);\n                b->x[0] = (b->x[0] >> scale) | (b->x[1] << (32 - scale));\n                b->x[1] >>= scale;\n            }\n        }\n    }\n    /* Ensure b is normalized. */\n    if (!b->x[1])\n        b->wds = 1;\n\n    return b;\n}\n\n/* Convert a double to a Bigint plus an exponent.  Return NULL on failure.\n\n   Given a finite nonzero double d, return an odd Bigint b and exponent *e\n   such that fabs(d) = b * 2**e.  On return, *bbits gives the number of\n   significant bits of b; that is, 2**(*bbits-1) <= b < 2**(*bbits).\n\n   If d is zero, then b == 0, *e == -1010, *bbits = 0.\n */\n\nstatic Bigint *\nd2b(U *d, int *e, int *bits)\n{\n    Bigint *b;\n    int de, k;\n    ULong *x, y, z;\n    int i;\n\n    b = Balloc(1);\n    if (b == NULL)\n        return NULL;\n    x = b->x;\n\n    z = word0(d) & Frac_mask;\n    word0(d) &= 0x7fffffff;   /* clear sign bit, which we ignore */\n    if ((de = (int)(word0(d) >> Exp_shift)))\n        z |= Exp_msk1;\n    if ((y = word1(d))) {\n        if ((k = lo0bits(&y))) {\n            x[0] = y | z << (32 - k);\n            z >>= k;\n        }\n        else\n            x[0] = y;\n        i =\n            b->wds = (x[1] = z) ? 2 : 1;\n    }\n    else {\n        k = lo0bits(&z);\n        x[0] = z;\n        i =\n            b->wds = 1;\n        k += 32;\n    }\n    if (de) {\n        *e = de - Bias - (P-1) + k;\n        *bits = P - k;\n    }\n    else {\n        *e = de - Bias - (P-1) + 1 + k;\n        *bits = 32*i - hi0bits(x[i-1]);\n    }\n    return b;\n}\n\n/* Compute the ratio of two Bigints, as a double.  The result may have an\n   error of up to 2.5 ulps. */\n\nstatic double\nratio(Bigint *a, Bigint *b)\n{\n    U da, db;\n    int k, ka, kb;\n\n    dval(&da) = b2d(a, &ka);\n    dval(&db) = b2d(b, &kb);\n    k = ka - kb + 32*(a->wds - b->wds);\n    if (k > 0)\n        word0(&da) += k*Exp_msk1;\n    else {\n        k = -k;\n        word0(&db) += k*Exp_msk1;\n    }\n    return dval(&da) / dval(&db);\n}\n\nstatic const double\ntens[] = {\n    1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,\n    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,\n    1e20, 1e21, 1e22\n};\n\nstatic const double\nbigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };\nstatic const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,\n                                   9007199254740992.*9007199254740992.e-256\n                                   /* = 2^106 * 1e-256 */\n};\n/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */\n/* flag unnecessarily.  It leads to a song and dance at the end of strtod. */\n#define Scale_Bit 0x10\n#define n_bigtens 5\n\n#define ULbits 32\n#define kshift 5\n#define kmask 31\n\n\nstatic int\ndshift(Bigint *b, int p2)\n{\n    int rv = hi0bits(b->x[b->wds-1]) - 4;\n    if (p2 > 0)\n        rv -= p2;\n    return rv & kmask;\n}\n\n/* special case of Bigint division.  The quotient is always in the range 0 <=\n   quotient < 10, and on entry the divisor S is normalized so that its top 4\n   bits (28--31) are zero and bit 27 is set. */\n\nstatic int\nquorem(Bigint *b, Bigint *S)\n{\n    int n;\n    ULong *bx, *bxe, q, *sx, *sxe;\n    ULLong borrow, carry, y, ys;\n\n    n = S->wds;\n#ifdef DEBUG\n    /*debug*/ if (b->wds > n)\n        /*debug*/       Bug(\"oversize b in quorem\");\n#endif\n    if (b->wds < n)\n        return 0;\n    sx = S->x;\n    sxe = sx + --n;\n    bx = b->x;\n    bxe = bx + n;\n    q = *bxe / (*sxe + 1);      /* ensure q <= true quotient */\n#ifdef DEBUG\n    /*debug*/ if (q > 9)\n        /*debug*/       Bug(\"oversized quotient in quorem\");\n#endif\n    if (q) {\n        borrow = 0;\n        carry = 0;\n        do {\n            ys = *sx++ * (ULLong)q + carry;\n            carry = ys >> 32;\n            y = *bx - (ys & FFFFFFFF) - borrow;\n            borrow = y >> 32 & (ULong)1;\n            *bx++ = (ULong)(y & FFFFFFFF);\n        }\n        while(sx <= sxe);\n        if (!*bxe) {\n            bx = b->x;\n            while(--bxe > bx && !*bxe)\n                --n;\n            b->wds = n;\n        }\n    }\n    if (cmp(b, S) >= 0) {\n        q++;\n        borrow = 0;\n        carry = 0;\n        bx = b->x;\n        sx = S->x;\n        do {\n            ys = *sx++ + carry;\n            carry = ys >> 32;\n            y = *bx - (ys & FFFFFFFF) - borrow;\n            borrow = y >> 32 & (ULong)1;\n            *bx++ = (ULong)(y & FFFFFFFF);\n        }\n        while(sx <= sxe);\n        bx = b->x;\n        bxe = bx + n;\n        if (!*bxe) {\n            while(--bxe > bx && !*bxe)\n                --n;\n            b->wds = n;\n        }\n    }\n    return q;\n}\n\n/* sulp(x) is a version of ulp(x) that takes bc.scale into account.\n\n   Assuming that x is finite and nonnegative (positive zero is fine\n   here) and x / 2^bc.scale is exactly representable as a double,\n   sulp(x) is equivalent to 2^bc.scale * ulp(x / 2^bc.scale). */\n\nstatic double\nsulp(U *x, BCinfo *bc)\n{\n    U u;\n\n    if (bc->scale && 2*P + 1 > (int)((word0(x) & Exp_mask) >> Exp_shift)) {\n        /* rv/2^bc->scale is subnormal */\n        word0(&u) = (P+2)*Exp_msk1;\n        word1(&u) = 0;\n        return u.d;\n    }\n    else {\n        assert(word0(x) || word1(x)); /* x != 0.0 */\n        return ulp(x);\n    }\n}\n\n/* The bigcomp function handles some hard cases for strtod, for inputs\n   with more than STRTOD_DIGLIM digits.  It's called once an initial\n   estimate for the double corresponding to the input string has\n   already been obtained by the code in _Py_dg_strtod.\n\n   The bigcomp function is only called after _Py_dg_strtod has found a\n   double value rv such that either rv or rv + 1ulp represents the\n   correctly rounded value corresponding to the original string.  It\n   determines which of these two values is the correct one by\n   computing the decimal digits of rv + 0.5ulp and comparing them with\n   the corresponding digits of s0.\n\n   In the following, write dv for the absolute value of the number represented\n   by the input string.\n\n   Inputs:\n\n     s0 points to the first significant digit of the input string.\n\n     rv is a (possibly scaled) estimate for the closest double value to the\n        value represented by the original input to _Py_dg_strtod.  If\n        bc->scale is nonzero, then rv/2^(bc->scale) is the approximation to\n        the input value.\n\n     bc is a struct containing information gathered during the parsing and\n        estimation steps of _Py_dg_strtod.  Description of fields follows:\n\n        bc->e0 gives the exponent of the input value, such that dv = (integer\n           given by the bd->nd digits of s0) * 10**e0\n\n        bc->nd gives the total number of significant digits of s0.  It will\n           be at least 1.\n\n        bc->nd0 gives the number of significant digits of s0 before the\n           decimal separator.  If there's no decimal separator, bc->nd0 ==\n           bc->nd.\n\n        bc->scale is the value used to scale rv to avoid doing arithmetic with\n           subnormal values.  It's either 0 or 2*P (=106).\n\n   Outputs:\n\n     On successful exit, rv/2^(bc->scale) is the closest double to dv.\n\n     Returns 0 on success, -1 on failure (e.g., due to a failed malloc call). */\n\nstatic int\nbigcomp(U *rv, const char *s0, BCinfo *bc)\n{\n    Bigint *b, *d;\n    int b2, d2, dd, i, nd, nd0, odd, p2, p5;\n\n    nd = bc->nd;\n    nd0 = bc->nd0;\n    p5 = nd + bc->e0;\n    b = sd2b(rv, bc->scale, &p2);\n    if (b == NULL)\n        return -1;\n\n    /* record whether the lsb of rv/2^(bc->scale) is odd:  in the exact halfway\n       case, this is used for round to even. */\n    odd = b->x[0] & 1;\n\n    /* left shift b by 1 bit and or a 1 into the least significant bit;\n       this gives us b * 2**p2 = rv/2^(bc->scale) + 0.5 ulp. */\n    b = lshift(b, 1);\n    if (b == NULL)\n        return -1;\n    b->x[0] |= 1;\n    p2--;\n\n    p2 -= p5;\n    d = i2b(1);\n    if (d == NULL) {\n        Bfree(b);\n        return -1;\n    }\n    /* Arrange for convenient computation of quotients:\n     * shift left if necessary so divisor has 4 leading 0 bits.\n     */\n    if (p5 > 0) {\n        d = pow5mult(d, p5);\n        if (d == NULL) {\n            Bfree(b);\n            return -1;\n        }\n    }\n    else if (p5 < 0) {\n        b = pow5mult(b, -p5);\n        if (b == NULL) {\n            Bfree(d);\n            return -1;\n        }\n    }\n    if (p2 > 0) {\n        b2 = p2;\n        d2 = 0;\n    }\n    else {\n        b2 = 0;\n        d2 = -p2;\n    }\n    i = dshift(d, d2);\n    if ((b2 += i) > 0) {\n        b = lshift(b, b2);\n        if (b == NULL) {\n            Bfree(d);\n            return -1;\n        }\n    }\n    if ((d2 += i) > 0) {\n        d = lshift(d, d2);\n        if (d == NULL) {\n            Bfree(b);\n            return -1;\n        }\n    }\n\n    /* Compare s0 with b/d: set dd to -1, 0, or 1 according as s0 < b/d, s0 ==\n     * b/d, or s0 > b/d.  Here the digits of s0 are thought of as representing\n     * a number in the range [0.1, 1). */\n    if (cmp(b, d) >= 0)\n        /* b/d >= 1 */\n        dd = -1;\n    else {\n        i = 0;\n        for(;;) {\n            b = multadd(b, 10, 0);\n            if (b == NULL) {\n                Bfree(d);\n                return -1;\n            }\n            dd = s0[i < nd0 ? i : i+1] - '0' - quorem(b, d);\n            i++;\n\n            if (dd)\n                break;\n            if (!b->x[0] && b->wds == 1) {\n                /* b/d == 0 */\n                dd = i < nd;\n                break;\n            }\n            if (!(i < nd)) {\n                /* b/d != 0, but digits of s0 exhausted */\n                dd = -1;\n                break;\n            }\n        }\n    }\n    Bfree(b);\n    Bfree(d);\n    if (dd > 0 || (dd == 0 && odd))\n        dval(rv) += sulp(rv, bc);\n    return 0;\n}\n\n\ndouble\n_Py_dg_strtod(const char *s00, char **se)\n{\n    int bb2, bb5, bbe, bd2, bd5, bs2, c, dsign, e, e1, error;\n    int esign, i, j, k, lz, nd, nd0, odd, sign;\n    const char *s, *s0, *s1;\n    double aadj, aadj1;\n    U aadj2, adj, rv, rv0;\n    ULong y, z, abs_exp;\n    Long L;\n    BCinfo bc;\n    Bigint *bb = NULL, *bd = NULL, *bd0 = NULL, *bs = NULL, *delta = NULL;\n    size_t ndigits, fraclen;\n    double result;\n\n    dval(&rv) = 0.;\n\n    /* Start parsing. */\n    c = *(s = s00);\n\n    /* Parse optional sign, if present. */\n    sign = 0;\n    switch (c) {\n    case '-':\n        sign = 1;\n        /* fall through */\n    case '+':\n        c = *++s;\n    }\n\n    /* Skip leading zeros: lz is true iff there were leading zeros. */\n    s1 = s;\n    while (c == '0')\n        c = *++s;\n    lz = s != s1;\n\n    /* Point s0 at the first nonzero digit (if any).  fraclen will be the\n       number of digits between the decimal point and the end of the\n       digit string.  ndigits will be the total number of digits ignoring\n       leading zeros. */\n    s0 = s1 = s;\n    while ('0' <= c && c <= '9')\n        c = *++s;\n    ndigits = s - s1;\n    fraclen = 0;\n\n    /* Parse decimal point and following digits. */\n    if (c == '.') {\n        c = *++s;\n        if (!ndigits) {\n            s1 = s;\n            while (c == '0')\n                c = *++s;\n            lz = lz || s != s1;\n            fraclen += (s - s1);\n            s0 = s;\n        }\n        s1 = s;\n        while ('0' <= c && c <= '9')\n            c = *++s;\n        ndigits += s - s1;\n        fraclen += s - s1;\n    }\n\n    /* Now lz is true if and only if there were leading zero digits, and\n       ndigits gives the total number of digits ignoring leading zeros.  A\n       valid input must have at least one digit. */\n    if (!ndigits && !lz) {\n        if (se)\n            *se = (char *)s00;\n        goto parse_error;\n    }\n\n    /* Range check ndigits and fraclen to make sure that they, and values\n       computed with them, can safely fit in an int. */\n    if (ndigits > MAX_DIGITS || fraclen > MAX_DIGITS) {\n        if (se)\n            *se = (char *)s00;\n        goto parse_error;\n    }\n    nd = (int)ndigits;\n    nd0 = (int)ndigits - (int)fraclen;\n\n    /* Parse exponent. */\n    e = 0;\n    if (c == 'e' || c == 'E') {\n        s00 = s;\n        c = *++s;\n\n        /* Exponent sign. */\n        esign = 0;\n        switch (c) {\n        case '-':\n            esign = 1;\n            /* fall through */\n        case '+':\n            c = *++s;\n        }\n\n        /* Skip zeros.  lz is true iff there are leading zeros. */\n        s1 = s;\n        while (c == '0')\n            c = *++s;\n        lz = s != s1;\n\n        /* Get absolute value of the exponent. */\n        s1 = s;\n        abs_exp = 0;\n        while ('0' <= c && c <= '9') {\n            abs_exp = 10*abs_exp + (c - '0');\n            c = *++s;\n        }\n\n        /* abs_exp will be correct modulo 2**32.  But 10**9 < 2**32, so if\n           there are at most 9 significant exponent digits then overflow is\n           impossible. */\n        if (s - s1 > 9 || abs_exp > MAX_ABS_EXP)\n            e = (int)MAX_ABS_EXP;\n        else\n            e = (int)abs_exp;\n        if (esign)\n            e = -e;\n\n        /* A valid exponent must have at least one digit. */\n        if (s == s1 && !lz)\n            s = s00;\n    }\n\n    /* Adjust exponent to take into account position of the point. */\n    e -= nd - nd0;\n    if (nd0 <= 0)\n        nd0 = nd;\n\n    /* Finished parsing.  Set se to indicate how far we parsed */\n    if (se)\n        *se = (char *)s;\n\n    /* If all digits were zero, exit with return value +-0.0.  Otherwise,\n       strip trailing zeros: scan back until we hit a nonzero digit. */\n    if (!nd)\n        goto ret;\n    for (i = nd; i > 0; ) {\n        --i;\n        if (s0[i < nd0 ? i : i+1] != '0') {\n            ++i;\n            break;\n        }\n    }\n    e += nd - i;\n    nd = i;\n    if (nd0 > nd)\n        nd0 = nd;\n\n    /* Summary of parsing results.  After parsing, and dealing with zero\n     * inputs, we have values s0, nd0, nd, e, sign, where:\n     *\n     *  - s0 points to the first significant digit of the input string\n     *\n     *  - nd is the total number of significant digits (here, and\n     *    below, 'significant digits' means the set of digits of the\n     *    significand of the input that remain after ignoring leading\n     *    and trailing zeros).\n     *\n     *  - nd0 indicates the position of the decimal point, if present; it\n     *    satisfies 1 <= nd0 <= nd.  The nd significant digits are in\n     *    s0[0:nd0] and s0[nd0+1:nd+1] using the usual Python half-open slice\n     *    notation.  (If nd0 < nd, then s0[nd0] contains a '.'  character; if\n     *    nd0 == nd, then s0[nd0] could be any non-digit character.)\n     *\n     *  - e is the adjusted exponent: the absolute value of the number\n     *    represented by the original input string is n * 10**e, where\n     *    n is the integer represented by the concatenation of\n     *    s0[0:nd0] and s0[nd0+1:nd+1]\n     *\n     *  - sign gives the sign of the input:  1 for negative, 0 for positive\n     *\n     *  - the first and last significant digits are nonzero\n     */\n\n    /* put first DBL_DIG+1 digits into integer y and z.\n     *\n     *  - y contains the value represented by the first min(9, nd)\n     *    significant digits\n     *\n     *  - if nd > 9, z contains the value represented by significant digits\n     *    with indices in [9, min(16, nd)).  So y * 10**(min(16, nd) - 9) + z\n     *    gives the value represented by the first min(16, nd) sig. digits.\n     */\n\n    bc.e0 = e1 = e;\n    y = z = 0;\n    for (i = 0; i < nd; i++) {\n        if (i < 9)\n            y = 10*y + s0[i < nd0 ? i : i+1] - '0';\n        else if (i < DBL_DIG+1)\n            z = 10*z + s0[i < nd0 ? i : i+1] - '0';\n        else\n            break;\n    }\n\n    k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;\n    dval(&rv) = y;\n    if (k > 9) {\n        dval(&rv) = tens[k - 9] * dval(&rv) + z;\n    }\n    if (nd <= DBL_DIG\n        && Flt_Rounds == 1\n        ) {\n        if (!e)\n            goto ret;\n        if (e > 0) {\n            if (e <= Ten_pmax) {\n                dval(&rv) *= tens[e];\n                goto ret;\n            }\n            i = DBL_DIG - nd;\n            if (e <= Ten_pmax + i) {\n                /* A fancier test would sometimes let us do\n                 * this for larger i values.\n                 */\n                e -= i;\n                dval(&rv) *= tens[i];\n                dval(&rv) *= tens[e];\n                goto ret;\n            }\n        }\n        else if (e >= -Ten_pmax) {\n            dval(&rv) /= tens[-e];\n            goto ret;\n        }\n    }\n    e1 += nd - k;\n\n    bc.scale = 0;\n\n    /* Get starting approximation = rv * 10**e1 */\n\n    if (e1 > 0) {\n        if ((i = e1 & 15))\n            dval(&rv) *= tens[i];\n        if (e1 &= ~15) {\n            if (e1 > DBL_MAX_10_EXP)\n                goto ovfl;\n            e1 >>= 4;\n            for(j = 0; e1 > 1; j++, e1 >>= 1)\n                if (e1 & 1)\n                    dval(&rv) *= bigtens[j];\n            /* The last multiplication could overflow. */\n            word0(&rv) -= P*Exp_msk1;\n            dval(&rv) *= bigtens[j];\n            if ((z = word0(&rv) & Exp_mask)\n                > Exp_msk1*(DBL_MAX_EXP+Bias-P))\n                goto ovfl;\n            if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {\n                /* set to largest number */\n                /* (Can't trust DBL_MAX) */\n                word0(&rv) = Big0;\n                word1(&rv) = Big1;\n            }\n            else\n                word0(&rv) += P*Exp_msk1;\n        }\n    }\n    else if (e1 < 0) {\n        /* The input decimal value lies in [10**e1, 10**(e1+16)).\n\n           If e1 <= -512, underflow immediately.\n           If e1 <= -256, set bc.scale to 2*P.\n\n           So for input value < 1e-256, bc.scale is always set;\n           for input value >= 1e-240, bc.scale is never set.\n           For input values in [1e-256, 1e-240), bc.scale may or may\n           not be set. */\n\n        e1 = -e1;\n        if ((i = e1 & 15))\n            dval(&rv) /= tens[i];\n        if (e1 >>= 4) {\n            if (e1 >= 1 << n_bigtens)\n                goto undfl;\n            if (e1 & Scale_Bit)\n                bc.scale = 2*P;\n            for(j = 0; e1 > 0; j++, e1 >>= 1)\n                if (e1 & 1)\n                    dval(&rv) *= tinytens[j];\n            if (bc.scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask)\n                                            >> Exp_shift)) > 0) {\n                /* scaled rv is denormal; clear j low bits */\n                if (j >= 32) {\n                    word1(&rv) = 0;\n                    if (j >= 53)\n                        word0(&rv) = (P+2)*Exp_msk1;\n                    else\n                        word0(&rv) &= 0xffffffff << (j-32);\n                }\n                else\n                    word1(&rv) &= 0xffffffff << j;\n            }\n            if (!dval(&rv))\n                goto undfl;\n        }\n    }\n\n    /* Now the hard part -- adjusting rv to the correct value.*/\n\n    /* Put digits into bd: true value = bd * 10^e */\n\n    bc.nd = nd;\n    bc.nd0 = nd0;       /* Only needed if nd > STRTOD_DIGLIM, but done here */\n                        /* to silence an erroneous warning about bc.nd0 */\n                        /* possibly not being initialized. */\n    if (nd > STRTOD_DIGLIM) {\n        /* ASSERT(STRTOD_DIGLIM >= 18); 18 == one more than the */\n        /* minimum number of decimal digits to distinguish double values */\n        /* in IEEE arithmetic. */\n\n        /* Truncate input to 18 significant digits, then discard any trailing\n           zeros on the result by updating nd, nd0, e and y suitably. (There's\n           no need to update z; it's not reused beyond this point.) */\n        for (i = 18; i > 0; ) {\n            /* scan back until we hit a nonzero digit.  significant digit 'i'\n            is s0[i] if i < nd0, s0[i+1] if i >= nd0. */\n            --i;\n            if (s0[i < nd0 ? i : i+1] != '0') {\n                ++i;\n                break;\n            }\n        }\n        e += nd - i;\n        nd = i;\n        if (nd0 > nd)\n            nd0 = nd;\n        if (nd < 9) { /* must recompute y */\n            y = 0;\n            for(i = 0; i < nd0; ++i)\n                y = 10*y + s0[i] - '0';\n            for(; i < nd; ++i)\n                y = 10*y + s0[i+1] - '0';\n        }\n    }\n    bd0 = s2b(s0, nd0, nd, y);\n    if (bd0 == NULL)\n        goto failed_malloc;\n\n    /* Notation for the comments below.  Write:\n\n         - dv for the absolute value of the number represented by the original\n           decimal input string.\n\n         - if we've truncated dv, write tdv for the truncated value.\n           Otherwise, set tdv == dv.\n\n         - srv for the quantity rv/2^bc.scale; so srv is the current binary\n           approximation to tdv (and dv).  It should be exactly representable\n           in an IEEE 754 double.\n    */\n\n    for(;;) {\n\n        /* This is the main correction loop for _Py_dg_strtod.\n\n           We've got a decimal value tdv, and a floating-point approximation\n           srv=rv/2^bc.scale to tdv.  The aim is to determine whether srv is\n           close enough (i.e., within 0.5 ulps) to tdv, and to compute a new\n           approximation if not.\n\n           To determine whether srv is close enough to tdv, compute integers\n           bd, bb and bs proportional to tdv, srv and 0.5 ulp(srv)\n           respectively, and then use integer arithmetic to determine whether\n           |tdv - srv| is less than, equal to, or greater than 0.5 ulp(srv).\n        */\n\n        bd = Balloc(bd0->k);\n        if (bd == NULL) {\n            goto failed_malloc;\n        }\n        Bcopy(bd, bd0);\n        bb = sd2b(&rv, bc.scale, &bbe);   /* srv = bb * 2^bbe */\n        if (bb == NULL) {\n            goto failed_malloc;\n        }\n        /* Record whether lsb of bb is odd, in case we need this\n           for the round-to-even step later. */\n        odd = bb->x[0] & 1;\n\n        /* tdv = bd * 10**e;  srv = bb * 2**bbe */\n        bs = i2b(1);\n        if (bs == NULL) {\n            goto failed_malloc;\n        }\n\n        if (e >= 0) {\n            bb2 = bb5 = 0;\n            bd2 = bd5 = e;\n        }\n        else {\n            bb2 = bb5 = -e;\n            bd2 = bd5 = 0;\n        }\n        if (bbe >= 0)\n            bb2 += bbe;\n        else\n            bd2 -= bbe;\n        bs2 = bb2;\n        bb2++;\n        bd2++;\n\n        /* At this stage bd5 - bb5 == e == bd2 - bb2 + bbe, bb2 - bs2 == 1,\n           and bs == 1, so:\n\n              tdv == bd * 10**e = bd * 2**(bbe - bb2 + bd2) * 5**(bd5 - bb5)\n              srv == bb * 2**bbe = bb * 2**(bbe - bb2 + bb2)\n              0.5 ulp(srv) == 2**(bbe-1) = bs * 2**(bbe - bb2 + bs2)\n\n           It follows that:\n\n              M * tdv = bd * 2**bd2 * 5**bd5\n              M * srv = bb * 2**bb2 * 5**bb5\n              M * 0.5 ulp(srv) = bs * 2**bs2 * 5**bb5\n\n           for some constant M.  (Actually, M == 2**(bb2 - bbe) * 5**bb5, but\n           this fact is not needed below.)\n        */\n\n        /* Remove factor of 2**i, where i = min(bb2, bd2, bs2). */\n        i = bb2 < bd2 ? bb2 : bd2;\n        if (i > bs2)\n            i = bs2;\n        if (i > 0) {\n            bb2 -= i;\n            bd2 -= i;\n            bs2 -= i;\n        }\n\n        /* Scale bb, bd, bs by the appropriate powers of 2 and 5. */\n        if (bb5 > 0) {\n            bs = pow5mult(bs, bb5);\n            if (bs == NULL) {\n                goto failed_malloc;\n            }\n            Bigint *bb1 = mult(bs, bb);\n            Bfree(bb);\n            bb = bb1;\n            if (bb == NULL) {\n                goto failed_malloc;\n            }\n        }\n        if (bb2 > 0) {\n            bb = lshift(bb, bb2);\n            if (bb == NULL) {\n                goto failed_malloc;\n            }\n        }\n        if (bd5 > 0) {\n            bd = pow5mult(bd, bd5);\n            if (bd == NULL) {\n                goto failed_malloc;\n            }\n        }\n        if (bd2 > 0) {\n            bd = lshift(bd, bd2);\n            if (bd == NULL) {\n                goto failed_malloc;\n            }\n        }\n        if (bs2 > 0) {\n            bs = lshift(bs, bs2);\n            if (bs == NULL) {\n                goto failed_malloc;\n            }\n        }\n\n        /* Now bd, bb and bs are scaled versions of tdv, srv and 0.5 ulp(srv),\n           respectively.  Compute the difference |tdv - srv|, and compare\n           with 0.5 ulp(srv). */\n\n        delta = diff(bb, bd);\n        if (delta == NULL) {\n            goto failed_malloc;\n        }\n        dsign = delta->sign;\n        delta->sign = 0;\n        i = cmp(delta, bs);\n        if (bc.nd > nd && i <= 0) {\n            if (dsign)\n                break;  /* Must use bigcomp(). */\n\n            /* Here rv overestimates the truncated decimal value by at most\n               0.5 ulp(rv).  Hence rv either overestimates the true decimal\n               value by <= 0.5 ulp(rv), or underestimates it by some small\n               amount (< 0.1 ulp(rv)); either way, rv is within 0.5 ulps of\n               the true decimal value, so it's possible to exit.\n\n               Exception: if scaled rv is a normal exact power of 2, but not\n               DBL_MIN, then rv - 0.5 ulp(rv) takes us all the way down to the\n               next double, so the correctly rounded result is either rv - 0.5\n               ulp(rv) or rv; in this case, use bigcomp to distinguish. */\n\n            if (!word1(&rv) && !(word0(&rv) & Bndry_mask)) {\n                /* rv can't be 0, since it's an overestimate for some\n                   nonzero value.  So rv is a normal power of 2. */\n                j = (int)(word0(&rv) & Exp_mask) >> Exp_shift;\n                /* rv / 2^bc.scale = 2^(j - 1023 - bc.scale); use bigcomp if\n                   rv / 2^bc.scale >= 2^-1021. */\n                if (j - bc.scale >= 2) {\n                    dval(&rv) -= 0.5 * sulp(&rv, &bc);\n                    break; /* Use bigcomp. */\n                }\n            }\n\n            {\n                bc.nd = nd;\n                i = -1; /* Discarded digits make delta smaller. */\n            }\n        }\n\n        if (i < 0) {\n            /* Error is less than half an ulp -- check for\n             * special case of mantissa a power of two.\n             */\n            if (dsign || word1(&rv) || word0(&rv) & Bndry_mask\n                || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1\n                ) {\n                break;\n            }\n            if (!delta->x[0] && delta->wds <= 1) {\n                /* exact result */\n                break;\n            }\n            delta = lshift(delta,Log2P);\n            if (delta == NULL) {\n                goto failed_malloc;\n            }\n            if (cmp(delta, bs) > 0)\n                goto drop_down;\n            break;\n        }\n        if (i == 0) {\n            /* exactly half-way between */\n            if (dsign) {\n                if ((word0(&rv) & Bndry_mask1) == Bndry_mask1\n                    &&  word1(&rv) == (\n                        (bc.scale &&\n                         (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) ?\n                        (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :\n                        0xffffffff)) {\n                    /*boundary case -- increment exponent*/\n                    word0(&rv) = (word0(&rv) & Exp_mask)\n                        + Exp_msk1\n                        ;\n                    word1(&rv) = 0;\n                    /* dsign = 0; */\n                    break;\n                }\n            }\n            else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {\n              drop_down:\n                /* boundary case -- decrement exponent */\n                if (bc.scale) {\n                    L = word0(&rv) & Exp_mask;\n                    if (L <= (2*P+1)*Exp_msk1) {\n                        if (L > (P+2)*Exp_msk1)\n                            /* round even ==> */\n                            /* accept rv */\n                            break;\n                        /* rv = smallest denormal */\n                        if (bc.nd > nd)\n                            break;\n                        goto undfl;\n                    }\n                }\n                L = (word0(&rv) & Exp_mask) - Exp_msk1;\n                word0(&rv) = L | Bndry_mask1;\n                word1(&rv) = 0xffffffff;\n                break;\n            }\n            if (!odd)\n                break;\n            if (dsign)\n                dval(&rv) += sulp(&rv, &bc);\n            else {\n                dval(&rv) -= sulp(&rv, &bc);\n                if (!dval(&rv)) {\n                    if (bc.nd >nd)\n                        break;\n                    goto undfl;\n                }\n            }\n            /* dsign = 1 - dsign; */\n            break;\n        }\n        if ((aadj = ratio(delta, bs)) <= 2.) {\n            if (dsign)\n                aadj = aadj1 = 1.;\n            else if (word1(&rv) || word0(&rv) & Bndry_mask) {\n                if (word1(&rv) == Tiny1 && !word0(&rv)) {\n                    if (bc.nd >nd)\n                        break;\n                    goto undfl;\n                }\n                aadj = 1.;\n                aadj1 = -1.;\n            }\n            else {\n                /* special case -- power of FLT_RADIX to be */\n                /* rounded down... */\n\n                if (aadj < 2./FLT_RADIX)\n                    aadj = 1./FLT_RADIX;\n                else\n                    aadj *= 0.5;\n                aadj1 = -aadj;\n            }\n        }\n        else {\n            aadj *= 0.5;\n            aadj1 = dsign ? aadj : -aadj;\n            if (Flt_Rounds == 0)\n                aadj1 += 0.5;\n        }\n        y = word0(&rv) & Exp_mask;\n\n        /* Check for overflow */\n\n        if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {\n            dval(&rv0) = dval(&rv);\n            word0(&rv) -= P*Exp_msk1;\n            adj.d = aadj1 * ulp(&rv);\n            dval(&rv) += adj.d;\n            if ((word0(&rv) & Exp_mask) >=\n                Exp_msk1*(DBL_MAX_EXP+Bias-P)) {\n                if (word0(&rv0) == Big0 && word1(&rv0) == Big1) {\n                    goto ovfl;\n                }\n                word0(&rv) = Big0;\n                word1(&rv) = Big1;\n                goto cont;\n            }\n            else\n                word0(&rv) += P*Exp_msk1;\n        }\n        else {\n            if (bc.scale && y <= 2*P*Exp_msk1) {\n                if (aadj <= 0x7fffffff) {\n                    if ((z = (ULong)aadj) <= 0)\n                        z = 1;\n                    aadj = z;\n                    aadj1 = dsign ? aadj : -aadj;\n                }\n                dval(&aadj2) = aadj1;\n                word0(&aadj2) += (2*P+1)*Exp_msk1 - y;\n                aadj1 = dval(&aadj2);\n            }\n            adj.d = aadj1 * ulp(&rv);\n            dval(&rv) += adj.d;\n        }\n        z = word0(&rv) & Exp_mask;\n        if (bc.nd == nd) {\n            if (!bc.scale)\n                if (y == z) {\n                    /* Can we stop now? */\n                    L = (Long)aadj;\n                    aadj -= L;\n                    /* The tolerances below are conservative. */\n                    if (dsign || word1(&rv) || word0(&rv) & Bndry_mask) {\n                        if (aadj < .4999999 || aadj > .5000001)\n                            break;\n                    }\n                    else if (aadj < .4999999/FLT_RADIX)\n                        break;\n                }\n        }\n      cont:\n        Bfree(bb); bb = NULL;\n        Bfree(bd); bd = NULL;\n        Bfree(bs); bs = NULL;\n        Bfree(delta); delta = NULL;\n    }\n    if (bc.nd > nd) {\n        error = bigcomp(&rv, s0, &bc);\n        if (error)\n            goto failed_malloc;\n    }\n\n    if (bc.scale) {\n        word0(&rv0) = Exp_1 - 2*P*Exp_msk1;\n        word1(&rv0) = 0;\n        dval(&rv) *= dval(&rv0);\n    }\n\n  ret:\n    result = sign ? -dval(&rv) : dval(&rv);\n    goto done;\n\n  parse_error:\n    result = 0.0;\n    goto done;\n\n  failed_malloc:\n    errno = ENOMEM;\n    result = -1.0;\n    goto done;\n\n  undfl:\n    result = sign ? -0.0 : 0.0;\n    goto done;\n\n  ovfl:\n    errno = ERANGE;\n    /* Can't trust HUGE_VAL */\n    word0(&rv) = Exp_mask;\n    word1(&rv) = 0;\n    result = sign ? -dval(&rv) : dval(&rv);\n    goto done;\n\n  done:\n    Bfree(bb);\n    Bfree(bd);\n    Bfree(bs);\n    Bfree(bd0);\n    Bfree(delta);\n    return result;\n\n}\n\nstatic char *\nrv_alloc(int i)\n{\n    int j, k, *r;\n\n    j = sizeof(ULong);\n    for(k = 0;\n        sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (unsigned)i;\n        j <<= 1)\n        k++;\n    r = (int*)Balloc(k);\n    if (r == NULL)\n        return NULL;\n    *r = k;\n    return (char *)(r+1);\n}\n\nstatic char *\nnrv_alloc(const char *s, char **rve, int n)\n{\n    char *rv, *t;\n\n    rv = rv_alloc(n);\n    if (rv == NULL)\n        return NULL;\n    t = rv;\n    while((*t = *s++)) t++;\n    if (rve)\n        *rve = t;\n    return rv;\n}\n\n/* freedtoa(s) must be used to free values s returned by dtoa\n * when MULTIPLE_THREADS is #defined.  It should be used in all cases,\n * but for consistency with earlier versions of dtoa, it is optional\n * when MULTIPLE_THREADS is not defined.\n */\n\nvoid\n_Py_dg_freedtoa(char *s)\n{\n    Bigint *b = (Bigint *)((int *)s - 1);\n    b->maxwds = 1 << (b->k = *(int*)b);\n    Bfree(b);\n}\n\n/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.\n *\n * Inspired by \"How to Print Floating-Point Numbers Accurately\" by\n * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].\n *\n * Modifications:\n *      1. Rather than iterating, we use a simple numeric overestimate\n *         to determine k = floor(log10(d)).  We scale relevant\n *         quantities using O(log2(k)) rather than O(k) multiplications.\n *      2. For some modes > 2 (corresponding to ecvt and fcvt), we don't\n *         try to generate digits strictly left to right.  Instead, we\n *         compute with fewer bits and propagate the carry if necessary\n *         when rounding the final digit up.  This is often faster.\n *      3. Under the assumption that input will be rounded nearest,\n *         mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.\n *         That is, we allow equality in stopping tests when the\n *         round-nearest rule will give the same floating-point value\n *         as would satisfaction of the stopping test with strict\n *         inequality.\n *      4. We remove common factors of powers of 2 from relevant\n *         quantities.\n *      5. When converting floating-point integers less than 1e16,\n *         we use floating-point arithmetic rather than resorting\n *         to multiple-precision integers.\n *      6. When asked to produce fewer than 15 digits, we first try\n *         to get by with floating-point arithmetic; we resort to\n *         multiple-precision integer arithmetic only if we cannot\n *         guarantee that the floating-point calculation has given\n *         the correctly rounded result.  For k requested digits and\n *         \"uniformly\" distributed input, the probability is\n *         something like 10^(k-15) that we must resort to the Long\n *         calculation.\n */\n\n/* Additional notes (METD): (1) returns NULL on failure.  (2) to avoid memory\n   leakage, a successful call to _Py_dg_dtoa should always be matched by a\n   call to _Py_dg_freedtoa. */\n\nchar *\n_Py_dg_dtoa(double dd, int mode, int ndigits,\n            int *decpt, int *sign, char **rve)\n{\n    /*  Arguments ndigits, decpt, sign are similar to those\n        of ecvt and fcvt; trailing zeros are suppressed from\n        the returned string.  If not null, *rve is set to point\n        to the end of the return value.  If d is +-Infinity or NaN,\n        then *decpt is set to 9999.\n\n        mode:\n        0 ==> shortest string that yields d when read in\n        and rounded to nearest.\n        1 ==> like 0, but with Steele & White stopping rule;\n        e.g. with IEEE P754 arithmetic , mode 0 gives\n        1e23 whereas mode 1 gives 9.999999999999999e22.\n        2 ==> max(1,ndigits) significant digits.  This gives a\n        return value similar to that of ecvt, except\n        that trailing zeros are suppressed.\n        3 ==> through ndigits past the decimal point.  This\n        gives a return value similar to that from fcvt,\n        except that trailing zeros are suppressed, and\n        ndigits can be negative.\n        4,5 ==> similar to 2 and 3, respectively, but (in\n        round-nearest mode) with the tests of mode 0 to\n        possibly return a shorter string that rounds to d.\n        With IEEE arithmetic and compilation with\n        -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same\n        as modes 2 and 3 when FLT_ROUNDS != 1.\n        6-9 ==> Debugging modes similar to mode - 4:  don't try\n        fast floating-point estimate (if applicable).\n\n        Values of mode other than 0-9 are treated as mode 0.\n\n        Sufficient space is allocated to the return value\n        to hold the suppressed trailing zeros.\n    */\n\n    int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,\n        j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,\n        spec_case, try_quick;\n    Long L;\n    int denorm;\n    ULong x;\n    Bigint *b, *b1, *delta, *mlo, *mhi, *S;\n    U d2, eps, u;\n    double ds;\n    char *s, *s0;\n\n    /* set pointers to NULL, to silence gcc compiler warnings and make\n       cleanup easier on error */\n    mlo = mhi = S = 0;\n    s0 = 0;\n\n    u.d = dd;\n    if (word0(&u) & Sign_bit) {\n        /* set sign for everything, including 0's and NaNs */\n        *sign = 1;\n        word0(&u) &= ~Sign_bit; /* clear sign bit */\n    }\n    else\n        *sign = 0;\n\n    /* quick return for Infinities, NaNs and zeros */\n    if ((word0(&u) & Exp_mask) == Exp_mask)\n    {\n        /* Infinity or NaN */\n        *decpt = 9999;\n        if (!word1(&u) && !(word0(&u) & 0xfffff))\n            return nrv_alloc(\"Infinity\", rve, 8);\n        return nrv_alloc(\"NaN\", rve, 3);\n    }\n    if (!dval(&u)) {\n        *decpt = 1;\n        return nrv_alloc(\"0\", rve, 1);\n    }\n\n    /* compute k = floor(log10(d)).  The computation may leave k\n       one too large, but should never leave k too small. */\n    b = d2b(&u, &be, &bbits);\n    if (b == NULL)\n        goto failed_malloc;\n    if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) {\n        dval(&d2) = dval(&u);\n        word0(&d2) &= Frac_mask1;\n        word0(&d2) |= Exp_11;\n\n        /* log(x)       ~=~ log(1.5) + (x-1.5)/1.5\n         * log10(x)      =  log(x) / log(10)\n         *              ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))\n         * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)\n         *\n         * This suggests computing an approximation k to log10(d) by\n         *\n         * k = (i - Bias)*0.301029995663981\n         *      + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );\n         *\n         * We want k to be too large rather than too small.\n         * The error in the first-order Taylor series approximation\n         * is in our favor, so we just round up the constant enough\n         * to compensate for any error in the multiplication of\n         * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,\n         * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,\n         * adding 1e-13 to the constant term more than suffices.\n         * Hence we adjust the constant term to 0.1760912590558.\n         * (We could get a more accurate k by invoking log10,\n         *  but this is probably not worthwhile.)\n         */\n\n        i -= Bias;\n        denorm = 0;\n    }\n    else {\n        /* d is denormalized */\n\n        i = bbits + be + (Bias + (P-1) - 1);\n        x = i > 32  ? word0(&u) << (64 - i) | word1(&u) >> (i - 32)\n            : word1(&u) << (32 - i);\n        dval(&d2) = x;\n        word0(&d2) -= 31*Exp_msk1; /* adjust exponent */\n        i -= (Bias + (P-1) - 1) + 1;\n        denorm = 1;\n    }\n    ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 +\n        i*0.301029995663981;\n    k = (int)ds;\n    if (ds < 0. && ds != k)\n        k--;    /* want k = floor(ds) */\n    k_check = 1;\n    if (k >= 0 && k <= Ten_pmax) {\n        if (dval(&u) < tens[k])\n            k--;\n        k_check = 0;\n    }\n    j = bbits - i - 1;\n    if (j >= 0) {\n        b2 = 0;\n        s2 = j;\n    }\n    else {\n        b2 = -j;\n        s2 = 0;\n    }\n    if (k >= 0) {\n        b5 = 0;\n        s5 = k;\n        s2 += k;\n    }\n    else {\n        b2 -= k;\n        b5 = -k;\n        s5 = 0;\n    }\n    if (mode < 0 || mode > 9)\n        mode = 0;\n\n    try_quick = 1;\n\n    if (mode > 5) {\n        mode -= 4;\n        try_quick = 0;\n    }\n    leftright = 1;\n    ilim = ilim1 = -1;  /* Values for cases 0 and 1; done here to */\n    /* silence erroneous \"gcc -Wall\" warning. */\n    switch(mode) {\n    case 0:\n    case 1:\n        i = 18;\n        ndigits = 0;\n        break;\n    case 2:\n        leftright = 0;\n        /* fall through */\n    case 4:\n        if (ndigits <= 0)\n            ndigits = 1;\n        ilim = ilim1 = i = ndigits;\n        break;\n    case 3:\n        leftright = 0;\n        /* fall through */\n    case 5:\n        i = ndigits + k + 1;\n        ilim = i;\n        ilim1 = i - 1;\n        if (i <= 0)\n            i = 1;\n    }\n    s0 = rv_alloc(i);\n    if (s0 == NULL)\n        goto failed_malloc;\n    s = s0;\n\n\n    if (ilim >= 0 && ilim <= Quick_max && try_quick) {\n\n        /* Try to get by with floating-point arithmetic. */\n\n        i = 0;\n        dval(&d2) = dval(&u);\n        k0 = k;\n        ilim0 = ilim;\n        ieps = 2; /* conservative */\n        if (k > 0) {\n            ds = tens[k&0xf];\n            j = k >> 4;\n            if (j & Bletch) {\n                /* prevent overflows */\n                j &= Bletch - 1;\n                dval(&u) /= bigtens[n_bigtens-1];\n                ieps++;\n            }\n            for(; j; j >>= 1, i++)\n                if (j & 1) {\n                    ieps++;\n                    ds *= bigtens[i];\n                }\n            dval(&u) /= ds;\n        }\n        else if ((j1 = -k)) {\n            dval(&u) *= tens[j1 & 0xf];\n            for(j = j1 >> 4; j; j >>= 1, i++)\n                if (j & 1) {\n                    ieps++;\n                    dval(&u) *= bigtens[i];\n                }\n        }\n        if (k_check && dval(&u) < 1. && ilim > 0) {\n            if (ilim1 <= 0)\n                goto fast_failed;\n            ilim = ilim1;\n            k--;\n            dval(&u) *= 10.;\n            ieps++;\n        }\n        dval(&eps) = ieps*dval(&u) + 7.;\n        word0(&eps) -= (P-1)*Exp_msk1;\n        if (ilim == 0) {\n            S = mhi = 0;\n            dval(&u) -= 5.;\n            if (dval(&u) > dval(&eps))\n                goto one_digit;\n            if (dval(&u) < -dval(&eps))\n                goto no_digits;\n            goto fast_failed;\n        }\n        if (leftright) {\n            /* Use Steele & White method of only\n             * generating digits needed.\n             */\n            dval(&eps) = 0.5/tens[ilim-1] - dval(&eps);\n            for(i = 0;;) {\n                L = (Long)dval(&u);\n                dval(&u) -= L;\n                *s++ = '0' + (int)L;\n                if (dval(&u) < dval(&eps))\n                    goto ret1;\n                if (1. - dval(&u) < dval(&eps))\n                    goto bump_up;\n                if (++i >= ilim)\n                    break;\n                dval(&eps) *= 10.;\n                dval(&u) *= 10.;\n            }\n        }\n        else {\n            /* Generate ilim digits, then fix them up. */\n            dval(&eps) *= tens[ilim-1];\n            for(i = 1;; i++, dval(&u) *= 10.) {\n                L = (Long)(dval(&u));\n                if (!(dval(&u) -= L))\n                    ilim = i;\n                *s++ = '0' + (int)L;\n                if (i == ilim) {\n                    if (dval(&u) > 0.5 + dval(&eps))\n                        goto bump_up;\n                    else if (dval(&u) < 0.5 - dval(&eps)) {\n                        while(*--s == '0');\n                        s++;\n                        goto ret1;\n                    }\n                    break;\n                }\n            }\n        }\n      fast_failed:\n        s = s0;\n        dval(&u) = dval(&d2);\n        k = k0;\n        ilim = ilim0;\n    }\n\n    /* Do we have a \"small\" integer? */\n\n    if (be >= 0 && k <= Int_max) {\n        /* Yes. */\n        ds = tens[k];\n        if (ndigits < 0 && ilim <= 0) {\n            S = mhi = 0;\n            if (ilim < 0 || dval(&u) <= 5*ds)\n                goto no_digits;\n            goto one_digit;\n        }\n        for(i = 1;; i++, dval(&u) *= 10.) {\n            L = (Long)(dval(&u) / ds);\n            dval(&u) -= L*ds;\n            *s++ = '0' + (int)L;\n            if (!dval(&u)) {\n                break;\n            }\n            if (i == ilim) {\n                dval(&u) += dval(&u);\n                if (dval(&u) > ds || (dval(&u) == ds && L & 1)) {\n                  bump_up:\n                    while(*--s == '9')\n                        if (s == s0) {\n                            k++;\n                            *s = '0';\n                            break;\n                        }\n                    ++*s++;\n                }\n                else {\n                    /* Strip trailing zeros. This branch was missing from the\n                       original dtoa.c, leading to surplus trailing zeros in\n                       some cases. See bugs.python.org/issue40780. */\n                    while (s > s0 && s[-1] == '0') {\n                        --s;\n                    }\n                }\n                break;\n            }\n        }\n        goto ret1;\n    }\n\n    m2 = b2;\n    m5 = b5;\n    if (leftright) {\n        i =\n            denorm ? be + (Bias + (P-1) - 1 + 1) :\n            1 + P - bbits;\n        b2 += i;\n        s2 += i;\n        mhi = i2b(1);\n        if (mhi == NULL)\n            goto failed_malloc;\n    }\n    if (m2 > 0 && s2 > 0) {\n        i = m2 < s2 ? m2 : s2;\n        b2 -= i;\n        m2 -= i;\n        s2 -= i;\n    }\n    if (b5 > 0) {\n        if (leftright) {\n            if (m5 > 0) {\n                mhi = pow5mult(mhi, m5);\n                if (mhi == NULL)\n                    goto failed_malloc;\n                b1 = mult(mhi, b);\n                Bfree(b);\n                b = b1;\n                if (b == NULL)\n                    goto failed_malloc;\n            }\n            if ((j = b5 - m5)) {\n                b = pow5mult(b, j);\n                if (b == NULL)\n                    goto failed_malloc;\n            }\n        }\n        else {\n            b = pow5mult(b, b5);\n            if (b == NULL)\n                goto failed_malloc;\n        }\n    }\n    S = i2b(1);\n    if (S == NULL)\n        goto failed_malloc;\n    if (s5 > 0) {\n        S = pow5mult(S, s5);\n        if (S == NULL)\n            goto failed_malloc;\n    }\n\n    /* Check for special case that d is a normalized power of 2. */\n\n    spec_case = 0;\n    if ((mode < 2 || leftright)\n        ) {\n        if (!word1(&u) && !(word0(&u) & Bndry_mask)\n            && word0(&u) & (Exp_mask & ~Exp_msk1)\n            ) {\n            /* The special case */\n            b2 += Log2P;\n            s2 += Log2P;\n            spec_case = 1;\n        }\n    }\n\n    /* Arrange for convenient computation of quotients:\n     * shift left if necessary so divisor has 4 leading 0 bits.\n     *\n     * Perhaps we should just compute leading 28 bits of S once\n     * and for all and pass them and a shift to quorem, so it\n     * can do shifts and ors to compute the numerator for q.\n     */\n#define iInc 28\n    i = dshift(S, s2);\n    b2 += i;\n    m2 += i;\n    s2 += i;\n    if (b2 > 0) {\n        b = lshift(b, b2);\n        if (b == NULL)\n            goto failed_malloc;\n    }\n    if (s2 > 0) {\n        S = lshift(S, s2);\n        if (S == NULL)\n            goto failed_malloc;\n    }\n    if (k_check) {\n        if (cmp(b,S) < 0) {\n            k--;\n            b = multadd(b, 10, 0);      /* we botched the k estimate */\n            if (b == NULL)\n                goto failed_malloc;\n            if (leftright) {\n                mhi = multadd(mhi, 10, 0);\n                if (mhi == NULL)\n                    goto failed_malloc;\n            }\n            ilim = ilim1;\n        }\n    }\n    if (ilim <= 0 && (mode == 3 || mode == 5)) {\n        if (ilim < 0) {\n            /* no digits, fcvt style */\n          no_digits:\n            k = -1 - ndigits;\n            goto ret;\n        }\n        else {\n            S = multadd(S, 5, 0);\n            if (S == NULL)\n                goto failed_malloc;\n            if (cmp(b, S) <= 0)\n                goto no_digits;\n        }\n      one_digit:\n        *s++ = '1';\n        k++;\n        goto ret;\n    }\n    if (leftright) {\n        if (m2 > 0) {\n            mhi = lshift(mhi, m2);\n            if (mhi == NULL)\n                goto failed_malloc;\n        }\n\n        /* Compute mlo -- check for special case\n         * that d is a normalized power of 2.\n         */\n\n        mlo = mhi;\n        if (spec_case) {\n            mhi = Balloc(mhi->k);\n            if (mhi == NULL)\n                goto failed_malloc;\n            Bcopy(mhi, mlo);\n            mhi = lshift(mhi, Log2P);\n            if (mhi == NULL)\n                goto failed_malloc;\n        }\n\n        for(i = 1;;i++) {\n            dig = quorem(b,S) + '0';\n            /* Do we yet have the shortest decimal string\n             * that will round to d?\n             */\n            j = cmp(b, mlo);\n            delta = diff(S, mhi);\n            if (delta == NULL)\n                goto failed_malloc;\n            j1 = delta->sign ? 1 : cmp(b, delta);\n            Bfree(delta);\n            if (j1 == 0 && mode != 1 && !(word1(&u) & 1)\n                ) {\n                if (dig == '9')\n                    goto round_9_up;\n                if (j > 0)\n                    dig++;\n                *s++ = dig;\n                goto ret;\n            }\n            if (j < 0 || (j == 0 && mode != 1\n                          && !(word1(&u) & 1)\n                    )) {\n                if (!b->x[0] && b->wds <= 1) {\n                    goto accept_dig;\n                }\n                if (j1 > 0) {\n                    b = lshift(b, 1);\n                    if (b == NULL)\n                        goto failed_malloc;\n                    j1 = cmp(b, S);\n                    if ((j1 > 0 || (j1 == 0 && dig & 1))\n                        && dig++ == '9')\n                        goto round_9_up;\n                }\n              accept_dig:\n                *s++ = dig;\n                goto ret;\n            }\n            if (j1 > 0) {\n                if (dig == '9') { /* possible if i == 1 */\n                  round_9_up:\n                    *s++ = '9';\n                    goto roundoff;\n                }\n                *s++ = dig + 1;\n                goto ret;\n            }\n            *s++ = dig;\n            if (i == ilim)\n                break;\n            b = multadd(b, 10, 0);\n            if (b == NULL)\n                goto failed_malloc;\n            if (mlo == mhi) {\n                mlo = mhi = multadd(mhi, 10, 0);\n                if (mlo == NULL)\n                    goto failed_malloc;\n            }\n            else {\n                mlo = multadd(mlo, 10, 0);\n                if (mlo == NULL)\n                    goto failed_malloc;\n                mhi = multadd(mhi, 10, 0);\n                if (mhi == NULL)\n                    goto failed_malloc;\n            }\n        }\n    }\n    else\n        for(i = 1;; i++) {\n            *s++ = dig = quorem(b,S) + '0';\n            if (!b->x[0] && b->wds <= 1) {\n                goto ret;\n            }\n            if (i >= ilim)\n                break;\n            b = multadd(b, 10, 0);\n            if (b == NULL)\n                goto failed_malloc;\n        }\n\n    /* Round off last digit */\n\n    b = lshift(b, 1);\n    if (b == NULL)\n        goto failed_malloc;\n    j = cmp(b, S);\n    if (j > 0 || (j == 0 && dig & 1)) {\n      roundoff:\n        while(*--s == '9')\n            if (s == s0) {\n                k++;\n                *s++ = '1';\n                goto ret;\n            }\n        ++*s++;\n    }\n    else {\n        while(*--s == '0');\n        s++;\n    }\n  ret:\n    Bfree(S);\n    if (mhi) {\n        if (mlo && mlo != mhi)\n            Bfree(mlo);\n        Bfree(mhi);\n    }\n  ret1:\n    Bfree(b);\n    *s = 0;\n    *decpt = k + 1;\n    if (rve)\n        *rve = s;\n    return s0;\n  failed_malloc:\n    if (S)\n        Bfree(S);\n    if (mlo && mlo != mhi)\n        Bfree(mlo);\n    if (mhi)\n        Bfree(mhi);\n    if (b)\n        Bfree(b);\n    if (s0)\n        _Py_dg_freedtoa(s0);\n    return NULL;\n}\n#ifdef __cplusplus\n}\n#endif\n\n#endif  // _PY_SHORT_FLOAT_REPR == 1\n"
  },
  {
    "path": "Dup2.c",
    "content": "#include <errno.h>\n#include <fcntl.h>\n#include <unistd.h>\n\n#define BADEXIT -1\n\nint\ndup2(int fd1, int fd2)\n{\n    if (fd1 != fd2) {\n#ifdef F_DUPFD\n        if (fcntl(fd1, F_GETFL) < 0)\n            return BADEXIT;\n        if (fcntl(fd2, F_GETFL) >= 0)\n            close(fd2);\n        if (fcntl(fd1, F_DUPFD, fd2) < 0)\n            return BADEXIT;\n#else\n        errno = ENOTSUP;\n        return BADEXIT;\n#endif\n    }\n    return fd2;\n}\n"
  },
  {
    "path": "Dynamic_Annotations.c",
    "content": "\n\n#ifdef _MSC_VER\n# include <windows.h>\n#endif\n\n#ifdef __cplusplus\n# error \"This file should be built as pure C to avoid name mangling\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"dynamic_annotations.h\"\n\n/* Each function is empty and called (via a macro) only in debug mode.\n   The arguments are captured by dynamic tools at runtime. */\n\n#if DYNAMIC_ANNOTATIONS_ENABLED == 1\n\nvoid AnnotateRWLockCreate(const char *file, int line,\n                          const volatile void *lock){}\nvoid AnnotateRWLockDestroy(const char *file, int line,\n                           const volatile void *lock){}\nvoid AnnotateRWLockAcquired(const char *file, int line,\n                            const volatile void *lock, long is_w){}\nvoid AnnotateRWLockReleased(const char *file, int line,\n                            const volatile void *lock, long is_w){}\nvoid AnnotateBarrierInit(const char *file, int line,\n                         const volatile void *barrier, long count,\n                         long reinitialization_allowed) {}\nvoid AnnotateBarrierWaitBefore(const char *file, int line,\n                               const volatile void *barrier) {}\nvoid AnnotateBarrierWaitAfter(const char *file, int line,\n                              const volatile void *barrier) {}\nvoid AnnotateBarrierDestroy(const char *file, int line,\n                            const volatile void *barrier) {}\n\nvoid AnnotateCondVarWait(const char *file, int line,\n                         const volatile void *cv,\n                         const volatile void *lock){}\nvoid AnnotateCondVarSignal(const char *file, int line,\n                           const volatile void *cv){}\nvoid AnnotateCondVarSignalAll(const char *file, int line,\n                              const volatile void *cv){}\nvoid AnnotatePublishMemoryRange(const char *file, int line,\n                                const volatile void *address,\n                                long size){}\nvoid AnnotateUnpublishMemoryRange(const char *file, int line,\n                                  const volatile void *address,\n                                  long size){}\nvoid AnnotatePCQCreate(const char *file, int line,\n                       const volatile void *pcq){}\nvoid AnnotatePCQDestroy(const char *file, int line,\n                        const volatile void *pcq){}\nvoid AnnotatePCQPut(const char *file, int line,\n                    const volatile void *pcq){}\nvoid AnnotatePCQGet(const char *file, int line,\n                    const volatile void *pcq){}\nvoid AnnotateNewMemory(const char *file, int line,\n                       const volatile void *mem,\n                       long size){}\nvoid AnnotateExpectRace(const char *file, int line,\n                        const volatile void *mem,\n                        const char *description){}\nvoid AnnotateBenignRace(const char *file, int line,\n                        const volatile void *mem,\n                        const char *description){}\nvoid AnnotateBenignRaceSized(const char *file, int line,\n                             const volatile void *mem,\n                             long size,\n                             const char *description) {}\nvoid AnnotateMutexIsUsedAsCondVar(const char *file, int line,\n                                  const volatile void *mu){}\nvoid AnnotateTraceMemory(const char *file, int line,\n                         const volatile void *arg){}\nvoid AnnotateThreadName(const char *file, int line,\n                        const char *name){}\nvoid AnnotateIgnoreReadsBegin(const char *file, int line){}\nvoid AnnotateIgnoreReadsEnd(const char *file, int line){}\nvoid AnnotateIgnoreWritesBegin(const char *file, int line){}\nvoid AnnotateIgnoreWritesEnd(const char *file, int line){}\nvoid AnnotateIgnoreSyncBegin(const char *file, int line){}\nvoid AnnotateIgnoreSyncEnd(const char *file, int line){}\nvoid AnnotateEnableRaceDetection(const char *file, int line, int enable){}\nvoid AnnotateNoOp(const char *file, int line,\n                  const volatile void *arg){}\nvoid AnnotateFlushState(const char *file, int line){}\n\nstatic int GetRunningOnValgrind(void) {\n#ifdef RUNNING_ON_VALGRIND\n  if (RUNNING_ON_VALGRIND) return 1;\n#endif\n\n#ifndef _MSC_VER\n  const char *running_on_valgrind_str = getenv(\"RUNNING_ON_VALGRIND\");\n  if (running_on_valgrind_str) {\n    return strcmp(running_on_valgrind_str, \"0\") != 0;\n  }\n#else\n  /* Visual Studio issues warnings if we use getenv,\n   * so we use GetEnvironmentVariableA instead.\n   */\n  char value[100] = \"1\";\n  int res = GetEnvironmentVariableA(\"RUNNING_ON_VALGRIND\",\n                                    value, sizeof(value));\n  /* value will remain \"1\" if res == 0 or res >= sizeof(value). The latter\n   * can happen only if the given value is long, in this case it can't be \"0\".\n   */\n  if (res > 0 && !strcmp(value, \"0\"))\n    return 1;\n#endif\n  return 0;\n}\n\n/* See the comments in dynamic_annotations.h */\nint RunningOnValgrind(void) {\n  static volatile int running_on_valgrind = -1;\n  /* C doesn't have thread-safe initialization of statics, and we\n     don't want to depend on pthread_once here, so hack it. */\n  int local_running_on_valgrind = running_on_valgrind;\n  if (local_running_on_valgrind == -1)\n    running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();\n  return local_running_on_valgrind;\n}\n\n#endif  /* DYNAMIC_ANNOTATIONS_ENABLED == 1 */\n"
  },
  {
    "path": "Dynload_Hpux.c",
    "content": "\n/* Support for dynamic loading of extension modules */\n\n#include \"dl.h\"\n#include <errno.h>\n\n#include \"Python.h\"\n#include \"importdl.h\"\n\n#if defined(__hp9000s300)\n#define FUNCNAME_PATTERN \"_%.20s_%.200s\"\n#else\n#define FUNCNAME_PATTERN \"%.20s_%.200s\"\n#endif\n\nconst char *_PyImport_DynLoadFiletab[] = {SHLIB_EXT, \".sl\", NULL};\n\ndl_funcptr _PyImport_FindSharedFuncptr(const char *prefix,\n                                       const char *shortname,\n                                       const char *pathname, FILE *fp)\n{\n    int flags = BIND_FIRST | BIND_DEFERRED;\n    int verbose = _Py_GetConfig()->verbose;\n    if (verbose) {\n        flags = BIND_FIRST | BIND_IMMEDIATE |\n            BIND_NONFATAL | BIND_VERBOSE;\n        printf(\"shl_load %s\\n\",pathname);\n    }\n\n    shl_t lib = shl_load(pathname, flags, 0);\n    /* XXX Chuck Blake once wrote that 0 should be BIND_NOSTART? */\n    if (lib == NULL) {\n        if (verbose) {\n            perror(pathname);\n        }\n        char buf[256];\n        PyOS_snprintf(buf, sizeof(buf), \"Failed to load %.200s\",\n                      pathname);\n        PyObject *buf_ob = PyUnicode_DecodeFSDefault(buf);\n        if (buf_ob == NULL)\n            return NULL;\n        PyObject *shortname_ob = PyUnicode_FromString(shortname);\n        if (shortname_ob == NULL) {\n            Py_DECREF(buf_ob);\n            return NULL;\n        }\n        PyObject *pathname_ob = PyUnicode_DecodeFSDefault(pathname);\n        if (pathname_ob == NULL) {\n            Py_DECREF(buf_ob);\n            Py_DECREF(shortname_ob);\n            return NULL;\n        }\n        PyErr_SetImportError(buf_ob, shortname_ob, pathname_ob);\n        Py_DECREF(buf_ob);\n        Py_DECREF(shortname_ob);\n        Py_DECREF(pathname_ob);\n        return NULL;\n    }\n\n    char funcname[258];\n    PyOS_snprintf(funcname, sizeof(funcname), FUNCNAME_PATTERN,\n                  prefix, shortname);\n    if (verbose) {\n        printf(\"shl_findsym %s\\n\", funcname);\n    }\n\n    dl_funcptr p;\n    if (shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p) == -1) {\n        shl_unload(lib);\n        p = NULL;\n    }\n    if (p == NULL && verbose) {\n        perror(funcname);\n    }\n    return p;\n}\n"
  },
  {
    "path": "Dynload_Shlib.c",
    "content": "\n/* Support for dynamic loading of extension modules */\n\n#include \"Python.h\"\n#include \"pycore_interp.h\"    // _PyInterpreterState.dlopenflags\n#include \"pycore_pystate.h\"   // _PyInterpreterState_GET()\n#include \"importdl.h\"\n\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#if defined(__NetBSD__)\n#include <sys/param.h>\n#if (NetBSD < 199712)\n#include <nlist.h>\n#include <link.h>\n#define dlerror() \"error in dynamic linking\"\n#endif\n#endif /* NetBSD */\n\n#ifdef HAVE_DLFCN_H\n#include <dlfcn.h>\n#endif\n\n#if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)\n#define LEAD_UNDERSCORE \"_\"\n#else\n#define LEAD_UNDERSCORE \"\"\n#endif\n\n/* The .so extension module ABI tag, supplied by the Makefile via\n   Makefile.pre.in and configure.  This is used to discriminate between\n   incompatible .so files so that extensions for different Python builds can\n   live in the same directory.  E.g. foomodule.cpython-32.so\n*/\n\nconst char *_PyImport_DynLoadFiletab[] = {\n#ifdef __CYGWIN__\n    \".dll\",\n#else  /* !__CYGWIN__ */\n    \".\" SOABI \".so\",\n#ifdef ALT_SOABI\n    \".\" ALT_SOABI \".so\",\n#endif\n    \".abi\" PYTHON_ABI_STRING \".so\",\n    \".so\",\n#endif  /* __CYGWIN__ */\n    NULL,\n};\n\n\ndl_funcptr\n_PyImport_FindSharedFuncptr(const char *prefix,\n                            const char *shortname,\n                            const char *pathname, FILE *fp)\n{\n    dl_funcptr p;\n    void *handle;\n    char funcname[258];\n    char pathbuf[260];\n    int dlopenflags=0;\n\n    if (strchr(pathname, '/') == NULL) {\n        /* Prefix bare filename with \"./\" */\n        PyOS_snprintf(pathbuf, sizeof(pathbuf), \"./%-.255s\", pathname);\n        pathname = pathbuf;\n    }\n\n    PyOS_snprintf(funcname, sizeof(funcname),\n                  LEAD_UNDERSCORE \"%.20s_%.200s\", prefix, shortname);\n\n    if (fp != NULL) {\n        struct _Py_stat_struct status;\n        if (_Py_fstat(fileno(fp), &status) == -1)\n            return NULL;\n    }\n\n    dlopenflags = _PyImport_GetDLOpenFlags(_PyInterpreterState_GET());\n\n    handle = dlopen(pathname, dlopenflags);\n\n    if (handle == NULL) {\n        PyObject *mod_name;\n        PyObject *path;\n        PyObject *error_ob;\n        const char *error = dlerror();\n        if (error == NULL)\n            error = \"unknown dlopen() error\";\n        error_ob = PyUnicode_DecodeLocale(error, \"surrogateescape\");\n        if (error_ob == NULL)\n            return NULL;\n        mod_name = PyUnicode_FromString(shortname);\n        if (mod_name == NULL) {\n            Py_DECREF(error_ob);\n            return NULL;\n        }\n        path = PyUnicode_DecodeFSDefault(pathname);\n        if (path == NULL) {\n            Py_DECREF(error_ob);\n            Py_DECREF(mod_name);\n            return NULL;\n        }\n        PyErr_SetImportError(error_ob, mod_name, path);\n        Py_DECREF(error_ob);\n        Py_DECREF(mod_name);\n        Py_DECREF(path);\n        return NULL;\n    }\n    p = (dl_funcptr) dlsym(handle, funcname);\n    return p;\n}\n"
  },
  {
    "path": "Dynload_Stub.c",
    "content": "\n/* This module provides the necessary stubs for when dynamic loading is\n   not present. */\n\n#include \"Python.h\"\n#include \"importdl.h\"\n\n\nconst char *_PyImport_DynLoadFiletab[] = {NULL};\n"
  },
  {
    "path": "Dynload_Win.c",
    "content": "\n/* Support for dynamic loading of extension modules */\n\n#include \"Python.h\"\n#include \"pycore_fileutils.h\"     // _Py_add_relfile()\n#include \"pycore_pystate.h\"       // _PyInterpreterState_GET()\n\n#ifdef HAVE_DIRECT_H\n#include <direct.h>\n#endif\n#include <ctype.h>\n\n#include \"importdl.h\"\n#include \"patchlevel.h\"\n#include <windows.h>\n\n#ifdef _DEBUG\n#define PYD_DEBUG_SUFFIX \"_d\"\n#else\n#define PYD_DEBUG_SUFFIX \"\"\n#endif\n\n#ifdef PYD_PLATFORM_TAG\n#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX \".cp\" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) \"-\" PYD_PLATFORM_TAG \".pyd\"\n#else\n#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX \".cp\" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) \".pyd\"\n#endif\n\n#define PYD_UNTAGGED_SUFFIX PYD_DEBUG_SUFFIX \".pyd\"\n\nconst char *_PyImport_DynLoadFiletab[] = {\n    PYD_TAGGED_SUFFIX,\n    PYD_UNTAGGED_SUFFIX,\n    NULL\n};\n\n/* Function to return the name of the \"python\" DLL that the supplied module\n   directly imports.  Looks through the list of imported modules and\n   returns the first entry that starts with \"python\" (case sensitive) and\n   is followed by nothing but numbers until the separator (period).\n\n   Returns a pointer to the import name, or NULL if no matching name was\n   located.\n\n   This function parses through the PE header for the module as loaded in\n   memory by the system loader.  The PE header is accessed as documented by\n   Microsoft in the MSDN PE and COFF specification (2/99), and handles\n   both PE32 and PE32+.  It only worries about the direct import table and\n   not the delay load import table since it's unlikely an extension is\n   going to be delay loading Python (after all, it's already loaded).\n\n   If any magic values are not found (e.g., the PE header or optional\n   header magic), then this function simply returns NULL. */\n\n#define DWORD_AT(mem) (*(DWORD *)(mem))\n#define WORD_AT(mem)  (*(WORD *)(mem))\n\nstatic char *GetPythonImport (HINSTANCE hModule)\n{\n    unsigned char *dllbase, *import_data, *import_name;\n    DWORD pe_offset, opt_offset;\n    WORD opt_magic;\n    int num_dict_off, import_off;\n\n    /* Safety check input */\n    if (hModule == NULL) {\n        return NULL;\n    }\n\n    /* Module instance is also the base load address.  First portion of\n       memory is the MS-DOS loader, which holds the offset to the PE\n       header (from the load base) at 0x3C */\n    dllbase = (unsigned char *)hModule;\n    pe_offset = DWORD_AT(dllbase + 0x3C);\n\n    /* The PE signature must be \"PE\\0\\0\" */\n    if (memcmp(dllbase+pe_offset,\"PE\\0\\0\",4)) {\n        return NULL;\n    }\n\n    /* Following the PE signature is the standard COFF header (20\n       bytes) and then the optional header.  The optional header starts\n       with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+\n       uses 64-bits for some fields).  It might also be 0x107 for a ROM\n       image, but we don't process that here.\n\n       The optional header ends with a data dictionary that directly\n       points to certain types of data, among them the import entries\n       (in the second table entry). Based on the header type, we\n       determine offsets for the data dictionary count and the entry\n       within the dictionary pointing to the imports. */\n\n    opt_offset = pe_offset + 4 + 20;\n    opt_magic = WORD_AT(dllbase+opt_offset);\n    if (opt_magic == 0x10B) {\n        /* PE32 */\n        num_dict_off = 92;\n        import_off   = 104;\n    } else if (opt_magic == 0x20B) {\n        /* PE32+ */\n        num_dict_off = 108;\n        import_off   = 120;\n    } else {\n        /* Unsupported */\n        return NULL;\n    }\n\n    /* Now if an import table exists, offset to it and walk the list of\n       imports.  The import table is an array (ending when an entry has\n       empty values) of structures (20 bytes each), which contains (at\n       offset 12) a relative address (to the module base) at which a\n       string constant holding the import name is located. */\n\n    if (DWORD_AT(dllbase + opt_offset + num_dict_off) >= 2) {\n        /* We have at least 2 tables - the import table is the second\n           one.  But still it may be that the table size is zero */\n        if (0 == DWORD_AT(dllbase + opt_offset + import_off + sizeof(DWORD)))\n            return NULL;\n        import_data = dllbase + DWORD_AT(dllbase +\n                                         opt_offset +\n                                         import_off);\n        while (DWORD_AT(import_data)) {\n            import_name = dllbase + DWORD_AT(import_data+12);\n            if (strlen(import_name) >= 6 &&\n                !strncmp(import_name,\"python\",6)) {\n                char *pch;\n\n                /* Don't claim that python3.dll is a Python DLL. */\n#ifdef _DEBUG\n                if (strcmp(import_name, \"python3_d.dll\") == 0) {\n#else\n                if (strcmp(import_name, \"python3.dll\") == 0) {\n#endif\n                    import_data += 20;\n                    continue;\n                }\n\n                /* Ensure python prefix is followed only\n                   by numbers to the end of the basename */\n                pch = import_name + 6;\n#ifdef _DEBUG\n                while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') {\n#else\n                while (*pch && *pch != '.') {\n#endif\n                    if (*pch >= '0' && *pch <= '9') {\n                        pch++;\n                    } else {\n                        pch = NULL;\n                        break;\n                    }\n                }\n\n                if (pch) {\n                    /* Found it - return the name */\n                    return import_name;\n                }\n            }\n            import_data += 20;\n        }\n    }\n\n    return NULL;\n}\n\n#ifdef Py_ENABLE_SHARED\n/* Load python3.dll before loading any extension module that might refer\n   to it. That way, we can be sure that always the python3.dll corresponding\n   to this python DLL is loaded, not a python3.dll that might be on the path\n   by chance.\n   Return whether the DLL was found.\n*/\nextern HMODULE PyWin_DLLhModule;\nstatic int\n_Py_CheckPython3(void)\n{\n    static int python3_checked = 0;\n    static HANDLE hPython3;\n    #define MAXPATHLEN 512\n    wchar_t py3path[MAXPATHLEN+1];\n    if (python3_checked) {\n        return hPython3 != NULL;\n    }\n    python3_checked = 1;\n\n    /* If there is a python3.dll next to the python3y.dll,\n       use that DLL */\n    if (PyWin_DLLhModule && GetModuleFileNameW(PyWin_DLLhModule, py3path, MAXPATHLEN)) {\n        wchar_t *p = wcsrchr(py3path, L'\\\\');\n        if (p) {\n            wcscpy(p + 1, PY3_DLLNAME);\n            hPython3 = LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);\n            if (hPython3 != NULL) {\n                return 1;\n            }\n        }\n    }\n\n    /* If we can locate python3.dll in our application dir,\n       use that DLL */\n    hPython3 = LoadLibraryExW(PY3_DLLNAME, NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR);\n    if (hPython3 != NULL) {\n        return 1;\n    }\n\n    /* For back-compat, also search {sys.prefix}\\DLLs, though\n       that has not been a normal install layout for a while */\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    PyConfig *config = (PyConfig*)_PyInterpreterState_GetConfig(interp);\n    assert(config->prefix);\n    if (config->prefix) {\n        wcscpy_s(py3path, MAXPATHLEN, config->prefix);\n        if (py3path[0] && _Py_add_relfile(py3path, L\"DLLs\\\\\" PY3_DLLNAME, MAXPATHLEN) >= 0) {\n            hPython3 = LoadLibraryExW(py3path, NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);\n        }\n    }\n    return hPython3 != NULL;\n    #undef MAXPATHLEN\n}\n#endif /* Py_ENABLE_SHARED */\n\ndl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,\n                                              const char *shortname,\n                                              PyObject *pathname, FILE *fp)\n{\n    dl_funcptr p;\n    char funcname[258], *import_python;\n\n#ifdef Py_ENABLE_SHARED\n    _Py_CheckPython3();\n#endif /* Py_ENABLE_SHARED */\n\n    wchar_t *wpathname = PyUnicode_AsWideCharString(pathname, NULL);\n    if (wpathname == NULL)\n        return NULL;\n\n    PyOS_snprintf(funcname, sizeof(funcname), \"%.20s_%.200s\", prefix, shortname);\n\n    {\n        HINSTANCE hDLL = NULL;\n#ifdef MS_WINDOWS_DESKTOP\n        unsigned int old_mode;\n\n        /* Don't display a message box when Python can't load a DLL */\n        old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);\n#endif\n\n        /* bpo-36085: We use LoadLibraryEx with restricted search paths\n           to avoid DLL preloading attacks and enable use of the\n           AddDllDirectory function. We add SEARCH_DLL_LOAD_DIR to\n           ensure DLLs adjacent to the PYD are preferred. */\n        Py_BEGIN_ALLOW_THREADS\n        hDLL = LoadLibraryExW(wpathname, NULL,\n                              LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |\n                              LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);\n        Py_END_ALLOW_THREADS\n        PyMem_Free(wpathname);\n\n#ifdef MS_WINDOWS_DESKTOP\n        /* restore old error mode settings */\n        SetErrorMode(old_mode);\n#endif\n\n        if (hDLL==NULL){\n            PyObject *message;\n            unsigned int errorCode;\n\n            /* Get an error string from Win32 error code */\n            wchar_t theInfo[256]; /* Pointer to error text\n                                  from system */\n            int theLength; /* Length of error text */\n\n            errorCode = GetLastError();\n\n            theLength = FormatMessageW(\n                FORMAT_MESSAGE_FROM_SYSTEM |\n                FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */\n                NULL, /* message source */\n                errorCode, /* the message (error) ID */\n                MAKELANGID(LANG_NEUTRAL,\n                           SUBLANG_DEFAULT),\n                           /* Default language */\n                theInfo, /* the buffer */\n                sizeof(theInfo) / sizeof(wchar_t), /* size in wchars */\n                NULL); /* no additional format args. */\n\n            /* Problem: could not get the error message.\n               This should not happen if called correctly. */\n            if (theLength == 0) {\n                message = PyUnicode_FromFormat(\n                    \"DLL load failed with error code %u while importing %s\",\n                    errorCode, shortname);\n            } else {\n                /* For some reason a \\r\\n\n                   is appended to the text */\n                if (theLength >= 2 &&\n                    theInfo[theLength-2] == '\\r' &&\n                    theInfo[theLength-1] == '\\n') {\n                    theLength -= 2;\n                    theInfo[theLength] = '\\0';\n                }\n                message = PyUnicode_FromFormat(\n                    \"DLL load failed while importing %s: \", shortname);\n\n                PyUnicode_AppendAndDel(&message,\n                    PyUnicode_FromWideChar(\n                        theInfo,\n                        theLength));\n            }\n            if (message != NULL) {\n                PyObject *shortname_obj = PyUnicode_FromString(shortname);\n                PyErr_SetImportError(message, shortname_obj, pathname);\n                Py_XDECREF(shortname_obj);\n                Py_DECREF(message);\n            }\n            return NULL;\n        } else {\n            char buffer[256];\n\n            PyOS_snprintf(buffer, sizeof(buffer),\n#ifdef _DEBUG\n                          \"python%d%d_d.dll\",\n#else\n                          \"python%d%d.dll\",\n#endif\n                          PY_MAJOR_VERSION,PY_MINOR_VERSION);\n            import_python = GetPythonImport(hDLL);\n\n            if (import_python &&\n                _stricmp(buffer,import_python)) {\n                PyErr_Format(PyExc_ImportError,\n                             \"Module use of %.150s conflicts \"\n                             \"with this version of Python.\",\n                             import_python);\n                Py_BEGIN_ALLOW_THREADS\n                FreeLibrary(hDLL);\n                Py_END_ALLOW_THREADS\n                return NULL;\n            }\n        }\n        Py_BEGIN_ALLOW_THREADS\n        p = GetProcAddress(hDLL, funcname);\n        Py_END_ALLOW_THREADS\n    }\n\n    return p;\n}\n"
  },
  {
    "path": "Emscripten_Signal.c",
    "content": "// To enable signal handling, the embedder should:\n// 1. set Module.Py_EmscriptenSignalBuffer = some_shared_array_buffer;\n// 2. set the Py_EMSCRIPTEN_SIGNAL_HANDLING flag to 1 as follows:\n//    Module.HEAP8[Module._Py_EMSCRIPTEN_SIGNAL_HANDLING] = 1\n//\n// The address &Py_EMSCRIPTEN_SIGNAL_HANDLING is exported as\n// Module._Py_EMSCRIPTEN_SIGNAL_HANDLING.\n#include <emscripten.h>\n#include \"Python.h\"\n\nEM_JS(int, _Py_CheckEmscriptenSignals_Helper, (void), {\n    if (!Module.Py_EmscriptenSignalBuffer) {\n        return 0;\n    }\n    try {\n        let result = Module.Py_EmscriptenSignalBuffer[0];\n        Module.Py_EmscriptenSignalBuffer[0] = 0;\n        return result;\n    } catch(e) {\n#if !defined(NDEBUG)\n        console.warn(\"Error occurred while trying to read signal buffer:\", e);\n#endif\n        return 0;\n    }\n});\n\nEMSCRIPTEN_KEEPALIVE int Py_EMSCRIPTEN_SIGNAL_HANDLING = 0;\n\nvoid\n_Py_CheckEmscriptenSignals(void)\n{\n    if (!Py_EMSCRIPTEN_SIGNAL_HANDLING) {\n        return;\n    }\n    int signal = _Py_CheckEmscriptenSignals_Helper();\n    if (signal) {\n        PyErr_SetInterruptEx(signal);\n    }\n}\n\n\n#define PY_EMSCRIPTEN_SIGNAL_INTERVAL 50\nstatic int emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL;\n\nvoid\n_Py_CheckEmscriptenSignalsPeriodically(void)\n{\n    if (!Py_EMSCRIPTEN_SIGNAL_HANDLING) {\n        return;\n    }\n    emscripten_signal_clock--;\n    if (emscripten_signal_clock == 0) {\n        emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL;\n        _Py_CheckEmscriptenSignals();\n    }\n}\n"
  },
  {
    "path": "Errors.c",
    "content": "\n/* Error handling */\n\n#include \"Python.h\"\n#include \"pycore_call.h\"          // _PyObject_CallNoArgs()\n#include \"pycore_initconfig.h\"    // _PyStatus_ERR()\n#include \"pycore_pyerrors.h\"      // _PyErr_Format()\n#include \"pycore_pystate.h\"       // _PyThreadState_GET()\n#include \"pycore_structseq.h\"     // _PyStructSequence_FiniBuiltin()\n#include \"pycore_sysmodule.h\"     // _PySys_Audit()\n#include \"pycore_traceback.h\"     // _PyTraceBack_FromFrame()\n\n#include <ctype.h>\n#ifdef MS_WINDOWS\n#  include <windows.h>\n#  include <winbase.h>\n#  include <stdlib.h>             // _sys_nerr\n#endif\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Forward declarations */\nstatic PyObject *\n_PyErr_FormatV(PyThreadState *tstate, PyObject *exception,\n               const char *format, va_list vargs);\n\nvoid\n_PyErr_SetRaisedException(PyThreadState *tstate, PyObject *exc)\n{\n    PyObject *old_exc = tstate->current_exception;\n    tstate->current_exception = exc;\n    Py_XDECREF(old_exc);\n}\n\nstatic PyObject*\n_PyErr_CreateException(PyObject *exception_type, PyObject *value)\n{\n    PyObject *exc;\n\n    if (value == NULL || value == Py_None) {\n        exc = _PyObject_CallNoArgs(exception_type);\n    }\n    else if (PyTuple_Check(value)) {\n        exc = PyObject_Call(exception_type, value, NULL);\n    }\n    else {\n        exc = PyObject_CallOneArg(exception_type, value);\n    }\n\n    if (exc != NULL && !PyExceptionInstance_Check(exc)) {\n        PyErr_Format(PyExc_TypeError,\n                     \"calling %R should have returned an instance of \"\n                     \"BaseException, not %s\",\n                     exception_type, Py_TYPE(exc)->tp_name);\n        Py_CLEAR(exc);\n    }\n\n    return exc;\n}\n\nvoid\n_PyErr_Restore(PyThreadState *tstate, PyObject *type, PyObject *value,\n               PyObject *traceback)\n{\n    if (type == NULL) {\n        assert(value == NULL);\n        assert(traceback == NULL);\n        _PyErr_SetRaisedException(tstate, NULL);\n        return;\n    }\n    assert(PyExceptionClass_Check(type));\n    if (value != NULL && type == (PyObject *)Py_TYPE(value)) {\n        /* Already normalized */\n        assert(((PyBaseExceptionObject *)value)->traceback != Py_None);\n    }\n    else {\n        PyObject *exc = _PyErr_CreateException(type, value);\n        Py_XDECREF(value);\n        if (exc == NULL) {\n            Py_DECREF(type);\n            Py_XDECREF(traceback);\n            return;\n        }\n        value = exc;\n    }\n    assert(PyExceptionInstance_Check(value));\n    if (traceback != NULL && !PyTraceBack_Check(traceback)) {\n        if (traceback == Py_None) {\n            Py_DECREF(Py_None);\n            traceback = NULL;\n        }\n        else {\n            PyErr_SetString(PyExc_TypeError, \"traceback must be a Traceback or None\");\n            Py_XDECREF(value);\n            Py_DECREF(type);\n            Py_XDECREF(traceback);\n            return;\n        }\n    }\n    PyObject *old_traceback = ((PyBaseExceptionObject *)value)->traceback;\n    ((PyBaseExceptionObject *)value)->traceback = traceback;\n    Py_XDECREF(old_traceback);\n    _PyErr_SetRaisedException(tstate, value);\n    Py_DECREF(type);\n}\n\nvoid\nPyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_Restore(tstate, type, value, traceback);\n}\n\nvoid\nPyErr_SetRaisedException(PyObject *exc)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_SetRaisedException(tstate, exc);\n}\n\n_PyErr_StackItem *\n_PyErr_GetTopmostException(PyThreadState *tstate)\n{\n    _PyErr_StackItem *exc_info = tstate->exc_info;\n    assert(exc_info);\n\n    while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) &&\n           exc_info->previous_item != NULL)\n    {\n        exc_info = exc_info->previous_item;\n    }\n    return exc_info;\n}\n\nstatic PyObject *\nget_normalization_failure_note(PyThreadState *tstate, PyObject *exception, PyObject *value)\n{\n    PyObject *args = PyObject_Repr(value);\n    if (args == NULL) {\n        _PyErr_Clear(tstate);\n        args = PyUnicode_FromFormat(\"<unknown>\");\n    }\n    PyObject *note;\n    const char *tpname = ((PyTypeObject*)exception)->tp_name;\n    if (args == NULL) {\n        _PyErr_Clear(tstate);\n        note = PyUnicode_FromFormat(\"Normalization failed: type=%s\", tpname);\n    }\n    else {\n        note = PyUnicode_FromFormat(\"Normalization failed: type=%s args=%S\",\n                                    tpname, args);\n        Py_DECREF(args);\n    }\n    return note;\n}\n\nvoid\n_PyErr_SetObject(PyThreadState *tstate, PyObject *exception, PyObject *value)\n{\n    PyObject *exc_value;\n    PyObject *tb = NULL;\n\n    if (exception != NULL &&\n        !PyExceptionClass_Check(exception)) {\n        _PyErr_Format(tstate, PyExc_SystemError,\n                      \"_PyErr_SetObject: \"\n                      \"exception %R is not a BaseException subclass\",\n                      exception);\n        return;\n    }\n    /* Normalize the exception */\n    int is_subclass = 0;\n    if (value != NULL && PyExceptionInstance_Check(value)) {\n        is_subclass = PyObject_IsSubclass((PyObject *)Py_TYPE(value), exception);\n        if (is_subclass < 0) {\n            return;\n        }\n    }\n    Py_XINCREF(value);\n    if (!is_subclass) {\n        /* We must normalize the value right now */\n\n        /* Issue #23571: functions must not be called with an\n            exception set */\n        _PyErr_Clear(tstate);\n\n        PyObject *fixed_value = _PyErr_CreateException(exception, value);\n        if (fixed_value == NULL) {\n            PyObject *exc = _PyErr_GetRaisedException(tstate);\n            assert(PyExceptionInstance_Check(exc));\n\n            PyObject *note = get_normalization_failure_note(tstate, exception, value);\n            Py_XDECREF(value);\n            if (note != NULL) {\n                /* ignore errors in _PyException_AddNote - they will be overwritten below */\n                _PyException_AddNote(exc, note);\n                Py_DECREF(note);\n            }\n            _PyErr_SetRaisedException(tstate, exc);\n            return;\n        }\n        Py_XSETREF(value, fixed_value);\n    }\n\n    exc_value = _PyErr_GetTopmostException(tstate)->exc_value;\n    if (exc_value != NULL && exc_value != Py_None) {\n        /* Implicit exception chaining */\n        Py_INCREF(exc_value);\n        /* Avoid creating new reference cycles through the\n           context chain, while taking care not to hang on\n           pre-existing ones.\n           This is O(chain length) but context chains are\n           usually very short. Sensitive readers may try\n           to inline the call to PyException_GetContext. */\n        if (exc_value != value) {\n            PyObject *o = exc_value, *context;\n            PyObject *slow_o = o;  /* Floyd's cycle detection algo */\n            int slow_update_toggle = 0;\n            while ((context = PyException_GetContext(o))) {\n                Py_DECREF(context);\n                if (context == value) {\n                    PyException_SetContext(o, NULL);\n                    break;\n                }\n                o = context;\n                if (o == slow_o) {\n                    /* pre-existing cycle - all exceptions on the\n                       path were visited and checked.  */\n                    break;\n                }\n                if (slow_update_toggle) {\n                    slow_o = PyException_GetContext(slow_o);\n                    Py_DECREF(slow_o);\n                }\n                slow_update_toggle = !slow_update_toggle;\n            }\n            PyException_SetContext(value, exc_value);\n        }\n        else {\n            Py_DECREF(exc_value);\n        }\n    }\n    assert(value != NULL);\n    if (PyExceptionInstance_Check(value))\n        tb = PyException_GetTraceback(value);\n    _PyErr_Restore(tstate, Py_NewRef(Py_TYPE(value)), value, tb);\n}\n\nvoid\nPyErr_SetObject(PyObject *exception, PyObject *value)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_SetObject(tstate, exception, value);\n}\n\n/* Set a key error with the specified argument, wrapping it in a\n * tuple automatically so that tuple keys are not unpacked as the\n * exception arguments. */\nvoid\n_PyErr_SetKeyError(PyObject *arg)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *tup = PyTuple_Pack(1, arg);\n    if (!tup) {\n        /* caller will expect error to be set anyway */\n        return;\n    }\n    _PyErr_SetObject(tstate, PyExc_KeyError, tup);\n    Py_DECREF(tup);\n}\n\nvoid\n_PyErr_SetNone(PyThreadState *tstate, PyObject *exception)\n{\n    _PyErr_SetObject(tstate, exception, (PyObject *)NULL);\n}\n\n\nvoid\nPyErr_SetNone(PyObject *exception)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_SetNone(tstate, exception);\n}\n\n\nvoid\n_PyErr_SetString(PyThreadState *tstate, PyObject *exception,\n                 const char *string)\n{\n    PyObject *value = PyUnicode_FromString(string);\n    _PyErr_SetObject(tstate, exception, value);\n    Py_XDECREF(value);\n}\n\nvoid\nPyErr_SetString(PyObject *exception, const char *string)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_SetString(tstate, exception, string);\n}\n\n\nPyObject* _Py_HOT_FUNCTION\nPyErr_Occurred(void)\n{\n    /* The caller must hold the GIL. */\n    assert(PyGILState_Check());\n\n    PyThreadState *tstate = _PyThreadState_GET();\n    return _PyErr_Occurred(tstate);\n}\n\n\nint\nPyErr_GivenExceptionMatches(PyObject *err, PyObject *exc)\n{\n    if (err == NULL || exc == NULL) {\n        /* maybe caused by \"import exceptions\" that failed early on */\n        return 0;\n    }\n    if (PyTuple_Check(exc)) {\n        Py_ssize_t i, n;\n        n = PyTuple_Size(exc);\n        for (i = 0; i < n; i++) {\n            /* Test recursively */\n             if (PyErr_GivenExceptionMatches(\n                 err, PyTuple_GET_ITEM(exc, i)))\n             {\n                 return 1;\n             }\n        }\n        return 0;\n    }\n    /* err might be an instance, so check its class. */\n    if (PyExceptionInstance_Check(err))\n        err = PyExceptionInstance_Class(err);\n\n    if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) {\n        return PyType_IsSubtype((PyTypeObject *)err, (PyTypeObject *)exc);\n    }\n\n    return err == exc;\n}\n\n\nint\n_PyErr_ExceptionMatches(PyThreadState *tstate, PyObject *exc)\n{\n    return PyErr_GivenExceptionMatches(_PyErr_Occurred(tstate), exc);\n}\n\n\nint\nPyErr_ExceptionMatches(PyObject *exc)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    return _PyErr_ExceptionMatches(tstate, exc);\n}\n\n\n#ifndef Py_NORMALIZE_RECURSION_LIMIT\n#define Py_NORMALIZE_RECURSION_LIMIT 32\n#endif\n\n/* Used in many places to normalize a raised exception, including in\n   eval_code2(), do_raise(), and PyErr_Print()\n\n   XXX: should PyErr_NormalizeException() also call\n            PyException_SetTraceback() with the resulting value and tb?\n*/\nvoid\n_PyErr_NormalizeException(PyThreadState *tstate, PyObject **exc,\n                          PyObject **val, PyObject **tb)\n{\n    int recursion_depth = 0;\n    tstate->recursion_headroom++;\n    PyObject *type, *value, *initial_tb;\n\n  restart:\n    type = *exc;\n    if (type == NULL) {\n        /* There was no exception, so nothing to do. */\n        tstate->recursion_headroom--;\n        return;\n    }\n\n    value = *val;\n    /* If PyErr_SetNone() was used, the value will have been actually\n       set to NULL.\n    */\n    if (!value) {\n        value = Py_NewRef(Py_None);\n    }\n\n    /* Normalize the exception so that if the type is a class, the\n       value will be an instance.\n    */\n    if (PyExceptionClass_Check(type)) {\n        PyObject *inclass = NULL;\n        int is_subclass = 0;\n\n        if (PyExceptionInstance_Check(value)) {\n            inclass = PyExceptionInstance_Class(value);\n            is_subclass = PyObject_IsSubclass(inclass, type);\n            if (is_subclass < 0) {\n                goto error;\n            }\n        }\n\n        /* If the value was not an instance, or is not an instance\n           whose class is (or is derived from) type, then use the\n           value as an argument to instantiation of the type\n           class.\n        */\n        if (!is_subclass) {\n            PyObject *fixed_value = _PyErr_CreateException(type, value);\n            if (fixed_value == NULL) {\n                goto error;\n            }\n            Py_SETREF(value, fixed_value);\n        }\n        /* If the class of the instance doesn't exactly match the\n           class of the type, believe the instance.\n        */\n        else if (inclass != type) {\n            Py_SETREF(type, Py_NewRef(inclass));\n        }\n    }\n    *exc = type;\n    *val = value;\n    tstate->recursion_headroom--;\n    return;\n\n  error:\n    Py_DECREF(type);\n    Py_DECREF(value);\n    recursion_depth++;\n    if (recursion_depth == Py_NORMALIZE_RECURSION_LIMIT) {\n        _PyErr_SetString(tstate, PyExc_RecursionError,\n                         \"maximum recursion depth exceeded \"\n                         \"while normalizing an exception\");\n    }\n    /* If the new exception doesn't set a traceback and the old\n       exception had a traceback, use the old traceback for the\n       new exception.  It's better than nothing.\n    */\n    initial_tb = *tb;\n    _PyErr_Fetch(tstate, exc, val, tb);\n    assert(*exc != NULL);\n    if (initial_tb != NULL) {\n        if (*tb == NULL)\n            *tb = initial_tb;\n        else\n            Py_DECREF(initial_tb);\n    }\n    /* Abort when Py_NORMALIZE_RECURSION_LIMIT has been exceeded, and the\n       corresponding RecursionError could not be normalized, and the\n       MemoryError raised when normalize this RecursionError could not be\n       normalized. */\n    if (recursion_depth >= Py_NORMALIZE_RECURSION_LIMIT + 2) {\n        if (PyErr_GivenExceptionMatches(*exc, PyExc_MemoryError)) {\n            Py_FatalError(\"Cannot recover from MemoryErrors \"\n                          \"while normalizing exceptions.\");\n        }\n        else {\n            Py_FatalError(\"Cannot recover from the recursive normalization \"\n                          \"of an exception.\");\n        }\n    }\n    goto restart;\n}\n\n\nvoid\nPyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_NormalizeException(tstate, exc, val, tb);\n}\n\n\nPyObject *\n_PyErr_GetRaisedException(PyThreadState *tstate) {\n    PyObject *exc = tstate->current_exception;\n    tstate->current_exception = NULL;\n    return exc;\n}\n\nPyObject *\nPyErr_GetRaisedException(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    return _PyErr_GetRaisedException(tstate);\n}\n\nvoid\n_PyErr_Fetch(PyThreadState *tstate, PyObject **p_type, PyObject **p_value,\n             PyObject **p_traceback)\n{\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    *p_value = exc;\n    if (exc == NULL) {\n        *p_type = NULL;\n        *p_traceback = NULL;\n    }\n    else {\n        *p_type = Py_NewRef(Py_TYPE(exc));\n        *p_traceback = Py_XNewRef(((PyBaseExceptionObject *)exc)->traceback);\n    }\n}\n\n\nvoid\nPyErr_Fetch(PyObject **p_type, PyObject **p_value, PyObject **p_traceback)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_Fetch(tstate, p_type, p_value, p_traceback);\n}\n\n\nvoid\n_PyErr_Clear(PyThreadState *tstate)\n{\n    _PyErr_Restore(tstate, NULL, NULL, NULL);\n}\n\n\nvoid\nPyErr_Clear(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_Clear(tstate);\n}\n\nstatic PyObject*\nget_exc_type(PyObject *exc_value)  /* returns a borrowed ref */\n{\n    if (exc_value == NULL || exc_value == Py_None) {\n        return Py_None;\n    }\n    else {\n        assert(PyExceptionInstance_Check(exc_value));\n        PyObject *type = PyExceptionInstance_Class(exc_value);\n        assert(type != NULL);\n        return type;\n    }\n}\n\nstatic PyObject*\nget_exc_traceback(PyObject *exc_value)  /* returns a borrowed ref */\n{\n    if (exc_value == NULL || exc_value == Py_None) {\n        return Py_None;\n    }\n    else {\n        assert(PyExceptionInstance_Check(exc_value));\n        PyObject *tb = PyException_GetTraceback(exc_value);\n        Py_XDECREF(tb);\n        return tb ? tb : Py_None;\n    }\n}\n\nvoid\n_PyErr_GetExcInfo(PyThreadState *tstate,\n                  PyObject **p_type, PyObject **p_value, PyObject **p_traceback)\n{\n    _PyErr_StackItem *exc_info = _PyErr_GetTopmostException(tstate);\n\n    *p_type = Py_XNewRef(get_exc_type(exc_info->exc_value));\n    *p_value = Py_XNewRef(exc_info->exc_value);\n    *p_traceback = Py_XNewRef(get_exc_traceback(exc_info->exc_value));\n}\n\nPyObject*\n_PyErr_GetHandledException(PyThreadState *tstate)\n{\n    _PyErr_StackItem *exc_info = _PyErr_GetTopmostException(tstate);\n    PyObject *exc = exc_info->exc_value;\n    if (exc == NULL || exc == Py_None) {\n        return NULL;\n    }\n    return Py_NewRef(exc);\n}\n\nPyObject*\nPyErr_GetHandledException(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    return _PyErr_GetHandledException(tstate);\n}\n\nvoid\n_PyErr_SetHandledException(PyThreadState *tstate, PyObject *exc)\n{\n    Py_XSETREF(tstate->exc_info->exc_value, Py_XNewRef(exc));\n}\n\nvoid\nPyErr_SetHandledException(PyObject *exc)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_SetHandledException(tstate, exc);\n}\n\nvoid\nPyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_GetExcInfo(tstate, p_type, p_value, p_traceback);\n}\n\nvoid\nPyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback)\n{\n    PyErr_SetHandledException(value);\n    Py_XDECREF(value);\n    /* These args are no longer used, but we still need to steal a ref */\n    Py_XDECREF(type);\n    Py_XDECREF(traceback);\n}\n\n\nPyObject*\n_PyErr_StackItemToExcInfoTuple(_PyErr_StackItem *err_info)\n{\n    PyObject *exc_value = err_info->exc_value;\n\n    assert(exc_value == NULL ||\n           exc_value == Py_None ||\n           PyExceptionInstance_Check(exc_value));\n\n    PyObject *exc_type = get_exc_type(exc_value);\n    PyObject *exc_traceback = get_exc_traceback(exc_value);\n\n    return Py_BuildValue(\n        \"(OOO)\",\n        exc_type ? exc_type : Py_None,\n        exc_value ? exc_value : Py_None,\n        exc_traceback ? exc_traceback : Py_None);\n}\n\n\n/* Like PyErr_Restore(), but if an exception is already set,\n   set the context associated with it.\n\n   The caller is responsible for ensuring that this call won't create\n   any cycles in the exception context chain. */\nvoid\n_PyErr_ChainExceptions(PyObject *typ, PyObject *val, PyObject *tb)\n{\n    if (typ == NULL)\n        return;\n\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    if (!PyExceptionClass_Check(typ)) {\n        _PyErr_Format(tstate, PyExc_SystemError,\n                      \"_PyErr_ChainExceptions: \"\n                      \"exception %R is not a BaseException subclass\",\n                      typ);\n        return;\n    }\n\n    if (_PyErr_Occurred(tstate)) {\n        _PyErr_NormalizeException(tstate, &typ, &val, &tb);\n        if (tb != NULL) {\n            PyException_SetTraceback(val, tb);\n            Py_DECREF(tb);\n        }\n        Py_DECREF(typ);\n        PyObject *exc2 = _PyErr_GetRaisedException(tstate);\n        PyException_SetContext(exc2, val);\n        _PyErr_SetRaisedException(tstate, exc2);\n    }\n    else {\n        _PyErr_Restore(tstate, typ, val, tb);\n    }\n}\n\n/* Like PyErr_SetRaisedException(), but if an exception is already set,\n   set the context associated with it.\n\n   The caller is responsible for ensuring that this call won't create\n   any cycles in the exception context chain. */\nvoid\n_PyErr_ChainExceptions1(PyObject *exc)\n{\n    if (exc == NULL) {\n        return;\n    }\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (_PyErr_Occurred(tstate)) {\n        PyObject *exc2 = _PyErr_GetRaisedException(tstate);\n        PyException_SetContext(exc2, exc);\n        _PyErr_SetRaisedException(tstate, exc2);\n    }\n    else {\n        _PyErr_SetRaisedException(tstate, exc);\n    }\n}\n\n/* If the current thread is handling an exception (exc_info is ), set this\n   exception as the context of the current raised exception.\n\n   This function can only be called when _PyErr_Occurred() is true.\n   Also, this function won't create any cycles in the exception context\n   chain to the extent that _PyErr_SetObject ensures this. */\nvoid\n_PyErr_ChainStackItem(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    assert(_PyErr_Occurred(tstate));\n\n    _PyErr_StackItem *exc_info = tstate->exc_info;\n    if (exc_info->exc_value == NULL || exc_info->exc_value == Py_None) {\n        return;\n    }\n\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n\n    /* _PyErr_SetObject sets the context from PyThreadState. */\n    _PyErr_SetObject(tstate, (PyObject *) Py_TYPE(exc), exc);\n    Py_DECREF(exc);  // since _PyErr_Occurred was true\n}\n\nstatic PyObject *\n_PyErr_FormatVFromCause(PyThreadState *tstate, PyObject *exception,\n                        const char *format, va_list vargs)\n{\n    assert(_PyErr_Occurred(tstate));\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    assert(!_PyErr_Occurred(tstate));\n    _PyErr_FormatV(tstate, exception, format, vargs);\n    PyObject *exc2 = _PyErr_GetRaisedException(tstate);\n    PyException_SetCause(exc2, Py_NewRef(exc));\n    PyException_SetContext(exc2, Py_NewRef(exc));\n    Py_DECREF(exc);\n    _PyErr_SetRaisedException(tstate, exc2);\n    return NULL;\n}\n\nPyObject *\n_PyErr_FormatFromCauseTstate(PyThreadState *tstate, PyObject *exception,\n                             const char *format, ...)\n{\n    va_list vargs;\n    va_start(vargs, format);\n    _PyErr_FormatVFromCause(tstate, exception, format, vargs);\n    va_end(vargs);\n    return NULL;\n}\n\nPyObject *\n_PyErr_FormatFromCause(PyObject *exception, const char *format, ...)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    va_list vargs;\n    va_start(vargs, format);\n    _PyErr_FormatVFromCause(tstate, exception, format, vargs);\n    va_end(vargs);\n    return NULL;\n}\n\n/* Convenience functions to set a type error exception and return 0 */\n\nint\nPyErr_BadArgument(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_SetString(tstate, PyExc_TypeError,\n                     \"bad argument type for built-in operation\");\n    return 0;\n}\n\nPyObject *\nPyErr_NoMemory(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    return _PyErr_NoMemory(tstate);\n}\n\nPyObject *\nPyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)\n{\n    return PyErr_SetFromErrnoWithFilenameObjects(exc, filenameObject, NULL);\n}\n\nPyObject *\nPyErr_SetFromErrnoWithFilenameObjects(PyObject *exc, PyObject *filenameObject, PyObject *filenameObject2)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *message;\n    PyObject *v, *args;\n    int i = errno;\n#ifdef MS_WINDOWS\n    WCHAR *s_buf = NULL;\n#endif /* Unix/Windows */\n\n#ifdef EINTR\n    if (i == EINTR && PyErr_CheckSignals())\n        return NULL;\n#endif\n\n#ifndef MS_WINDOWS\n    if (i != 0) {\n        const char *s = strerror(i);\n        message = PyUnicode_DecodeLocale(s, \"surrogateescape\");\n    }\n    else {\n        /* Sometimes errno didn't get set */\n        message = PyUnicode_FromString(\"Error\");\n    }\n#else\n    if (i == 0)\n        message = PyUnicode_FromString(\"Error\"); /* Sometimes errno didn't get set */\n    else\n    {\n        /* Note that the Win32 errors do not lineup with the\n           errno error.  So if the error is in the MSVC error\n           table, we use it, otherwise we assume it really _is_\n           a Win32 error code\n        */\n        if (i > 0 && i < _sys_nerr) {\n            message = PyUnicode_FromString(_sys_errlist[i]);\n        }\n        else {\n            int len = FormatMessageW(\n                FORMAT_MESSAGE_ALLOCATE_BUFFER |\n                FORMAT_MESSAGE_FROM_SYSTEM |\n                FORMAT_MESSAGE_IGNORE_INSERTS,\n                NULL,                   /* no message source */\n                i,\n                MAKELANGID(LANG_NEUTRAL,\n                           SUBLANG_DEFAULT),\n                           /* Default language */\n                (LPWSTR) &s_buf,\n                0,                      /* size not used */\n                NULL);                  /* no args */\n            if (len==0) {\n                /* Only ever seen this in out-of-mem\n                   situations */\n                s_buf = NULL;\n                message = PyUnicode_FromFormat(\"Windows Error 0x%x\", i);\n            } else {\n                /* remove trailing cr/lf and dots */\n                while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))\n                    s_buf[--len] = L'\\0';\n                message = PyUnicode_FromWideChar(s_buf, len);\n            }\n        }\n    }\n#endif /* Unix/Windows */\n\n    if (message == NULL)\n    {\n#ifdef MS_WINDOWS\n        LocalFree(s_buf);\n#endif\n        return NULL;\n    }\n\n    if (filenameObject != NULL) {\n        if (filenameObject2 != NULL)\n            args = Py_BuildValue(\"(iOOiO)\", i, message, filenameObject, 0, filenameObject2);\n        else\n            args = Py_BuildValue(\"(iOO)\", i, message, filenameObject);\n    } else {\n        assert(filenameObject2 == NULL);\n        args = Py_BuildValue(\"(iO)\", i, message);\n    }\n    Py_DECREF(message);\n\n    if (args != NULL) {\n        v = PyObject_Call(exc, args, NULL);\n        Py_DECREF(args);\n        if (v != NULL) {\n            _PyErr_SetObject(tstate, (PyObject *) Py_TYPE(v), v);\n            Py_DECREF(v);\n        }\n    }\n#ifdef MS_WINDOWS\n    LocalFree(s_buf);\n#endif\n    return NULL;\n}\n\nPyObject *\nPyErr_SetFromErrnoWithFilename(PyObject *exc, const char *filename)\n{\n    PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL;\n    PyObject *result = PyErr_SetFromErrnoWithFilenameObjects(exc, name, NULL);\n    Py_XDECREF(name);\n    return result;\n}\n\nPyObject *\nPyErr_SetFromErrno(PyObject *exc)\n{\n    return PyErr_SetFromErrnoWithFilenameObjects(exc, NULL, NULL);\n}\n\n#ifdef MS_WINDOWS\n/* Windows specific error code handling */\nPyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(\n    PyObject *exc,\n    int ierr,\n    PyObject *filenameObject)\n{\n    return PyErr_SetExcFromWindowsErrWithFilenameObjects(exc, ierr,\n        filenameObject, NULL);\n}\n\nPyObject *PyErr_SetExcFromWindowsErrWithFilenameObjects(\n    PyObject *exc,\n    int ierr,\n    PyObject *filenameObject,\n    PyObject *filenameObject2)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    int len;\n    WCHAR *s_buf = NULL; /* Free via LocalFree */\n    PyObject *message;\n    PyObject *args, *v;\n\n    DWORD err = (DWORD)ierr;\n    if (err==0) {\n        err = GetLastError();\n    }\n\n    len = FormatMessageW(\n        /* Error API error */\n        FORMAT_MESSAGE_ALLOCATE_BUFFER |\n        FORMAT_MESSAGE_FROM_SYSTEM |\n        FORMAT_MESSAGE_IGNORE_INSERTS,\n        NULL,           /* no message source */\n        err,\n        MAKELANGID(LANG_NEUTRAL,\n        SUBLANG_DEFAULT), /* Default language */\n        (LPWSTR) &s_buf,\n        0,              /* size not used */\n        NULL);          /* no args */\n    if (len==0) {\n        /* Only seen this in out of mem situations */\n        message = PyUnicode_FromFormat(\"Windows Error 0x%x\", err);\n        s_buf = NULL;\n    } else {\n        /* remove trailing cr/lf and dots */\n        while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.'))\n            s_buf[--len] = L'\\0';\n        message = PyUnicode_FromWideChar(s_buf, len);\n    }\n\n    if (message == NULL)\n    {\n        LocalFree(s_buf);\n        return NULL;\n    }\n\n    if (filenameObject == NULL) {\n        assert(filenameObject2 == NULL);\n        filenameObject = filenameObject2 = Py_None;\n    }\n    else if (filenameObject2 == NULL)\n        filenameObject2 = Py_None;\n    /* This is the constructor signature for OSError.\n       The POSIX translation will be figured out by the constructor. */\n    args = Py_BuildValue(\"(iOOiO)\", 0, message, filenameObject, err, filenameObject2);\n    Py_DECREF(message);\n\n    if (args != NULL) {\n        v = PyObject_Call(exc, args, NULL);\n        Py_DECREF(args);\n        if (v != NULL) {\n            _PyErr_SetObject(tstate, (PyObject *) Py_TYPE(v), v);\n            Py_DECREF(v);\n        }\n    }\n    LocalFree(s_buf);\n    return NULL;\n}\n\nPyObject *PyErr_SetExcFromWindowsErrWithFilename(\n    PyObject *exc,\n    int ierr,\n    const char *filename)\n{\n    PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL;\n    PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObjects(exc,\n                                                                 ierr,\n                                                                 name,\n                                                                 NULL);\n    Py_XDECREF(name);\n    return ret;\n}\n\nPyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr)\n{\n    return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL);\n}\n\nPyObject *PyErr_SetFromWindowsErr(int ierr)\n{\n    return PyErr_SetExcFromWindowsErrWithFilename(PyExc_OSError,\n                                                  ierr, NULL);\n}\n\nPyObject *PyErr_SetFromWindowsErrWithFilename(\n    int ierr,\n    const char *filename)\n{\n    PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL;\n    PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObjects(\n                                                  PyExc_OSError,\n                                                  ierr, name, NULL);\n    Py_XDECREF(name);\n    return result;\n}\n\n#endif /* MS_WINDOWS */\n\nstatic PyObject *\n_PyErr_SetImportErrorSubclassWithNameFrom(\n    PyObject *exception, PyObject *msg,\n    PyObject *name, PyObject *path, PyObject* from_name)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    int issubclass;\n    PyObject *kwargs, *error;\n\n    issubclass = PyObject_IsSubclass(exception, PyExc_ImportError);\n    if (issubclass < 0) {\n        return NULL;\n    }\n    else if (!issubclass) {\n        _PyErr_SetString(tstate, PyExc_TypeError,\n                         \"expected a subclass of ImportError\");\n        return NULL;\n    }\n\n    if (msg == NULL) {\n        _PyErr_SetString(tstate, PyExc_TypeError,\n                         \"expected a message argument\");\n        return NULL;\n    }\n\n    if (name == NULL) {\n        name = Py_None;\n    }\n    if (path == NULL) {\n        path = Py_None;\n    }\n    if (from_name == NULL) {\n        from_name = Py_None;\n    }\n\n\n    kwargs = PyDict_New();\n    if (kwargs == NULL) {\n        return NULL;\n    }\n    if (PyDict_SetItemString(kwargs, \"name\", name) < 0) {\n        goto done;\n    }\n    if (PyDict_SetItemString(kwargs, \"path\", path) < 0) {\n        goto done;\n    }\n    if (PyDict_SetItemString(kwargs, \"name_from\", from_name) < 0) {\n        goto done;\n    }\n\n    error = PyObject_VectorcallDict(exception, &msg, 1, kwargs);\n    if (error != NULL) {\n        _PyErr_SetObject(tstate, (PyObject *)Py_TYPE(error), error);\n        Py_DECREF(error);\n    }\n\ndone:\n    Py_DECREF(kwargs);\n    return NULL;\n}\n\n\nPyObject *\nPyErr_SetImportErrorSubclass(PyObject *exception, PyObject *msg,\n    PyObject *name, PyObject *path)\n{\n    return _PyErr_SetImportErrorSubclassWithNameFrom(exception, msg, name, path, NULL);\n}\n\nPyObject *\n_PyErr_SetImportErrorWithNameFrom(PyObject *msg, PyObject *name, PyObject *path, PyObject* from_name)\n{\n    return _PyErr_SetImportErrorSubclassWithNameFrom(PyExc_ImportError, msg, name, path, from_name);\n}\n\nPyObject *\nPyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path)\n{\n    return PyErr_SetImportErrorSubclass(PyExc_ImportError, msg, name, path);\n}\n\nvoid\n_PyErr_BadInternalCall(const char *filename, int lineno)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_Format(tstate, PyExc_SystemError,\n                  \"%s:%d: bad argument to internal function\",\n                  filename, lineno);\n}\n\n/* Remove the preprocessor macro for PyErr_BadInternalCall() so that we can\n   export the entry point for existing object code: */\n#undef PyErr_BadInternalCall\nvoid\nPyErr_BadInternalCall(void)\n{\n    assert(0 && \"bad argument to internal function\");\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_SetString(tstate, PyExc_SystemError,\n                     \"bad argument to internal function\");\n}\n#define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__)\n\n\nstatic PyObject *\n_PyErr_FormatV(PyThreadState *tstate, PyObject *exception,\n               const char *format, va_list vargs)\n{\n    PyObject* string;\n\n    /* Issue #23571: PyUnicode_FromFormatV() must not be called with an\n       exception set, it calls arbitrary Python code like PyObject_Repr() */\n    _PyErr_Clear(tstate);\n\n    string = PyUnicode_FromFormatV(format, vargs);\n\n    _PyErr_SetObject(tstate, exception, string);\n    Py_XDECREF(string);\n    return NULL;\n}\n\n\nPyObject *\nPyErr_FormatV(PyObject *exception, const char *format, va_list vargs)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    return _PyErr_FormatV(tstate, exception, format, vargs);\n}\n\n\nPyObject *\n_PyErr_Format(PyThreadState *tstate, PyObject *exception,\n              const char *format, ...)\n{\n    va_list vargs;\n    va_start(vargs, format);\n    _PyErr_FormatV(tstate, exception, format, vargs);\n    va_end(vargs);\n    return NULL;\n}\n\n\nPyObject *\nPyErr_Format(PyObject *exception, const char *format, ...)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    va_list vargs;\n    va_start(vargs, format);\n    _PyErr_FormatV(tstate, exception, format, vargs);\n    va_end(vargs);\n    return NULL;\n}\n\n\n/* Adds a note to the current exception (if any) */\nvoid\n_PyErr_FormatNote(const char *format, ...)\n{\n    PyObject *exc = PyErr_GetRaisedException();\n    if (exc == NULL) {\n        return;\n    }\n    va_list vargs;\n    va_start(vargs, format);\n    PyObject *note = PyUnicode_FromFormatV(format, vargs);\n    va_end(vargs);\n    if (note == NULL) {\n        goto error;\n    }\n    int res = _PyException_AddNote(exc, note);\n    Py_DECREF(note);\n    if (res < 0) {\n        goto error;\n    }\n    PyErr_SetRaisedException(exc);\n    return;\nerror:\n    _PyErr_ChainExceptions1(exc);\n}\n\n\nPyObject *\nPyErr_NewException(const char *name, PyObject *base, PyObject *dict)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *modulename = NULL;\n    PyObject *mydict = NULL;\n    PyObject *bases = NULL;\n    PyObject *result = NULL;\n\n    const char *dot = strrchr(name, '.');\n    if (dot == NULL) {\n        _PyErr_SetString(tstate, PyExc_SystemError,\n                         \"PyErr_NewException: name must be module.class\");\n        return NULL;\n    }\n    if (base == NULL) {\n        base = PyExc_Exception;\n    }\n    if (dict == NULL) {\n        dict = mydict = PyDict_New();\n        if (dict == NULL)\n            goto failure;\n    }\n\n    int r = PyDict_Contains(dict, &_Py_ID(__module__));\n    if (r < 0) {\n        goto failure;\n    }\n    if (r == 0) {\n        modulename = PyUnicode_FromStringAndSize(name,\n                                             (Py_ssize_t)(dot-name));\n        if (modulename == NULL)\n            goto failure;\n        if (PyDict_SetItem(dict, &_Py_ID(__module__), modulename) != 0)\n            goto failure;\n    }\n    if (PyTuple_Check(base)) {\n        bases = Py_NewRef(base);\n    } else {\n        bases = PyTuple_Pack(1, base);\n        if (bases == NULL)\n            goto failure;\n    }\n    /* Create a real class. */\n    result = PyObject_CallFunction((PyObject *)&PyType_Type, \"sOO\",\n                                   dot+1, bases, dict);\n  failure:\n    Py_XDECREF(bases);\n    Py_XDECREF(mydict);\n    Py_XDECREF(modulename);\n    return result;\n}\n\n\n/* Create an exception with docstring */\nPyObject *\nPyErr_NewExceptionWithDoc(const char *name, const char *doc,\n                          PyObject *base, PyObject *dict)\n{\n    int result;\n    PyObject *ret = NULL;\n    PyObject *mydict = NULL; /* points to the dict only if we create it */\n    PyObject *docobj;\n\n    if (dict == NULL) {\n        dict = mydict = PyDict_New();\n        if (dict == NULL) {\n            return NULL;\n        }\n    }\n\n    if (doc != NULL) {\n        docobj = PyUnicode_FromString(doc);\n        if (docobj == NULL)\n            goto failure;\n        result = PyDict_SetItemString(dict, \"__doc__\", docobj);\n        Py_DECREF(docobj);\n        if (result < 0)\n            goto failure;\n    }\n\n    ret = PyErr_NewException(name, base, dict);\n  failure:\n    Py_XDECREF(mydict);\n    return ret;\n}\n\n\nPyDoc_STRVAR(UnraisableHookArgs__doc__,\n\"UnraisableHookArgs\\n\\\n\\n\\\nType used to pass arguments to sys.unraisablehook.\");\n\nstatic PyTypeObject UnraisableHookArgsType;\n\nstatic PyStructSequence_Field UnraisableHookArgs_fields[] = {\n    {\"exc_type\", \"Exception type\"},\n    {\"exc_value\", \"Exception value\"},\n    {\"exc_traceback\", \"Exception traceback\"},\n    {\"err_msg\", \"Error message\"},\n    {\"object\", \"Object causing the exception\"},\n    {0}\n};\n\nstatic PyStructSequence_Desc UnraisableHookArgs_desc = {\n    .name = \"UnraisableHookArgs\",\n    .doc = UnraisableHookArgs__doc__,\n    .fields = UnraisableHookArgs_fields,\n    .n_in_sequence = 5\n};\n\n\nPyStatus\n_PyErr_InitTypes(PyInterpreterState *interp)\n{\n    if (_PyStructSequence_InitBuiltin(interp, &UnraisableHookArgsType,\n                                      &UnraisableHookArgs_desc) < 0)\n    {\n        return _PyStatus_ERR(\"failed to initialize UnraisableHookArgs type\");\n    }\n    return _PyStatus_OK();\n}\n\n\nvoid\n_PyErr_FiniTypes(PyInterpreterState *interp)\n{\n    _PyStructSequence_FiniBuiltin(interp, &UnraisableHookArgsType);\n}\n\n\nstatic PyObject *\nmake_unraisable_hook_args(PyThreadState *tstate, PyObject *exc_type,\n                          PyObject *exc_value, PyObject *exc_tb,\n                          PyObject *err_msg, PyObject *obj)\n{\n    PyObject *args = PyStructSequence_New(&UnraisableHookArgsType);\n    if (args == NULL) {\n        return NULL;\n    }\n\n    Py_ssize_t pos = 0;\n#define ADD_ITEM(exc_type) \\\n        do { \\\n            if (exc_type == NULL) { \\\n                exc_type = Py_None; \\\n            } \\\n            PyStructSequence_SET_ITEM(args, pos++, Py_NewRef(exc_type)); \\\n        } while (0)\n\n\n    ADD_ITEM(exc_type);\n    ADD_ITEM(exc_value);\n    ADD_ITEM(exc_tb);\n    ADD_ITEM(err_msg);\n    ADD_ITEM(obj);\n#undef ADD_ITEM\n\n    if (_PyErr_Occurred(tstate)) {\n        Py_DECREF(args);\n        return NULL;\n    }\n    return args;\n}\n\n\n\n/* Default implementation of sys.unraisablehook.\n\n   It can be called to log the exception of a custom sys.unraisablehook.\n\n   Do nothing if sys.stderr attribute doesn't exist or is set to None. */\nstatic int\nwrite_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type,\n                          PyObject *exc_value, PyObject *exc_tb,\n                          PyObject *err_msg, PyObject *obj, PyObject *file)\n{\n    if (obj != NULL && obj != Py_None) {\n        if (err_msg != NULL && err_msg != Py_None) {\n            if (PyFile_WriteObject(err_msg, file, Py_PRINT_RAW) < 0) {\n                return -1;\n            }\n            if (PyFile_WriteString(\": \", file) < 0) {\n                return -1;\n            }\n        }\n        else {\n            if (PyFile_WriteString(\"Exception ignored in: \", file) < 0) {\n                return -1;\n            }\n        }\n\n        if (PyFile_WriteObject(obj, file, 0) < 0) {\n            _PyErr_Clear(tstate);\n            if (PyFile_WriteString(\"<object repr() failed>\", file) < 0) {\n                return -1;\n            }\n        }\n        if (PyFile_WriteString(\"\\n\", file) < 0) {\n            return -1;\n        }\n    }\n    else if (err_msg != NULL && err_msg != Py_None) {\n        if (PyFile_WriteObject(err_msg, file, Py_PRINT_RAW) < 0) {\n            return -1;\n        }\n        if (PyFile_WriteString(\":\\n\", file) < 0) {\n            return -1;\n        }\n    }\n\n    if (exc_tb != NULL && exc_tb != Py_None) {\n        if (PyTraceBack_Print(exc_tb, file) < 0) {\n            /* continue even if writing the traceback failed */\n            _PyErr_Clear(tstate);\n        }\n    }\n\n    if (exc_type == NULL || exc_type == Py_None) {\n        return -1;\n    }\n\n    assert(PyExceptionClass_Check(exc_type));\n\n    PyObject *modulename = PyObject_GetAttr(exc_type, &_Py_ID(__module__));\n    if (modulename == NULL || !PyUnicode_Check(modulename)) {\n        Py_XDECREF(modulename);\n        _PyErr_Clear(tstate);\n        if (PyFile_WriteString(\"<unknown>\", file) < 0) {\n            return -1;\n        }\n    }\n    else {\n        if (!_PyUnicode_Equal(modulename, &_Py_ID(builtins)) &&\n            !_PyUnicode_Equal(modulename, &_Py_ID(__main__))) {\n            if (PyFile_WriteObject(modulename, file, Py_PRINT_RAW) < 0) {\n                Py_DECREF(modulename);\n                return -1;\n            }\n            Py_DECREF(modulename);\n            if (PyFile_WriteString(\".\", file) < 0) {\n                return -1;\n            }\n        }\n        else {\n            Py_DECREF(modulename);\n        }\n    }\n\n    PyObject *qualname = PyType_GetQualName((PyTypeObject *)exc_type);\n    if (qualname == NULL || !PyUnicode_Check(qualname)) {\n        Py_XDECREF(qualname);\n        _PyErr_Clear(tstate);\n        if (PyFile_WriteString(\"<unknown>\", file) < 0) {\n            return -1;\n        }\n    }\n    else {\n        if (PyFile_WriteObject(qualname, file, Py_PRINT_RAW) < 0) {\n            Py_DECREF(qualname);\n            return -1;\n        }\n        Py_DECREF(qualname);\n    }\n\n    if (exc_value && exc_value != Py_None) {\n        if (PyFile_WriteString(\": \", file) < 0) {\n            return -1;\n        }\n        if (PyFile_WriteObject(exc_value, file, Py_PRINT_RAW) < 0) {\n            _PyErr_Clear(tstate);\n            if (PyFile_WriteString(\"<exception str() failed>\", file) < 0) {\n                return -1;\n            }\n        }\n    }\n\n    if (PyFile_WriteString(\"\\n\", file) < 0) {\n        return -1;\n    }\n\n    /* Explicitly call file.flush() */\n    PyObject *res = _PyObject_CallMethodNoArgs(file, &_Py_ID(flush));\n    if (!res) {\n        return -1;\n    }\n    Py_DECREF(res);\n\n    return 0;\n}\n\n\nstatic int\nwrite_unraisable_exc(PyThreadState *tstate, PyObject *exc_type,\n                     PyObject *exc_value, PyObject *exc_tb, PyObject *err_msg,\n                     PyObject *obj)\n{\n    PyObject *file = _PySys_GetAttr(tstate, &_Py_ID(stderr));\n    if (file == NULL || file == Py_None) {\n        return 0;\n    }\n\n    /* Hold a strong reference to ensure that sys.stderr doesn't go away\n       while we use it */\n    Py_INCREF(file);\n    int res = write_unraisable_exc_file(tstate, exc_type, exc_value, exc_tb,\n                                        err_msg, obj, file);\n    Py_DECREF(file);\n\n    return res;\n}\n\n\nPyObject*\n_PyErr_WriteUnraisableDefaultHook(PyObject *args)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    if (!Py_IS_TYPE(args, &UnraisableHookArgsType)) {\n        _PyErr_SetString(tstate, PyExc_TypeError,\n                         \"sys.unraisablehook argument type \"\n                         \"must be UnraisableHookArgs\");\n        return NULL;\n    }\n\n    /* Borrowed references */\n    PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);\n    PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);\n    PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);\n    PyObject *err_msg = PyStructSequence_GET_ITEM(args, 3);\n    PyObject *obj = PyStructSequence_GET_ITEM(args, 4);\n\n    if (write_unraisable_exc(tstate, exc_type, exc_value, exc_tb, err_msg, obj) < 0) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\n\n/* Call sys.unraisablehook().\n\n   This function can be used when an exception has occurred but there is no way\n   for Python to handle it. For example, when a destructor raises an exception\n   or during garbage collection (gc.collect()).\n\n   If err_msg_str is non-NULL, the error message is formatted as:\n   \"Exception ignored %s\" % err_msg_str. Otherwise, use \"Exception ignored in\"\n   error message.\n\n   An exception must be set when calling this function. */\nvoid\n_PyErr_WriteUnraisableMsg(const char *err_msg_str, PyObject *obj)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _Py_EnsureTstateNotNULL(tstate);\n\n    PyObject *err_msg = NULL;\n    PyObject *exc_type, *exc_value, *exc_tb;\n    _PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);\n\n    assert(exc_type != NULL);\n\n    if (exc_type == NULL) {\n        /* sys.unraisablehook requires that at least exc_type is set */\n        goto default_hook;\n    }\n\n    if (exc_tb == NULL) {\n        PyFrameObject *frame = PyThreadState_GetFrame(tstate);\n        if (frame != NULL) {\n            exc_tb = _PyTraceBack_FromFrame(NULL, frame);\n            if (exc_tb == NULL) {\n                _PyErr_Clear(tstate);\n            }\n            Py_DECREF(frame);\n        }\n    }\n\n    _PyErr_NormalizeException(tstate, &exc_type, &exc_value, &exc_tb);\n\n    if (exc_tb != NULL && exc_tb != Py_None && PyTraceBack_Check(exc_tb)) {\n        if (PyException_SetTraceback(exc_value, exc_tb) < 0) {\n            _PyErr_Clear(tstate);\n        }\n    }\n\n    if (err_msg_str != NULL) {\n        err_msg = PyUnicode_FromFormat(\"Exception ignored %s\", err_msg_str);\n        if (err_msg == NULL) {\n            PyErr_Clear();\n        }\n    }\n\n    PyObject *hook_args = make_unraisable_hook_args(\n        tstate, exc_type, exc_value, exc_tb, err_msg, obj);\n    if (hook_args == NULL) {\n        err_msg_str = (\"Exception ignored on building \"\n                       \"sys.unraisablehook arguments\");\n        goto error;\n    }\n\n    PyObject *hook = _PySys_GetAttr(tstate, &_Py_ID(unraisablehook));\n    if (hook == NULL) {\n        Py_DECREF(hook_args);\n        goto default_hook;\n    }\n\n    if (_PySys_Audit(tstate, \"sys.unraisablehook\", \"OO\", hook, hook_args) < 0) {\n        Py_DECREF(hook_args);\n        err_msg_str = \"Exception ignored in audit hook\";\n        obj = NULL;\n        goto error;\n    }\n\n    if (hook == Py_None) {\n        Py_DECREF(hook_args);\n        goto default_hook;\n    }\n\n    PyObject *res = PyObject_CallOneArg(hook, hook_args);\n    Py_DECREF(hook_args);\n    if (res != NULL) {\n        Py_DECREF(res);\n        goto done;\n    }\n\n    /* sys.unraisablehook failed: log its error using default hook */\n    obj = hook;\n    err_msg_str = NULL;\n\nerror:\n    /* err_msg_str and obj have been updated and we have a new exception */\n    Py_XSETREF(err_msg, PyUnicode_FromString(err_msg_str ?\n        err_msg_str : \"Exception ignored in sys.unraisablehook\"));\n    Py_XDECREF(exc_type);\n    Py_XDECREF(exc_value);\n    Py_XDECREF(exc_tb);\n    _PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);\n\ndefault_hook:\n    /* Call the default unraisable hook (ignore failure) */\n    (void)write_unraisable_exc(tstate, exc_type, exc_value, exc_tb,\n                               err_msg, obj);\n\ndone:\n    Py_XDECREF(exc_type);\n    Py_XDECREF(exc_value);\n    Py_XDECREF(exc_tb);\n    Py_XDECREF(err_msg);\n    _PyErr_Clear(tstate); /* Just in case */\n}\n\n\nvoid\nPyErr_WriteUnraisable(PyObject *obj)\n{\n    _PyErr_WriteUnraisableMsg(NULL, obj);\n}\n\n\nvoid\nPyErr_SyntaxLocation(const char *filename, int lineno)\n{\n    PyErr_SyntaxLocationEx(filename, lineno, -1);\n}\n\n\n/* Set file and line information for the current exception.\n   If the exception is not a SyntaxError, also sets additional attributes\n   to make printing of exceptions believe it is a syntax error. */\n\nstatic void\nPyErr_SyntaxLocationObjectEx(PyObject *filename, int lineno, int col_offset,\n                             int end_lineno, int end_col_offset)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    /* add attributes for the line number and filename for the error */\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    /* XXX check that it is, indeed, a syntax error. It might not\n     * be, though. */\n    PyObject *tmp = PyLong_FromLong(lineno);\n    if (tmp == NULL) {\n        _PyErr_Clear(tstate);\n    }\n    else {\n        if (PyObject_SetAttr(exc, &_Py_ID(lineno), tmp)) {\n            _PyErr_Clear(tstate);\n        }\n        Py_DECREF(tmp);\n    }\n    tmp = NULL;\n    if (col_offset >= 0) {\n        tmp = PyLong_FromLong(col_offset);\n        if (tmp == NULL) {\n            _PyErr_Clear(tstate);\n        }\n    }\n    if (PyObject_SetAttr(exc, &_Py_ID(offset), tmp ? tmp : Py_None)) {\n        _PyErr_Clear(tstate);\n    }\n    Py_XDECREF(tmp);\n\n    tmp = NULL;\n    if (end_lineno >= 0) {\n        tmp = PyLong_FromLong(end_lineno);\n        if (tmp == NULL) {\n            _PyErr_Clear(tstate);\n        }\n    }\n    if (PyObject_SetAttr(exc, &_Py_ID(end_lineno), tmp ? tmp : Py_None)) {\n        _PyErr_Clear(tstate);\n    }\n    Py_XDECREF(tmp);\n\n    tmp = NULL;\n    if (end_col_offset >= 0) {\n        tmp = PyLong_FromLong(end_col_offset);\n        if (tmp == NULL) {\n            _PyErr_Clear(tstate);\n        }\n    }\n    if (PyObject_SetAttr(exc, &_Py_ID(end_offset), tmp ? tmp : Py_None)) {\n        _PyErr_Clear(tstate);\n    }\n    Py_XDECREF(tmp);\n\n    tmp = NULL;\n    if (filename != NULL) {\n        if (PyObject_SetAttr(exc, &_Py_ID(filename), filename)) {\n            _PyErr_Clear(tstate);\n        }\n\n        tmp = PyErr_ProgramTextObject(filename, lineno);\n        if (tmp) {\n            if (PyObject_SetAttr(exc, &_Py_ID(text), tmp)) {\n                _PyErr_Clear(tstate);\n            }\n            Py_DECREF(tmp);\n        }\n        else {\n            _PyErr_Clear(tstate);\n        }\n    }\n    if ((PyObject *)Py_TYPE(exc) != PyExc_SyntaxError) {\n        if (_PyObject_LookupAttr(exc, &_Py_ID(msg), &tmp) < 0) {\n            _PyErr_Clear(tstate);\n        }\n        else if (tmp) {\n            Py_DECREF(tmp);\n        }\n        else {\n            tmp = PyObject_Str(exc);\n            if (tmp) {\n                if (PyObject_SetAttr(exc, &_Py_ID(msg), tmp)) {\n                    _PyErr_Clear(tstate);\n                }\n                Py_DECREF(tmp);\n            }\n            else {\n                _PyErr_Clear(tstate);\n            }\n        }\n\n        if (_PyObject_LookupAttr(exc, &_Py_ID(print_file_and_line), &tmp) < 0) {\n            _PyErr_Clear(tstate);\n        }\n        else if (tmp) {\n            Py_DECREF(tmp);\n        }\n        else {\n            if (PyObject_SetAttr(exc, &_Py_ID(print_file_and_line), Py_None)) {\n                _PyErr_Clear(tstate);\n            }\n        }\n    }\n    _PyErr_SetRaisedException(tstate, exc);\n}\n\nvoid\nPyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset) {\n    PyErr_SyntaxLocationObjectEx(filename, lineno, col_offset, lineno, -1);\n}\n\nvoid\nPyErr_RangedSyntaxLocationObject(PyObject *filename, int lineno, int col_offset,\n                                 int end_lineno, int end_col_offset) {\n    PyErr_SyntaxLocationObjectEx(filename, lineno, col_offset, end_lineno, end_col_offset);\n}\n\nvoid\nPyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *fileobj;\n    if (filename != NULL) {\n        fileobj = PyUnicode_DecodeFSDefault(filename);\n        if (fileobj == NULL) {\n            _PyErr_Clear(tstate);\n        }\n    }\n    else {\n        fileobj = NULL;\n    }\n    PyErr_SyntaxLocationObject(fileobj, lineno, col_offset);\n    Py_XDECREF(fileobj);\n}\n\n/* Attempt to load the line of text that the exception refers to.  If it\n   fails, it will return NULL but will not set an exception.\n\n   XXX The functionality of this function is quite similar to the\n   functionality in tb_displayline() in traceback.c. */\n\nstatic PyObject *\nerr_programtext(PyThreadState *tstate, FILE *fp, int lineno, const char* encoding)\n{\n    int i;\n    char linebuf[1000];\n    if (fp == NULL) {\n        return NULL;\n    }\n\n    for (i = 0; i < lineno; i++) {\n        char *pLastChar = &linebuf[sizeof(linebuf) - 2];\n        do {\n            *pLastChar = '\\0';\n            if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf,\n                                         fp, NULL) == NULL) {\n                goto after_loop;\n            }\n            /* fgets read *something*; if it didn't get as\n               far as pLastChar, it must have found a newline\n               or hit the end of the file; if pLastChar is \\n,\n               it obviously found a newline; else we haven't\n               yet seen a newline, so must continue */\n        } while (*pLastChar != '\\0' && *pLastChar != '\\n');\n    }\n\nafter_loop:\n    fclose(fp);\n    if (i == lineno) {\n        PyObject *res;\n        if (encoding != NULL) {\n            res = PyUnicode_Decode(linebuf, strlen(linebuf), encoding, \"replace\");\n        } else {\n            res = PyUnicode_FromString(linebuf);\n        }\n        if (res == NULL)\n            _PyErr_Clear(tstate);\n        return res;\n    }\n    return NULL;\n}\n\nPyObject *\nPyErr_ProgramText(const char *filename, int lineno)\n{\n    if (filename == NULL) {\n        return NULL;\n    }\n\n    PyObject *filename_obj = PyUnicode_DecodeFSDefault(filename);\n    if (filename_obj == NULL) {\n        PyErr_Clear();\n        return NULL;\n    }\n    PyObject *res = PyErr_ProgramTextObject(filename_obj, lineno);\n    Py_DECREF(filename_obj);\n    return res;\n}\n\nPyObject *\n_PyErr_ProgramDecodedTextObject(PyObject *filename, int lineno, const char* encoding)\n{\n    if (filename == NULL || lineno <= 0) {\n        return NULL;\n    }\n\n    PyThreadState *tstate = _PyThreadState_GET();\n    FILE *fp = _Py_fopen_obj(filename, \"r\" PY_STDIOTEXTMODE);\n    if (fp == NULL) {\n        _PyErr_Clear(tstate);\n        return NULL;\n    }\n    return err_programtext(tstate, fp, lineno, encoding);\n}\n\nPyObject *\nPyErr_ProgramTextObject(PyObject *filename, int lineno)\n{\n    return _PyErr_ProgramDecodedTextObject(filename, lineno, NULL);\n}\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "Fileutils.c",
    "content": "#include \"Python.h\"\n#include \"pycore_fileutils.h\"     // fileutils definitions\n#include \"pycore_runtime.h\"       // _PyRuntime\n#include \"osdefs.h\"               // SEP\n#include <locale.h>\n#include <stdlib.h>               // mbstowcs()\n\n#ifdef MS_WINDOWS\n#  include <malloc.h>\n#  include <windows.h>\n#  include <winioctl.h>             // FILE_DEVICE_* constants\n#  include \"pycore_fileutils_windows.h\" // FILE_STAT_BASIC_INFORMATION\n#  if defined(MS_WINDOWS_GAMES) && !defined(MS_WINDOWS_DESKTOP)\n#    define PATHCCH_ALLOW_LONG_PATHS 0x01\n#  else\n#    include <pathcch.h>            // PathCchCombineEx\n#  endif\nextern int winerror_to_errno(int);\n#endif\n\n#ifdef HAVE_LANGINFO_H\n#include <langinfo.h>\n#endif\n\n#ifdef HAVE_SYS_IOCTL_H\n#include <sys/ioctl.h>\n#endif\n\n#ifdef HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION\n#include <iconv.h>\n#endif\n\n#ifdef HAVE_FCNTL_H\n#include <fcntl.h>\n#endif /* HAVE_FCNTL_H */\n\n#ifdef O_CLOEXEC\n/* Does open() support the O_CLOEXEC flag? Possible values:\n\n   -1: unknown\n    0: open() ignores O_CLOEXEC flag, ex: Linux kernel older than 2.6.23\n    1: open() supports O_CLOEXEC flag, close-on-exec is set\n\n   The flag is used by _Py_open(), _Py_open_noraise(), io.FileIO\n   and os.open(). */\nint _Py_open_cloexec_works = -1;\n#endif\n\n// The value must be the same in unicodeobject.c.\n#define MAX_UNICODE 0x10ffff\n\n// mbstowcs() and mbrtowc() errors\nstatic const size_t DECODE_ERROR = ((size_t)-1);\nstatic const size_t INCOMPLETE_CHARACTER = (size_t)-2;\n\n\nstatic int\nget_surrogateescape(_Py_error_handler errors, int *surrogateescape)\n{\n    switch (errors)\n    {\n    case _Py_ERROR_STRICT:\n        *surrogateescape = 0;\n        return 0;\n    case _Py_ERROR_SURROGATEESCAPE:\n        *surrogateescape = 1;\n        return 0;\n    default:\n        return -1;\n    }\n}\n\n\nPyObject *\n_Py_device_encoding(int fd)\n{\n    int valid;\n    Py_BEGIN_ALLOW_THREADS\n    _Py_BEGIN_SUPPRESS_IPH\n    valid = isatty(fd);\n    _Py_END_SUPPRESS_IPH\n    Py_END_ALLOW_THREADS\n    if (!valid)\n        Py_RETURN_NONE;\n\n#ifdef MS_WINDOWS\n#ifdef HAVE_WINDOWS_CONSOLE_IO\n    UINT cp;\n    if (fd == 0)\n        cp = GetConsoleCP();\n    else if (fd == 1 || fd == 2)\n        cp = GetConsoleOutputCP();\n    else\n        cp = 0;\n    /* GetConsoleCP() and GetConsoleOutputCP() return 0 if the application\n       has no console */\n    if (cp == 0) {\n        Py_RETURN_NONE;\n    }\n\n    return PyUnicode_FromFormat(\"cp%u\", (unsigned int)cp);\n#else\n    Py_RETURN_NONE;\n#endif /* HAVE_WINDOWS_CONSOLE_IO */\n#else\n    if (_PyRuntime.preconfig.utf8_mode) {\n        _Py_DECLARE_STR(utf_8, \"utf-8\");\n        return Py_NewRef(&_Py_STR(utf_8));\n    }\n    return _Py_GetLocaleEncodingObject();\n#endif\n}\n\n\nstatic int\nis_valid_wide_char(wchar_t ch)\n{\n#ifdef HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION\n    /* Oracle Solaris doesn't use Unicode code points as wchar_t encoding\n       for non-Unicode locales, which makes values higher than MAX_UNICODE\n       possibly valid. */\n    return 1;\n#endif\n    if (Py_UNICODE_IS_SURROGATE(ch)) {\n        // Reject lone surrogate characters\n        return 0;\n    }\n    if (ch > MAX_UNICODE) {\n        // bpo-35883: Reject characters outside [U+0000; U+10ffff] range.\n        // The glibc mbstowcs() UTF-8 decoder does not respect the RFC 3629,\n        // it creates characters outside the [U+0000; U+10ffff] range:\n        // https://sourceware.org/bugzilla/show_bug.cgi?id=2373\n        return 0;\n    }\n    return 1;\n}\n\n\nstatic size_t\n_Py_mbstowcs(wchar_t *dest, const char *src, size_t n)\n{\n    size_t count = mbstowcs(dest, src, n);\n    if (dest != NULL && count != DECODE_ERROR) {\n        for (size_t i=0; i < count; i++) {\n            wchar_t ch = dest[i];\n            if (!is_valid_wide_char(ch)) {\n                return DECODE_ERROR;\n            }\n        }\n    }\n    return count;\n}\n\n\n#ifdef HAVE_MBRTOWC\nstatic size_t\n_Py_mbrtowc(wchar_t *pwc, const char *str, size_t len, mbstate_t *pmbs)\n{\n    assert(pwc != NULL);\n    size_t count = mbrtowc(pwc, str, len, pmbs);\n    if (count != 0 && count != DECODE_ERROR && count != INCOMPLETE_CHARACTER) {\n        if (!is_valid_wide_char(*pwc)) {\n            return DECODE_ERROR;\n        }\n    }\n    return count;\n}\n#endif\n\n\n#if !defined(_Py_FORCE_UTF8_FS_ENCODING) && !defined(MS_WINDOWS)\n\n#define USE_FORCE_ASCII\n\nextern int _Py_normalize_encoding(const char *, char *, size_t);\n\n/* Workaround FreeBSD and OpenIndiana locale encoding issue with the C locale\n   and POSIX locale. nl_langinfo(CODESET) announces an alias of the\n   ASCII encoding, whereas mbstowcs() and wcstombs() functions use the\n   ISO-8859-1 encoding. The problem is that os.fsencode() and os.fsdecode() use\n   locale.getpreferredencoding() codec. For example, if command line arguments\n   are decoded by mbstowcs() and encoded back by os.fsencode(), we get a\n   UnicodeEncodeError instead of retrieving the original byte string.\n\n   The workaround is enabled if setlocale(LC_CTYPE, NULL) returns \"C\",\n   nl_langinfo(CODESET) announces \"ascii\" (or an alias to ASCII), and at least\n   one byte in range 0x80-0xff can be decoded from the locale encoding. The\n   workaround is also enabled on error, for example if getting the locale\n   failed.\n\n   On HP-UX with the C locale or the POSIX locale, nl_langinfo(CODESET)\n   announces \"roman8\" but mbstowcs() uses Latin1 in practice. Force also the\n   ASCII encoding in this case.\n\n   Values of force_ascii:\n\n       1: the workaround is used: Py_EncodeLocale() uses\n          encode_ascii_surrogateescape() and Py_DecodeLocale() uses\n          decode_ascii()\n       0: the workaround is not used: Py_EncodeLocale() uses wcstombs() and\n          Py_DecodeLocale() uses mbstowcs()\n      -1: unknown, need to call check_force_ascii() to get the value\n*/\n#define force_ascii (_PyRuntime.fileutils.force_ascii)\n\nstatic int\ncheck_force_ascii(void)\n{\n    char *loc = setlocale(LC_CTYPE, NULL);\n    if (loc == NULL) {\n        goto error;\n    }\n    if (strcmp(loc, \"C\") != 0 && strcmp(loc, \"POSIX\") != 0) {\n        /* the LC_CTYPE locale is different than C and POSIX */\n        return 0;\n    }\n\n#if defined(HAVE_LANGINFO_H) && defined(CODESET)\n    const char *codeset = nl_langinfo(CODESET);\n    if (!codeset || codeset[0] == '\\0') {\n        /* CODESET is not set or empty */\n        goto error;\n    }\n\n    char encoding[20];   /* longest name: \"iso_646.irv_1991\\0\" */\n    if (!_Py_normalize_encoding(codeset, encoding, sizeof(encoding))) {\n        goto error;\n    }\n\n#ifdef __hpux\n    if (strcmp(encoding, \"roman8\") == 0) {\n        unsigned char ch;\n        wchar_t wch;\n        size_t res;\n\n        ch = (unsigned char)0xA7;\n        res = _Py_mbstowcs(&wch, (char*)&ch, 1);\n        if (res != DECODE_ERROR && wch == L'\\xA7') {\n            /* On HP-UX with C locale or the POSIX locale,\n               nl_langinfo(CODESET) announces \"roman8\", whereas mbstowcs() uses\n               Latin1 encoding in practice. Force ASCII in this case.\n\n               Roman8 decodes 0xA7 to U+00CF. Latin1 decodes 0xA7 to U+00A7. */\n            return 1;\n        }\n    }\n#else\n    const char* ascii_aliases[] = {\n        \"ascii\",\n        /* Aliases from Lib/encodings/aliases.py */\n        \"646\",\n        \"ansi_x3.4_1968\",\n        \"ansi_x3.4_1986\",\n        \"ansi_x3_4_1968\",\n        \"cp367\",\n        \"csascii\",\n        \"ibm367\",\n        \"iso646_us\",\n        \"iso_646.irv_1991\",\n        \"iso_ir_6\",\n        \"us\",\n        \"us_ascii\",\n        NULL\n    };\n\n    int is_ascii = 0;\n    for (const char **alias=ascii_aliases; *alias != NULL; alias++) {\n        if (strcmp(encoding, *alias) == 0) {\n            is_ascii = 1;\n            break;\n        }\n    }\n    if (!is_ascii) {\n        /* nl_langinfo(CODESET) is not \"ascii\" or an alias of ASCII */\n        return 0;\n    }\n\n    for (unsigned int i=0x80; i<=0xff; i++) {\n        char ch[1];\n        wchar_t wch[1];\n        size_t res;\n\n        unsigned uch = (unsigned char)i;\n        ch[0] = (char)uch;\n        res = _Py_mbstowcs(wch, ch, 1);\n        if (res != DECODE_ERROR) {\n            /* decoding a non-ASCII character from the locale encoding succeed:\n               the locale encoding is not ASCII, force ASCII */\n            return 1;\n        }\n    }\n    /* None of the bytes in the range 0x80-0xff can be decoded from the locale\n       encoding: the locale encoding is really ASCII */\n#endif   /* !defined(__hpux) */\n    return 0;\n#else\n    /* nl_langinfo(CODESET) is not available: always force ASCII */\n    return 1;\n#endif   /* defined(HAVE_LANGINFO_H) && defined(CODESET) */\n\nerror:\n    /* if an error occurred, force the ASCII encoding */\n    return 1;\n}\n\n\nint\n_Py_GetForceASCII(void)\n{\n    if (force_ascii == -1) {\n        force_ascii = check_force_ascii();\n    }\n    return force_ascii;\n}\n\n\nvoid\n_Py_ResetForceASCII(void)\n{\n    force_ascii = -1;\n}\n\n\nstatic int\nencode_ascii(const wchar_t *text, char **str,\n             size_t *error_pos, const char **reason,\n             int raw_malloc, _Py_error_handler errors)\n{\n    char *result = NULL, *out;\n    size_t len, i;\n    wchar_t ch;\n\n    int surrogateescape;\n    if (get_surrogateescape(errors, &surrogateescape) < 0) {\n        return -3;\n    }\n\n    len = wcslen(text);\n\n    /* +1 for NULL byte */\n    if (raw_malloc) {\n        result = PyMem_RawMalloc(len + 1);\n    }\n    else {\n        result = PyMem_Malloc(len + 1);\n    }\n    if (result == NULL) {\n        return -1;\n    }\n\n    out = result;\n    for (i=0; i<len; i++) {\n        ch = text[i];\n\n        if (ch <= 0x7f) {\n            /* ASCII character */\n            *out++ = (char)ch;\n        }\n        else if (surrogateescape && 0xdc80 <= ch && ch <= 0xdcff) {\n            /* UTF-8b surrogate */\n            *out++ = (char)(ch - 0xdc00);\n        }\n        else {\n            if (raw_malloc) {\n                PyMem_RawFree(result);\n            }\n            else {\n                PyMem_Free(result);\n            }\n            if (error_pos != NULL) {\n                *error_pos = i;\n            }\n            if (reason) {\n                *reason = \"encoding error\";\n            }\n            return -2;\n        }\n    }\n    *out = '\\0';\n    *str = result;\n    return 0;\n}\n#else\nint\n_Py_GetForceASCII(void)\n{\n    return 0;\n}\n\nvoid\n_Py_ResetForceASCII(void)\n{\n    /* nothing to do */\n}\n#endif   /* !defined(_Py_FORCE_UTF8_FS_ENCODING) && !defined(MS_WINDOWS) */\n\n\n#if !defined(HAVE_MBRTOWC) || defined(USE_FORCE_ASCII)\nstatic int\ndecode_ascii(const char *arg, wchar_t **wstr, size_t *wlen,\n             const char **reason, _Py_error_handler errors)\n{\n    wchar_t *res;\n    unsigned char *in;\n    wchar_t *out;\n    size_t argsize = strlen(arg) + 1;\n\n    int surrogateescape;\n    if (get_surrogateescape(errors, &surrogateescape) < 0) {\n        return -3;\n    }\n\n    if (argsize > PY_SSIZE_T_MAX / sizeof(wchar_t)) {\n        return -1;\n    }\n    res = PyMem_RawMalloc(argsize * sizeof(wchar_t));\n    if (!res) {\n        return -1;\n    }\n\n    out = res;\n    for (in = (unsigned char*)arg; *in; in++) {\n        unsigned char ch = *in;\n        if (ch < 128) {\n            *out++ = ch;\n        }\n        else {\n            if (!surrogateescape) {\n                PyMem_RawFree(res);\n                if (wlen) {\n                    *wlen = in - (unsigned char*)arg;\n                }\n                if (reason) {\n                    *reason = \"decoding error\";\n                }\n                return -2;\n            }\n            *out++ = 0xdc00 + ch;\n        }\n    }\n    *out = 0;\n\n    if (wlen != NULL) {\n        *wlen = out - res;\n    }\n    *wstr = res;\n    return 0;\n}\n#endif   /* !HAVE_MBRTOWC */\n\nstatic int\ndecode_current_locale(const char* arg, wchar_t **wstr, size_t *wlen,\n                      const char **reason, _Py_error_handler errors)\n{\n    wchar_t *res;\n    size_t argsize;\n    size_t count;\n#ifdef HAVE_MBRTOWC\n    unsigned char *in;\n    wchar_t *out;\n    mbstate_t mbs;\n#endif\n\n    int surrogateescape;\n    if (get_surrogateescape(errors, &surrogateescape) < 0) {\n        return -3;\n    }\n\n#ifdef HAVE_BROKEN_MBSTOWCS\n    /* Some platforms have a broken implementation of\n     * mbstowcs which does not count the characters that\n     * would result from conversion.  Use an upper bound.\n     */\n    argsize = strlen(arg);\n#else\n    argsize = _Py_mbstowcs(NULL, arg, 0);\n#endif\n    if (argsize != DECODE_ERROR) {\n        if (argsize > PY_SSIZE_T_MAX / sizeof(wchar_t) - 1) {\n            return -1;\n        }\n        res = (wchar_t *)PyMem_RawMalloc((argsize + 1) * sizeof(wchar_t));\n        if (!res) {\n            return -1;\n        }\n\n        count = _Py_mbstowcs(res, arg, argsize + 1);\n        if (count != DECODE_ERROR) {\n            *wstr = res;\n            if (wlen != NULL) {\n                *wlen = count;\n            }\n            return 0;\n        }\n        PyMem_RawFree(res);\n    }\n\n    /* Conversion failed. Fall back to escaping with surrogateescape. */\n#ifdef HAVE_MBRTOWC\n    /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */\n\n    /* Overallocate; as multi-byte characters are in the argument, the\n       actual output could use less memory. */\n    argsize = strlen(arg) + 1;\n    if (argsize > PY_SSIZE_T_MAX / sizeof(wchar_t)) {\n        return -1;\n    }\n    res = (wchar_t*)PyMem_RawMalloc(argsize * sizeof(wchar_t));\n    if (!res) {\n        return -1;\n    }\n\n    in = (unsigned char*)arg;\n    out = res;\n    memset(&mbs, 0, sizeof mbs);\n    while (argsize) {\n        size_t converted = _Py_mbrtowc(out, (char*)in, argsize, &mbs);\n        if (converted == 0) {\n            /* Reached end of string; null char stored. */\n            break;\n        }\n\n        if (converted == INCOMPLETE_CHARACTER) {\n            /* Incomplete character. This should never happen,\n               since we provide everything that we have -\n               unless there is a bug in the C library, or I\n               misunderstood how mbrtowc works. */\n            goto decode_error;\n        }\n\n        if (converted == DECODE_ERROR) {\n            if (!surrogateescape) {\n                goto decode_error;\n            }\n\n            /* Decoding error. Escape as UTF-8b, and start over in the initial\n               shift state. */\n            *out++ = 0xdc00 + *in++;\n            argsize--;\n            memset(&mbs, 0, sizeof mbs);\n            continue;\n        }\n\n        // _Py_mbrtowc() reject lone surrogate characters\n        assert(!Py_UNICODE_IS_SURROGATE(*out));\n\n        /* successfully converted some bytes */\n        in += converted;\n        argsize -= converted;\n        out++;\n    }\n    if (wlen != NULL) {\n        *wlen = out - res;\n    }\n    *wstr = res;\n    return 0;\n\ndecode_error:\n    PyMem_RawFree(res);\n    if (wlen) {\n        *wlen = in - (unsigned char*)arg;\n    }\n    if (reason) {\n        *reason = \"decoding error\";\n    }\n    return -2;\n#else   /* HAVE_MBRTOWC */\n    /* Cannot use C locale for escaping; manually escape as if charset\n       is ASCII (i.e. escape all bytes > 128. This will still roundtrip\n       correctly in the locale's charset, which must be an ASCII superset. */\n    return decode_ascii(arg, wstr, wlen, reason, errors);\n#endif   /* HAVE_MBRTOWC */\n}\n\n\n/* Decode a byte string from the locale encoding.\n\n   Use the strict error handler if 'surrogateescape' is zero.  Use the\n   surrogateescape error handler if 'surrogateescape' is non-zero: undecodable\n   bytes are decoded as characters in range U+DC80..U+DCFF. If a byte sequence\n   can be decoded as a surrogate character, escape the bytes using the\n   surrogateescape error handler instead of decoding them.\n\n   On success, return 0 and write the newly allocated wide character string into\n   *wstr (use PyMem_RawFree() to free the memory). If wlen is not NULL, write\n   the number of wide characters excluding the null character into *wlen.\n\n   On memory allocation failure, return -1.\n\n   On decoding error, return -2. If wlen is not NULL, write the start of\n   invalid byte sequence in the input string into *wlen. If reason is not NULL,\n   write the decoding error message into *reason.\n\n   Return -3 if the error handler 'errors' is not supported.\n\n   Use the Py_EncodeLocaleEx() function to encode the character string back to\n   a byte string. */\nint\n_Py_DecodeLocaleEx(const char* arg, wchar_t **wstr, size_t *wlen,\n                   const char **reason,\n                   int current_locale, _Py_error_handler errors)\n{\n    if (current_locale) {\n#ifdef _Py_FORCE_UTF8_LOCALE\n        return _Py_DecodeUTF8Ex(arg, strlen(arg), wstr, wlen, reason,\n                                errors);\n#else\n        return decode_current_locale(arg, wstr, wlen, reason, errors);\n#endif\n    }\n\n#ifdef _Py_FORCE_UTF8_FS_ENCODING\n    return _Py_DecodeUTF8Ex(arg, strlen(arg), wstr, wlen, reason,\n                            errors);\n#else\n    int use_utf8 = (_PyRuntime.preconfig.utf8_mode >= 1);\n#ifdef MS_WINDOWS\n    use_utf8 |= (_PyRuntime.preconfig.legacy_windows_fs_encoding == 0);\n#endif\n    if (use_utf8) {\n        return _Py_DecodeUTF8Ex(arg, strlen(arg), wstr, wlen, reason,\n                                errors);\n    }\n\n#ifdef USE_FORCE_ASCII\n    if (force_ascii == -1) {\n        force_ascii = check_force_ascii();\n    }\n\n    if (force_ascii) {\n        /* force ASCII encoding to workaround mbstowcs() issue */\n        return decode_ascii(arg, wstr, wlen, reason, errors);\n    }\n#endif\n\n    return decode_current_locale(arg, wstr, wlen, reason, errors);\n#endif   /* !_Py_FORCE_UTF8_FS_ENCODING */\n}\n\n\n/* Decode a byte string from the locale encoding with the\n   surrogateescape error handler: undecodable bytes are decoded as characters\n   in range U+DC80..U+DCFF. If a byte sequence can be decoded as a surrogate\n   character, escape the bytes using the surrogateescape error handler instead\n   of decoding them.\n\n   Return a pointer to a newly allocated wide character string, use\n   PyMem_RawFree() to free the memory. If size is not NULL, write the number of\n   wide characters excluding the null character into *size\n\n   Return NULL on decoding error or memory allocation error. If *size* is not\n   NULL, *size is set to (size_t)-1 on memory error or set to (size_t)-2 on\n   decoding error.\n\n   Decoding errors should never happen, unless there is a bug in the C\n   library.\n\n   Use the Py_EncodeLocale() function to encode the character string back to a\n   byte string. */\nwchar_t*\nPy_DecodeLocale(const char* arg, size_t *wlen)\n{\n    wchar_t *wstr;\n    int res = _Py_DecodeLocaleEx(arg, &wstr, wlen,\n                                 NULL, 0,\n                                 _Py_ERROR_SURROGATEESCAPE);\n    if (res != 0) {\n        assert(res != -3);\n        if (wlen != NULL) {\n            *wlen = (size_t)res;\n        }\n        return NULL;\n    }\n    return wstr;\n}\n\n\nstatic int\nencode_current_locale(const wchar_t *text, char **str,\n                      size_t *error_pos, const char **reason,\n                      int raw_malloc, _Py_error_handler errors)\n{\n    const size_t len = wcslen(text);\n    char *result = NULL, *bytes = NULL;\n    size_t i, size, converted;\n    wchar_t c, buf[2];\n\n    int surrogateescape;\n    if (get_surrogateescape(errors, &surrogateescape) < 0) {\n        return -3;\n    }\n\n    /* The function works in two steps:\n       1. compute the length of the output buffer in bytes (size)\n       2. outputs the bytes */\n    size = 0;\n    buf[1] = 0;\n    while (1) {\n        for (i=0; i < len; i++) {\n            c = text[i];\n            if (c >= 0xdc80 && c <= 0xdcff) {\n                if (!surrogateescape) {\n                    goto encode_error;\n                }\n                /* UTF-8b surrogate */\n                if (bytes != NULL) {\n                    *bytes++ = c - 0xdc00;\n                    size--;\n                }\n                else {\n                    size++;\n                }\n                continue;\n            }\n            else {\n                buf[0] = c;\n                if (bytes != NULL) {\n                    converted = wcstombs(bytes, buf, size);\n                }\n                else {\n                    converted = wcstombs(NULL, buf, 0);\n                }\n                if (converted == DECODE_ERROR) {\n                    goto encode_error;\n                }\n                if (bytes != NULL) {\n                    bytes += converted;\n                    size -= converted;\n                }\n                else {\n                    size += converted;\n                }\n            }\n        }\n        if (result != NULL) {\n            *bytes = '\\0';\n            break;\n        }\n\n        size += 1; /* nul byte at the end */\n        if (raw_malloc) {\n            result = PyMem_RawMalloc(size);\n        }\n        else {\n            result = PyMem_Malloc(size);\n        }\n        if (result == NULL) {\n            return -1;\n        }\n        bytes = result;\n    }\n    *str = result;\n    return 0;\n\nencode_error:\n    if (raw_malloc) {\n        PyMem_RawFree(result);\n    }\n    else {\n        PyMem_Free(result);\n    }\n    if (error_pos != NULL) {\n        *error_pos = i;\n    }\n    if (reason) {\n        *reason = \"encoding error\";\n    }\n    return -2;\n}\n\n\n/* Encode a string to the locale encoding.\n\n   Parameters:\n\n   * raw_malloc: if non-zero, allocate memory using PyMem_RawMalloc() instead\n     of PyMem_Malloc().\n   * current_locale: if non-zero, use the current LC_CTYPE, otherwise use\n     Python filesystem encoding.\n   * errors: error handler like \"strict\" or \"surrogateescape\".\n\n   Return value:\n\n    0: success, *str is set to a newly allocated decoded string.\n   -1: memory allocation failure\n   -2: encoding error, set *error_pos and *reason (if set).\n   -3: the error handler 'errors' is not supported.\n */\nstatic int\nencode_locale_ex(const wchar_t *text, char **str, size_t *error_pos,\n                 const char **reason,\n                 int raw_malloc, int current_locale, _Py_error_handler errors)\n{\n    if (current_locale) {\n#ifdef _Py_FORCE_UTF8_LOCALE\n        return _Py_EncodeUTF8Ex(text, str, error_pos, reason,\n                                raw_malloc, errors);\n#else\n        return encode_current_locale(text, str, error_pos, reason,\n                                     raw_malloc, errors);\n#endif\n    }\n\n#ifdef _Py_FORCE_UTF8_FS_ENCODING\n    return _Py_EncodeUTF8Ex(text, str, error_pos, reason,\n                            raw_malloc, errors);\n#else\n    int use_utf8 = (_PyRuntime.preconfig.utf8_mode >= 1);\n#ifdef MS_WINDOWS\n    use_utf8 |= (_PyRuntime.preconfig.legacy_windows_fs_encoding == 0);\n#endif\n    if (use_utf8) {\n        return _Py_EncodeUTF8Ex(text, str, error_pos, reason,\n                                raw_malloc, errors);\n    }\n\n#ifdef USE_FORCE_ASCII\n    if (force_ascii == -1) {\n        force_ascii = check_force_ascii();\n    }\n\n    if (force_ascii) {\n        return encode_ascii(text, str, error_pos, reason,\n                            raw_malloc, errors);\n    }\n#endif\n\n    return encode_current_locale(text, str, error_pos, reason,\n                                 raw_malloc, errors);\n#endif   /* _Py_FORCE_UTF8_FS_ENCODING */\n}\n\nstatic char*\nencode_locale(const wchar_t *text, size_t *error_pos,\n              int raw_malloc, int current_locale)\n{\n    char *str;\n    int res = encode_locale_ex(text, &str, error_pos, NULL,\n                               raw_malloc, current_locale,\n                               _Py_ERROR_SURROGATEESCAPE);\n    if (res != -2 && error_pos) {\n        *error_pos = (size_t)-1;\n    }\n    if (res != 0) {\n        return NULL;\n    }\n    return str;\n}\n\n/* Encode a wide character string to the locale encoding with the\n   surrogateescape error handler: surrogate characters in the range\n   U+DC80..U+DCFF are converted to bytes 0x80..0xFF.\n\n   Return a pointer to a newly allocated byte string, use PyMem_Free() to free\n   the memory. Return NULL on encoding or memory allocation error.\n\n   If error_pos is not NULL, *error_pos is set to (size_t)-1 on success, or set\n   to the index of the invalid character on encoding error.\n\n   Use the Py_DecodeLocale() function to decode the bytes string back to a wide\n   character string. */\nchar*\nPy_EncodeLocale(const wchar_t *text, size_t *error_pos)\n{\n    return encode_locale(text, error_pos, 0, 0);\n}\n\n\n/* Similar to Py_EncodeLocale(), but result must be freed by PyMem_RawFree()\n   instead of PyMem_Free(). */\nchar*\n_Py_EncodeLocaleRaw(const wchar_t *text, size_t *error_pos)\n{\n    return encode_locale(text, error_pos, 1, 0);\n}\n\n\nint\n_Py_EncodeLocaleEx(const wchar_t *text, char **str,\n                   size_t *error_pos, const char **reason,\n                   int current_locale, _Py_error_handler errors)\n{\n    return encode_locale_ex(text, str, error_pos, reason, 1,\n                            current_locale, errors);\n}\n\n\n// Get the current locale encoding name:\n//\n// - Return \"utf-8\" if _Py_FORCE_UTF8_LOCALE macro is defined (ex: on Android)\n// - Return \"utf-8\" if the UTF-8 Mode is enabled\n// - On Windows, return the ANSI code page (ex: \"cp1250\")\n// - Return \"utf-8\" if nl_langinfo(CODESET) returns an empty string.\n// - Otherwise, return nl_langinfo(CODESET).\n//\n// Return NULL on memory allocation failure.\n//\n// See also config_get_locale_encoding()\nwchar_t*\n_Py_GetLocaleEncoding(void)\n{\n#ifdef _Py_FORCE_UTF8_LOCALE\n    // On Android langinfo.h and CODESET are missing,\n    // and UTF-8 is always used in mbstowcs() and wcstombs().\n    return _PyMem_RawWcsdup(L\"utf-8\");\n#else\n\n#ifdef MS_WINDOWS\n    wchar_t encoding[23];\n    unsigned int ansi_codepage = GetACP();\n    swprintf(encoding, Py_ARRAY_LENGTH(encoding), L\"cp%u\", ansi_codepage);\n    encoding[Py_ARRAY_LENGTH(encoding) - 1] = 0;\n    return _PyMem_RawWcsdup(encoding);\n#else\n    const char *encoding = nl_langinfo(CODESET);\n    if (!encoding || encoding[0] == '\\0') {\n        // Use UTF-8 if nl_langinfo() returns an empty string. It can happen on\n        // macOS if the LC_CTYPE locale is not supported.\n        return _PyMem_RawWcsdup(L\"utf-8\");\n    }\n\n    wchar_t *wstr;\n    int res = decode_current_locale(encoding, &wstr, NULL,\n                                    NULL, _Py_ERROR_SURROGATEESCAPE);\n    if (res < 0) {\n        return NULL;\n    }\n    return wstr;\n#endif  // !MS_WINDOWS\n\n#endif  // !_Py_FORCE_UTF8_LOCALE\n}\n\n\nPyObject *\n_Py_GetLocaleEncodingObject(void)\n{\n    wchar_t *encoding = _Py_GetLocaleEncoding();\n    if (encoding == NULL) {\n        PyErr_NoMemory();\n        return NULL;\n    }\n\n    PyObject *str = PyUnicode_FromWideChar(encoding, -1);\n    PyMem_RawFree(encoding);\n    return str;\n}\n\n#ifdef HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION\n\n/* Check whether current locale uses Unicode as internal wchar_t form. */\nint\n_Py_LocaleUsesNonUnicodeWchar(void)\n{\n    /* Oracle Solaris uses non-Unicode internal wchar_t form for\n       non-Unicode locales and hence needs conversion to UTF first. */\n    char* codeset = nl_langinfo(CODESET);\n    if (!codeset) {\n        return 0;\n    }\n    /* 646 refers to ISO/IEC 646 standard that corresponds to ASCII encoding */\n    return (strcmp(codeset, \"UTF-8\") != 0 && strcmp(codeset, \"646\") != 0);\n}\n\nstatic wchar_t *\n_Py_ConvertWCharForm(const wchar_t *source, Py_ssize_t size,\n                     const char *tocode, const char *fromcode)\n{\n    static_assert(sizeof(wchar_t) == 4, \"wchar_t must be 32-bit\");\n\n    /* Ensure we won't overflow the size. */\n    if (size > (PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(wchar_t))) {\n        PyErr_NoMemory();\n        return NULL;\n    }\n\n    /* the string doesn't have to be NULL terminated */\n    wchar_t* target = PyMem_Malloc(size * sizeof(wchar_t));\n    if (target == NULL) {\n        PyErr_NoMemory();\n        return NULL;\n    }\n\n    iconv_t cd = iconv_open(tocode, fromcode);\n    if (cd == (iconv_t)-1) {\n        PyErr_Format(PyExc_ValueError, \"iconv_open() failed\");\n        PyMem_Free(target);\n        return NULL;\n    }\n\n    char *inbuf = (char *) source;\n    char *outbuf = (char *) target;\n    size_t inbytesleft = sizeof(wchar_t) * size;\n    size_t outbytesleft = inbytesleft;\n\n    size_t ret = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);\n    if (ret == DECODE_ERROR) {\n        PyErr_Format(PyExc_ValueError, \"iconv() failed\");\n        PyMem_Free(target);\n        iconv_close(cd);\n        return NULL;\n    }\n\n    iconv_close(cd);\n    return target;\n}\n\n/* Convert a wide character string to the UCS-4 encoded string. This\n   is necessary on systems where internal form of wchar_t are not Unicode\n   code points (e.g. Oracle Solaris).\n\n   Return a pointer to a newly allocated string, use PyMem_Free() to free\n   the memory. Return NULL and raise exception on conversion or memory\n   allocation error. */\nwchar_t *\n_Py_DecodeNonUnicodeWchar(const wchar_t *native, Py_ssize_t size)\n{\n    return _Py_ConvertWCharForm(native, size, \"UCS-4-INTERNAL\", \"wchar_t\");\n}\n\n/* Convert a UCS-4 encoded string to native wide character string. This\n   is necessary on systems where internal form of wchar_t are not Unicode\n   code points (e.g. Oracle Solaris).\n\n   The conversion is done in place. This can be done because both wchar_t\n   and UCS-4 use 4-byte encoding, and one wchar_t symbol always correspond\n   to a single UCS-4 symbol and vice versa. (This is true for Oracle Solaris,\n   which is currently the only system using these functions; it doesn't have\n   to be for other systems).\n\n   Return 0 on success. Return -1 and raise exception on conversion\n   or memory allocation error. */\nint\n_Py_EncodeNonUnicodeWchar_InPlace(wchar_t *unicode, Py_ssize_t size)\n{\n    wchar_t* result = _Py_ConvertWCharForm(unicode, size, \"wchar_t\", \"UCS-4-INTERNAL\");\n    if (!result) {\n        return -1;\n    }\n    memcpy(unicode, result, size * sizeof(wchar_t));\n    PyMem_Free(result);\n    return 0;\n}\n#endif /* HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION */\n\n#ifdef MS_WINDOWS\nstatic __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */\n\nstatic void\nFILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out, int* nsec_out)\n{\n    /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */\n    /* Cannot simply cast and dereference in_ptr,\n       since it might not be aligned properly */\n    __int64 in;\n    memcpy(&in, in_ptr, sizeof(in));\n    *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */\n    *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, time_t);\n}\n\nstatic void\nLARGE_INTEGER_to_time_t_nsec(LARGE_INTEGER *in_ptr, time_t *time_out, int* nsec_out)\n{\n    *nsec_out = (int)(in_ptr->QuadPart % 10000000) * 100; /* FILETIME is in units of 100 nsec. */\n    *time_out = Py_SAFE_DOWNCAST((in_ptr->QuadPart / 10000000) - secs_between_epochs, __int64, time_t);\n}\n\nvoid\n_Py_time_t_to_FILE_TIME(time_t time_in, int nsec_in, FILETIME *out_ptr)\n{\n    /* XXX endianness */\n    __int64 out;\n    out = time_in + secs_between_epochs;\n    out = out * 10000000 + nsec_in / 100;\n    memcpy(out_ptr, &out, sizeof(out));\n}\n\n/* Below, we *know* that ugo+r is 0444 */\n#if _S_IREAD != 0400\n#error Unsupported C library\n#endif\nstatic int\nattributes_to_mode(DWORD attr)\n{\n    int m = 0;\n    if (attr & FILE_ATTRIBUTE_DIRECTORY)\n        m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */\n    else\n        m |= _S_IFREG;\n    if (attr & FILE_ATTRIBUTE_READONLY)\n        m |= 0444;\n    else\n        m |= 0666;\n    return m;\n}\n\n\ntypedef union {\n    FILE_ID_128 id;\n    struct {\n        uint64_t st_ino;\n        uint64_t st_ino_high;\n    };\n} id_128_to_ino;\n\n\nvoid\n_Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag,\n                           FILE_BASIC_INFO *basic_info, FILE_ID_INFO *id_info,\n                           struct _Py_stat_struct *result)\n{\n    memset(result, 0, sizeof(*result));\n    result->st_mode = attributes_to_mode(info->dwFileAttributes);\n    result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;\n    result->st_dev = id_info ? id_info->VolumeSerialNumber : info->dwVolumeSerialNumber;\n    result->st_rdev = 0;\n    /* st_ctime is deprecated, but we preserve the legacy value in our caller, not here */\n    if (basic_info) {\n        LARGE_INTEGER_to_time_t_nsec(&basic_info->CreationTime, &result->st_birthtime, &result->st_birthtime_nsec);\n        LARGE_INTEGER_to_time_t_nsec(&basic_info->ChangeTime, &result->st_ctime, &result->st_ctime_nsec);\n        LARGE_INTEGER_to_time_t_nsec(&basic_info->LastWriteTime, &result->st_mtime, &result->st_mtime_nsec);\n        LARGE_INTEGER_to_time_t_nsec(&basic_info->LastAccessTime, &result->st_atime, &result->st_atime_nsec);\n    } else {\n        FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_birthtime, &result->st_birthtime_nsec);\n        FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);\n        FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);\n    }\n    result->st_nlink = info->nNumberOfLinks;\n\n    if (id_info) {\n        id_128_to_ino file_id;\n        file_id.id = id_info->FileId;\n        result->st_ino = file_id.st_ino;\n        result->st_ino_high = file_id.st_ino_high;\n    }\n    if (!result->st_ino && !result->st_ino_high) {\n        /* should only occur for DirEntry_from_find_data, in which case the\n           index is likely to be zero anyway. */\n        result->st_ino = (((uint64_t)info->nFileIndexHigh) << 32) + info->nFileIndexLow;\n    }\n\n    /* bpo-37834: Only actual symlinks set the S_IFLNK flag. But lstat() will\n       open other name surrogate reparse points without traversing them. To\n       detect/handle these, check st_file_attributes and st_reparse_tag. */\n    result->st_reparse_tag = reparse_tag;\n    if (info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&\n        reparse_tag == IO_REPARSE_TAG_SYMLINK) {\n        /* set the bits that make this a symlink */\n        result->st_mode = (result->st_mode & ~S_IFMT) | S_IFLNK;\n    }\n    result->st_file_attributes = info->dwFileAttributes;\n}\n\nvoid\n_Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *info,\n                            struct _Py_stat_struct *result)\n{\n    memset(result, 0, sizeof(*result));\n    result->st_mode = attributes_to_mode(info->FileAttributes);\n    result->st_size = info->EndOfFile.QuadPart;\n    LARGE_INTEGER_to_time_t_nsec(&info->CreationTime, &result->st_birthtime, &result->st_birthtime_nsec);\n    LARGE_INTEGER_to_time_t_nsec(&info->ChangeTime, &result->st_ctime, &result->st_ctime_nsec);\n    LARGE_INTEGER_to_time_t_nsec(&info->LastWriteTime, &result->st_mtime, &result->st_mtime_nsec);\n    LARGE_INTEGER_to_time_t_nsec(&info->LastAccessTime, &result->st_atime, &result->st_atime_nsec);\n    result->st_nlink = info->NumberOfLinks;\n    result->st_dev = info->VolumeSerialNumber.QuadPart;\n    /* File systems with less than 128-bits zero pad into this field */\n    id_128_to_ino file_id;\n    file_id.id = info->FileId128;\n    result->st_ino = file_id.st_ino;\n    result->st_ino_high = file_id.st_ino_high;\n    /* bpo-37834: Only actual symlinks set the S_IFLNK flag. But lstat() will\n       open other name surrogate reparse points without traversing them. To\n       detect/handle these, check st_file_attributes and st_reparse_tag. */\n    result->st_reparse_tag = info->ReparseTag;\n    if (info->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&\n        info->ReparseTag == IO_REPARSE_TAG_SYMLINK) {\n        /* set the bits that make this a symlink */\n        result->st_mode = (result->st_mode & ~S_IFMT) | S_IFLNK;\n    }\n    result->st_file_attributes = info->FileAttributes;\n    switch (info->DeviceType) {\n    case FILE_DEVICE_DISK:\n    case FILE_DEVICE_VIRTUAL_DISK:\n    case FILE_DEVICE_DFS:\n    case FILE_DEVICE_CD_ROM:\n    case FILE_DEVICE_CONTROLLER:\n    case FILE_DEVICE_DATALINK:\n        break;\n    case FILE_DEVICE_DISK_FILE_SYSTEM:\n    case FILE_DEVICE_CD_ROM_FILE_SYSTEM:\n    case FILE_DEVICE_NETWORK_FILE_SYSTEM:\n        result->st_mode = (result->st_mode & ~S_IFMT) | 0x6000; /* _S_IFBLK */\n        break;\n    case FILE_DEVICE_CONSOLE:\n    case FILE_DEVICE_NULL:\n    case FILE_DEVICE_KEYBOARD:\n    case FILE_DEVICE_MODEM:\n    case FILE_DEVICE_MOUSE:\n    case FILE_DEVICE_PARALLEL_PORT:\n    case FILE_DEVICE_PRINTER:\n    case FILE_DEVICE_SCREEN:\n    case FILE_DEVICE_SERIAL_PORT:\n    case FILE_DEVICE_SOUND:\n        result->st_mode = (result->st_mode & ~S_IFMT) | _S_IFCHR;\n        break;\n    case FILE_DEVICE_NAMED_PIPE:\n        result->st_mode = (result->st_mode & ~S_IFMT) | _S_IFIFO;\n        break;\n    default:\n        if (info->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\n            result->st_mode = (result->st_mode & ~S_IFMT) | _S_IFDIR;\n        }\n        break;\n    }\n}\n\n#endif\n\n/* Return information about a file.\n\n   On POSIX, use fstat().\n\n   On Windows, use GetFileType() and GetFileInformationByHandle() which support\n   files larger than 2 GiB.  fstat() may fail with EOVERFLOW on files larger\n   than 2 GiB because the file size type is a signed 32-bit integer: see issue\n   #23152.\n\n   On Windows, set the last Windows error and return nonzero on error. On\n   POSIX, set errno and return nonzero on error. Fill status and return 0 on\n   success. */\nint\n_Py_fstat_noraise(int fd, struct _Py_stat_struct *status)\n{\n#ifdef MS_WINDOWS\n    BY_HANDLE_FILE_INFORMATION info;\n    FILE_BASIC_INFO basicInfo;\n    FILE_ID_INFO idInfo;\n    HANDLE h;\n    int type;\n\n    h = _Py_get_osfhandle_noraise(fd);\n\n    if (h == INVALID_HANDLE_VALUE) {\n        /* errno is already set by _get_osfhandle, but we also set\n           the Win32 error for callers who expect that */\n        SetLastError(ERROR_INVALID_HANDLE);\n        return -1;\n    }\n    memset(status, 0, sizeof(*status));\n\n    type = GetFileType(h);\n    if (type == FILE_TYPE_UNKNOWN) {\n        DWORD error = GetLastError();\n        if (error != 0) {\n            errno = winerror_to_errno(error);\n            return -1;\n        }\n        /* else: valid but unknown file */\n    }\n\n    if (type != FILE_TYPE_DISK) {\n        if (type == FILE_TYPE_CHAR)\n            status->st_mode = _S_IFCHR;\n        else if (type == FILE_TYPE_PIPE)\n            status->st_mode = _S_IFIFO;\n        return 0;\n    }\n\n    if (!GetFileInformationByHandle(h, &info) ||\n        !GetFileInformationByHandleEx(h, FileBasicInfo, &basicInfo, sizeof(basicInfo)) ||\n        !GetFileInformationByHandleEx(h, FileIdInfo, &idInfo, sizeof(idInfo))) {\n        /* The Win32 error is already set, but we also set errno for\n           callers who expect it */\n        errno = winerror_to_errno(GetLastError());\n        return -1;\n    }\n\n    _Py_attribute_data_to_stat(&info, 0, &basicInfo, &idInfo, status);\n    return 0;\n#else\n    return fstat(fd, status);\n#endif\n}\n\n/* Return information about a file.\n\n   On POSIX, use fstat().\n\n   On Windows, use GetFileType() and GetFileInformationByHandle() which support\n   files larger than 2 GiB.  fstat() may fail with EOVERFLOW on files larger\n   than 2 GiB because the file size type is a signed 32-bit integer: see issue\n   #23152.\n\n   Raise an exception and return -1 on error. On Windows, set the last Windows\n   error on error. On POSIX, set errno on error. Fill status and return 0 on\n   success.\n\n   Release the GIL to call GetFileType() and GetFileInformationByHandle(), or\n   to call fstat(). The caller must hold the GIL. */\nint\n_Py_fstat(int fd, struct _Py_stat_struct *status)\n{\n    int res;\n\n    assert(PyGILState_Check());\n\n    Py_BEGIN_ALLOW_THREADS\n    res = _Py_fstat_noraise(fd, status);\n    Py_END_ALLOW_THREADS\n\n    if (res != 0) {\n#ifdef MS_WINDOWS\n        PyErr_SetFromWindowsErr(0);\n#else\n        PyErr_SetFromErrno(PyExc_OSError);\n#endif\n        return -1;\n    }\n    return 0;\n}\n\n/* Like _Py_stat() but with a raw filename. */\nint\n_Py_wstat(const wchar_t* path, struct stat *buf)\n{\n    int err;\n#ifdef MS_WINDOWS\n    struct _stat wstatbuf;\n    err = _wstat(path, &wstatbuf);\n    if (!err) {\n        buf->st_mode = wstatbuf.st_mode;\n    }\n#else\n    char *fname;\n    fname = _Py_EncodeLocaleRaw(path, NULL);\n    if (fname == NULL) {\n        errno = EINVAL;\n        return -1;\n    }\n    err = stat(fname, buf);\n    PyMem_RawFree(fname);\n#endif\n    return err;\n}\n\n\n/* Call _wstat() on Windows, or encode the path to the filesystem encoding and\n   call stat() otherwise. Only fill st_mode attribute on Windows.\n\n   Return 0 on success, -1 on _wstat() / stat() error, -2 if an exception was\n   raised. */\n\nint\n_Py_stat(PyObject *path, struct stat *statbuf)\n{\n#ifdef MS_WINDOWS\n    int err;\n\n    wchar_t *wpath = PyUnicode_AsWideCharString(path, NULL);\n    if (wpath == NULL)\n        return -2;\n\n    err = _Py_wstat(wpath, statbuf);\n    PyMem_Free(wpath);\n    return err;\n#else\n    int ret;\n    PyObject *bytes;\n    char *cpath;\n\n    bytes = PyUnicode_EncodeFSDefault(path);\n    if (bytes == NULL)\n        return -2;\n\n    /* check for embedded null bytes */\n    if (PyBytes_AsStringAndSize(bytes, &cpath, NULL) == -1) {\n        Py_DECREF(bytes);\n        return -2;\n    }\n\n    ret = stat(cpath, statbuf);\n    Py_DECREF(bytes);\n    return ret;\n#endif\n}\n\n#ifdef MS_WINDOWS\n// For some Windows API partitions, SetHandleInformation() is declared\n// but none of the handle flags are defined.\n#ifndef HANDLE_FLAG_INHERIT\n#define HANDLE_FLAG_INHERIT 0x00000001\n#endif\n#endif\n\n/* This function MUST be kept async-signal-safe on POSIX when raise=0. */\nstatic int\nget_inheritable(int fd, int raise)\n{\n#ifdef MS_WINDOWS\n    HANDLE handle;\n    DWORD flags;\n\n    handle = _Py_get_osfhandle_noraise(fd);\n    if (handle == INVALID_HANDLE_VALUE) {\n        if (raise)\n            PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n\n    if (!GetHandleInformation(handle, &flags)) {\n        if (raise)\n            PyErr_SetFromWindowsErr(0);\n        return -1;\n    }\n\n    return (flags & HANDLE_FLAG_INHERIT);\n#else\n    int flags;\n\n    flags = fcntl(fd, F_GETFD, 0);\n    if (flags == -1) {\n        if (raise)\n            PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n    return !(flags & FD_CLOEXEC);\n#endif\n}\n\n/* Get the inheritable flag of the specified file descriptor.\n   Return 1 if the file descriptor can be inherited, 0 if it cannot,\n   raise an exception and return -1 on error. */\nint\n_Py_get_inheritable(int fd)\n{\n    return get_inheritable(fd, 1);\n}\n\n\n/* This function MUST be kept async-signal-safe on POSIX when raise=0. */\nstatic int\nset_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)\n{\n#ifdef MS_WINDOWS\n    HANDLE handle;\n    DWORD flags;\n#else\n#if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)\n    static int ioctl_works = -1;\n    int request;\n    int err;\n#endif\n    int flags, new_flags;\n    int res;\n#endif\n\n    /* atomic_flag_works can only be used to make the file descriptor\n       non-inheritable */\n    assert(!(atomic_flag_works != NULL && inheritable));\n\n    if (atomic_flag_works != NULL && !inheritable) {\n        if (*atomic_flag_works == -1) {\n            int isInheritable = get_inheritable(fd, raise);\n            if (isInheritable == -1)\n                return -1;\n            *atomic_flag_works = !isInheritable;\n        }\n\n        if (*atomic_flag_works)\n            return 0;\n    }\n\n#ifdef MS_WINDOWS\n    handle = _Py_get_osfhandle_noraise(fd);\n    if (handle == INVALID_HANDLE_VALUE) {\n        if (raise)\n            PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n\n    if (inheritable)\n        flags = HANDLE_FLAG_INHERIT;\n    else\n        flags = 0;\n\n    if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) {\n        if (raise)\n            PyErr_SetFromWindowsErr(0);\n        return -1;\n    }\n    return 0;\n\n#else\n\n#if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)\n    if (ioctl_works != 0 && raise != 0) {\n        /* fast-path: ioctl() only requires one syscall */\n        /* caveat: raise=0 is an indicator that we must be async-signal-safe\n         * thus avoid using ioctl() so we skip the fast-path. */\n        if (inheritable)\n            request = FIONCLEX;\n        else\n            request = FIOCLEX;\n        err = ioctl(fd, request, NULL);\n        if (!err) {\n            ioctl_works = 1;\n            return 0;\n        }\n\n#ifdef O_PATH\n        if (errno == EBADF) {\n            // bpo-44849: On Linux and FreeBSD, ioctl(FIOCLEX) fails with EBADF\n            // on O_PATH file descriptors. Fall through to the fcntl()\n            // implementation.\n        }\n        else\n#endif\n        if (errno != ENOTTY && errno != EACCES) {\n            if (raise)\n                PyErr_SetFromErrno(PyExc_OSError);\n            return -1;\n        }\n        else {\n            /* Issue #22258: Here, ENOTTY means \"Inappropriate ioctl for\n               device\". The ioctl is declared but not supported by the kernel.\n               Remember that ioctl() doesn't work. It is the case on\n               Illumos-based OS for example.\n\n               Issue #27057: When SELinux policy disallows ioctl it will fail\n               with EACCES. While FIOCLEX is safe operation it may be\n               unavailable because ioctl was denied altogether.\n               This can be the case on Android. */\n            ioctl_works = 0;\n        }\n        /* fallback to fcntl() if ioctl() does not work */\n    }\n#endif\n\n    /* slow-path: fcntl() requires two syscalls */\n    flags = fcntl(fd, F_GETFD);\n    if (flags < 0) {\n        if (raise)\n            PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n\n    if (inheritable) {\n        new_flags = flags & ~FD_CLOEXEC;\n    }\n    else {\n        new_flags = flags | FD_CLOEXEC;\n    }\n\n    if (new_flags == flags) {\n        /* FD_CLOEXEC flag already set/cleared: nothing to do */\n        return 0;\n    }\n\n    res = fcntl(fd, F_SETFD, new_flags);\n    if (res < 0) {\n        if (raise)\n            PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n    return 0;\n#endif\n}\n\n/* Make the file descriptor non-inheritable.\n   Return 0 on success, set errno and return -1 on error. */\nstatic int\nmake_non_inheritable(int fd)\n{\n    return set_inheritable(fd, 0, 0, NULL);\n}\n\n/* Set the inheritable flag of the specified file descriptor.\n   On success: return 0, on error: raise an exception and return -1.\n\n   If atomic_flag_works is not NULL:\n\n    * if *atomic_flag_works==-1, check if the inheritable is set on the file\n      descriptor: if yes, set *atomic_flag_works to 1, otherwise set to 0 and\n      set the inheritable flag\n    * if *atomic_flag_works==1: do nothing\n    * if *atomic_flag_works==0: set inheritable flag to False\n\n   Set atomic_flag_works to NULL if no atomic flag was used to create the\n   file descriptor.\n\n   atomic_flag_works can only be used to make a file descriptor\n   non-inheritable: atomic_flag_works must be NULL if inheritable=1. */\nint\n_Py_set_inheritable(int fd, int inheritable, int *atomic_flag_works)\n{\n    return set_inheritable(fd, inheritable, 1, atomic_flag_works);\n}\n\n/* Same as _Py_set_inheritable() but on error, set errno and\n   don't raise an exception.\n   This function is async-signal-safe. */\nint\n_Py_set_inheritable_async_safe(int fd, int inheritable, int *atomic_flag_works)\n{\n    return set_inheritable(fd, inheritable, 0, atomic_flag_works);\n}\n\nstatic int\n_Py_open_impl(const char *pathname, int flags, int gil_held)\n{\n    int fd;\n    int async_err = 0;\n#ifndef MS_WINDOWS\n    int *atomic_flag_works;\n#endif\n\n#ifdef MS_WINDOWS\n    flags |= O_NOINHERIT;\n#elif defined(O_CLOEXEC)\n    atomic_flag_works = &_Py_open_cloexec_works;\n    flags |= O_CLOEXEC;\n#else\n    atomic_flag_works = NULL;\n#endif\n\n    if (gil_held) {\n        PyObject *pathname_obj = PyUnicode_DecodeFSDefault(pathname);\n        if (pathname_obj == NULL) {\n            return -1;\n        }\n        if (PySys_Audit(\"open\", \"OOi\", pathname_obj, Py_None, flags) < 0) {\n            Py_DECREF(pathname_obj);\n            return -1;\n        }\n\n        do {\n            Py_BEGIN_ALLOW_THREADS\n            fd = open(pathname, flags);\n            Py_END_ALLOW_THREADS\n        } while (fd < 0\n                 && errno == EINTR && !(async_err = PyErr_CheckSignals()));\n        if (async_err) {\n            Py_DECREF(pathname_obj);\n            return -1;\n        }\n        if (fd < 0) {\n            PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, pathname_obj, NULL);\n            Py_DECREF(pathname_obj);\n            return -1;\n        }\n        Py_DECREF(pathname_obj);\n    }\n    else {\n        fd = open(pathname, flags);\n        if (fd < 0)\n            return -1;\n    }\n\n#ifndef MS_WINDOWS\n    if (set_inheritable(fd, 0, gil_held, atomic_flag_works) < 0) {\n        close(fd);\n        return -1;\n    }\n#endif\n\n    return fd;\n}\n\n/* Open a file with the specified flags (wrapper to open() function).\n   Return a file descriptor on success. Raise an exception and return -1 on\n   error.\n\n   The file descriptor is created non-inheritable.\n\n   When interrupted by a signal (open() fails with EINTR), retry the syscall,\n   except if the Python signal handler raises an exception.\n\n   Release the GIL to call open(). The caller must hold the GIL. */\nint\n_Py_open(const char *pathname, int flags)\n{\n    /* _Py_open() must be called with the GIL held. */\n    assert(PyGILState_Check());\n    return _Py_open_impl(pathname, flags, 1);\n}\n\n/* Open a file with the specified flags (wrapper to open() function).\n   Return a file descriptor on success. Set errno and return -1 on error.\n\n   The file descriptor is created non-inheritable.\n\n   If interrupted by a signal, fail with EINTR. */\nint\n_Py_open_noraise(const char *pathname, int flags)\n{\n    return _Py_open_impl(pathname, flags, 0);\n}\n\n/* Open a file. Use _wfopen() on Windows, encode the path to the locale\n   encoding and use fopen() otherwise.\n\n   The file descriptor is created non-inheritable.\n\n   If interrupted by a signal, fail with EINTR. */\nFILE *\n_Py_wfopen(const wchar_t *path, const wchar_t *mode)\n{\n    FILE *f;\n    if (PySys_Audit(\"open\", \"uui\", path, mode, 0) < 0) {\n        return NULL;\n    }\n#ifndef MS_WINDOWS\n    char *cpath;\n    char cmode[10];\n    size_t r;\n    r = wcstombs(cmode, mode, 10);\n    if (r == DECODE_ERROR || r >= 10) {\n        errno = EINVAL;\n        return NULL;\n    }\n    cpath = _Py_EncodeLocaleRaw(path, NULL);\n    if (cpath == NULL) {\n        return NULL;\n    }\n    f = fopen(cpath, cmode);\n    PyMem_RawFree(cpath);\n#else\n    f = _wfopen(path, mode);\n#endif\n    if (f == NULL)\n        return NULL;\n    if (make_non_inheritable(fileno(f)) < 0) {\n        fclose(f);\n        return NULL;\n    }\n    return f;\n}\n\n\n/* Open a file. Call _wfopen() on Windows, or encode the path to the filesystem\n   encoding and call fopen() otherwise.\n\n   Return the new file object on success. Raise an exception and return NULL\n   on error.\n\n   The file descriptor is created non-inheritable.\n\n   When interrupted by a signal (open() fails with EINTR), retry the syscall,\n   except if the Python signal handler raises an exception.\n\n   Release the GIL to call _wfopen() or fopen(). The caller must hold\n   the GIL. */\nFILE*\n_Py_fopen_obj(PyObject *path, const char *mode)\n{\n    FILE *f;\n    int async_err = 0;\n#ifdef MS_WINDOWS\n    wchar_t wmode[10];\n    int usize;\n\n    assert(PyGILState_Check());\n\n    if (PySys_Audit(\"open\", \"Osi\", path, mode, 0) < 0) {\n        return NULL;\n    }\n    if (!PyUnicode_Check(path)) {\n        PyErr_Format(PyExc_TypeError,\n                     \"str file path expected under Windows, got %R\",\n                     Py_TYPE(path));\n        return NULL;\n    }\n\n    wchar_t *wpath = PyUnicode_AsWideCharString(path, NULL);\n    if (wpath == NULL)\n        return NULL;\n\n    usize = MultiByteToWideChar(CP_ACP, 0, mode, -1,\n                                wmode, Py_ARRAY_LENGTH(wmode));\n    if (usize == 0) {\n        PyErr_SetFromWindowsErr(0);\n        PyMem_Free(wpath);\n        return NULL;\n    }\n\n    do {\n        Py_BEGIN_ALLOW_THREADS\n        f = _wfopen(wpath, wmode);\n        Py_END_ALLOW_THREADS\n    } while (f == NULL\n             && errno == EINTR && !(async_err = PyErr_CheckSignals()));\n    PyMem_Free(wpath);\n#else\n    PyObject *bytes;\n    const char *path_bytes;\n\n    assert(PyGILState_Check());\n\n    if (!PyUnicode_FSConverter(path, &bytes))\n        return NULL;\n    path_bytes = PyBytes_AS_STRING(bytes);\n\n    if (PySys_Audit(\"open\", \"Osi\", path, mode, 0) < 0) {\n        Py_DECREF(bytes);\n        return NULL;\n    }\n\n    do {\n        Py_BEGIN_ALLOW_THREADS\n        f = fopen(path_bytes, mode);\n        Py_END_ALLOW_THREADS\n    } while (f == NULL\n             && errno == EINTR && !(async_err = PyErr_CheckSignals()));\n\n    Py_DECREF(bytes);\n#endif\n    if (async_err)\n        return NULL;\n\n    if (f == NULL) {\n        PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);\n        return NULL;\n    }\n\n    if (set_inheritable(fileno(f), 0, 1, NULL) < 0) {\n        fclose(f);\n        return NULL;\n    }\n    return f;\n}\n\n/* Read count bytes from fd into buf.\n\n   On success, return the number of read bytes, it can be lower than count.\n   If the current file offset is at or past the end of file, no bytes are read,\n   and read() returns zero.\n\n   On error, raise an exception, set errno and return -1.\n\n   When interrupted by a signal (read() fails with EINTR), retry the syscall.\n   If the Python signal handler raises an exception, the function returns -1\n   (the syscall is not retried).\n\n   Release the GIL to call read(). The caller must hold the GIL. */\nPy_ssize_t\n_Py_read(int fd, void *buf, size_t count)\n{\n    Py_ssize_t n;\n    int err;\n    int async_err = 0;\n\n    assert(PyGILState_Check());\n\n    /* _Py_read() must not be called with an exception set, otherwise the\n     * caller may think that read() was interrupted by a signal and the signal\n     * handler raised an exception. */\n    assert(!PyErr_Occurred());\n\n    if (count > _PY_READ_MAX) {\n        count = _PY_READ_MAX;\n    }\n\n    _Py_BEGIN_SUPPRESS_IPH\n    do {\n        Py_BEGIN_ALLOW_THREADS\n        errno = 0;\n#ifdef MS_WINDOWS\n        _doserrno = 0;\n        n = read(fd, buf, (int)count);\n        // read() on a non-blocking empty pipe fails with EINVAL, which is\n        // mapped from the Windows error code ERROR_NO_DATA.\n        if (n < 0 && errno == EINVAL) {\n            if (_doserrno == ERROR_NO_DATA) {\n                errno = EAGAIN;\n            }\n        }\n#else\n        n = read(fd, buf, count);\n#endif\n        /* save/restore errno because PyErr_CheckSignals()\n         * and PyErr_SetFromErrno() can modify it */\n        err = errno;\n        Py_END_ALLOW_THREADS\n    } while (n < 0 && err == EINTR &&\n            !(async_err = PyErr_CheckSignals()));\n    _Py_END_SUPPRESS_IPH\n\n    if (async_err) {\n        /* read() was interrupted by a signal (failed with EINTR)\n         * and the Python signal handler raised an exception */\n        errno = err;\n        assert(errno == EINTR && PyErr_Occurred());\n        return -1;\n    }\n    if (n < 0) {\n        PyErr_SetFromErrno(PyExc_OSError);\n        errno = err;\n        return -1;\n    }\n\n    return n;\n}\n\nstatic Py_ssize_t\n_Py_write_impl(int fd, const void *buf, size_t count, int gil_held)\n{\n    Py_ssize_t n;\n    int err;\n    int async_err = 0;\n\n    _Py_BEGIN_SUPPRESS_IPH\n#ifdef MS_WINDOWS\n    if (count > 32767) {\n        /* Issue #11395: the Windows console returns an error (12: not\n           enough space error) on writing into stdout if stdout mode is\n           binary and the length is greater than 66,000 bytes (or less,\n           depending on heap usage). */\n        if (gil_held) {\n            Py_BEGIN_ALLOW_THREADS\n            if (isatty(fd)) {\n                count = 32767;\n            }\n            Py_END_ALLOW_THREADS\n        } else {\n            if (isatty(fd)) {\n                count = 32767;\n            }\n        }\n    }\n\n#endif\n    if (count > _PY_WRITE_MAX) {\n        count = _PY_WRITE_MAX;\n    }\n\n    if (gil_held) {\n        do {\n            Py_BEGIN_ALLOW_THREADS\n            errno = 0;\n#ifdef MS_WINDOWS\n            // write() on a non-blocking pipe fails with ENOSPC on Windows if\n            // the pipe lacks available space for the entire buffer.\n            int c = (int)count;\n            do {\n                _doserrno = 0;\n                n = write(fd, buf, c);\n                if (n >= 0 || errno != ENOSPC || _doserrno != 0) {\n                    break;\n                }\n                errno = EAGAIN;\n                c /= 2;\n            } while (c > 0);\n#else\n            n = write(fd, buf, count);\n#endif\n            /* save/restore errno because PyErr_CheckSignals()\n             * and PyErr_SetFromErrno() can modify it */\n            err = errno;\n            Py_END_ALLOW_THREADS\n        } while (n < 0 && err == EINTR &&\n                !(async_err = PyErr_CheckSignals()));\n    }\n    else {\n        do {\n            errno = 0;\n#ifdef MS_WINDOWS\n            // write() on a non-blocking pipe fails with ENOSPC on Windows if\n            // the pipe lacks available space for the entire buffer.\n            int c = (int)count;\n            do {\n                _doserrno = 0;\n                n = write(fd, buf, c);\n                if (n >= 0 || errno != ENOSPC || _doserrno != 0) {\n                    break;\n                }\n                errno = EAGAIN;\n                c /= 2;\n            } while (c > 0);\n#else\n            n = write(fd, buf, count);\n#endif\n            err = errno;\n        } while (n < 0 && err == EINTR);\n    }\n    _Py_END_SUPPRESS_IPH\n\n    if (async_err) {\n        /* write() was interrupted by a signal (failed with EINTR)\n           and the Python signal handler raised an exception (if gil_held is\n           nonzero). */\n        errno = err;\n        assert(errno == EINTR && (!gil_held || PyErr_Occurred()));\n        return -1;\n    }\n    if (n < 0) {\n        if (gil_held)\n            PyErr_SetFromErrno(PyExc_OSError);\n        errno = err;\n        return -1;\n    }\n\n    return n;\n}\n\n/* Write count bytes of buf into fd.\n\n   On success, return the number of written bytes, it can be lower than count\n   including 0. On error, raise an exception, set errno and return -1.\n\n   When interrupted by a signal (write() fails with EINTR), retry the syscall.\n   If the Python signal handler raises an exception, the function returns -1\n   (the syscall is not retried).\n\n   Release the GIL to call write(). The caller must hold the GIL. */\nPy_ssize_t\n_Py_write(int fd, const void *buf, size_t count)\n{\n    assert(PyGILState_Check());\n\n    /* _Py_write() must not be called with an exception set, otherwise the\n     * caller may think that write() was interrupted by a signal and the signal\n     * handler raised an exception. */\n    assert(!PyErr_Occurred());\n\n    return _Py_write_impl(fd, buf, count, 1);\n}\n\n/* Write count bytes of buf into fd.\n *\n * On success, return the number of written bytes, it can be lower than count\n * including 0. On error, set errno and return -1.\n *\n * When interrupted by a signal (write() fails with EINTR), retry the syscall\n * without calling the Python signal handler. */\nPy_ssize_t\n_Py_write_noraise(int fd, const void *buf, size_t count)\n{\n    return _Py_write_impl(fd, buf, count, 0);\n}\n\n#ifdef HAVE_READLINK\n\n/* Read value of symbolic link. Encode the path to the locale encoding, decode\n   the result from the locale encoding.\n\n   Return -1 on encoding error, on readlink() error, if the internal buffer is\n   too short, on decoding error, or if 'buf' is too short. */\nint\n_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t buflen)\n{\n    char *cpath;\n    char cbuf[MAXPATHLEN];\n    size_t cbuf_len = Py_ARRAY_LENGTH(cbuf);\n    wchar_t *wbuf;\n    Py_ssize_t res;\n    size_t r1;\n\n    cpath = _Py_EncodeLocaleRaw(path, NULL);\n    if (cpath == NULL) {\n        errno = EINVAL;\n        return -1;\n    }\n    res = readlink(cpath, cbuf, cbuf_len);\n    PyMem_RawFree(cpath);\n    if (res == -1) {\n        return -1;\n    }\n    if ((size_t)res == cbuf_len) {\n        errno = EINVAL;\n        return -1;\n    }\n    cbuf[res] = '\\0'; /* buf will be null terminated */\n    wbuf = Py_DecodeLocale(cbuf, &r1);\n    if (wbuf == NULL) {\n        errno = EINVAL;\n        return -1;\n    }\n    /* wbuf must have space to store the trailing NUL character */\n    if (buflen <= r1) {\n        PyMem_RawFree(wbuf);\n        errno = EINVAL;\n        return -1;\n    }\n    wcsncpy(buf, wbuf, buflen);\n    PyMem_RawFree(wbuf);\n    return (int)r1;\n}\n#endif\n\n#ifdef HAVE_REALPATH\n\n/* Return the canonicalized absolute pathname. Encode path to the locale\n   encoding, decode the result from the locale encoding.\n\n   Return NULL on encoding error, realpath() error, decoding error\n   or if 'resolved_path' is too short. */\nwchar_t*\n_Py_wrealpath(const wchar_t *path,\n              wchar_t *resolved_path, size_t resolved_path_len)\n{\n    char *cpath;\n    char cresolved_path[MAXPATHLEN];\n    wchar_t *wresolved_path;\n    char *res;\n    size_t r;\n    cpath = _Py_EncodeLocaleRaw(path, NULL);\n    if (cpath == NULL) {\n        errno = EINVAL;\n        return NULL;\n    }\n    res = realpath(cpath, cresolved_path);\n    PyMem_RawFree(cpath);\n    if (res == NULL)\n        return NULL;\n\n    wresolved_path = Py_DecodeLocale(cresolved_path, &r);\n    if (wresolved_path == NULL) {\n        errno = EINVAL;\n        return NULL;\n    }\n    /* wresolved_path must have space to store the trailing NUL character */\n    if (resolved_path_len <= r) {\n        PyMem_RawFree(wresolved_path);\n        errno = EINVAL;\n        return NULL;\n    }\n    wcsncpy(resolved_path, wresolved_path, resolved_path_len);\n    PyMem_RawFree(wresolved_path);\n    return resolved_path;\n}\n#endif\n\n\nint\n_Py_isabs(const wchar_t *path)\n{\n#ifdef MS_WINDOWS\n    const wchar_t *tail;\n    HRESULT hr = PathCchSkipRoot(path, &tail);\n    if (FAILED(hr) || path == tail) {\n        return 0;\n    }\n    if (tail == &path[1] && (path[0] == SEP || path[0] == ALTSEP)) {\n        // Exclude paths with leading SEP\n        return 0;\n    }\n    if (tail == &path[2] && path[1] == L':') {\n        // Exclude drive-relative paths (e.g. C:filename.ext)\n        return 0;\n    }\n    return 1;\n#else\n    return (path[0] == SEP);\n#endif\n}\n\n\n/* Get an absolute path.\n   On error (ex: fail to get the current directory), return -1.\n   On memory allocation failure, set *abspath_p to NULL and return 0.\n   On success, return a newly allocated to *abspath_p to and return 0.\n   The string must be freed by PyMem_RawFree(). */\nint\n_Py_abspath(const wchar_t *path, wchar_t **abspath_p)\n{\n    if (path[0] == '\\0' || !wcscmp(path, L\".\")) {\n        wchar_t cwd[MAXPATHLEN + 1];\n        cwd[Py_ARRAY_LENGTH(cwd) - 1] = 0;\n        if (!_Py_wgetcwd(cwd, Py_ARRAY_LENGTH(cwd) - 1)) {\n            /* unable to get the current directory */\n            return -1;\n        }\n        *abspath_p = _PyMem_RawWcsdup(cwd);\n        return 0;\n    }\n\n    if (_Py_isabs(path)) {\n        *abspath_p = _PyMem_RawWcsdup(path);\n        return 0;\n    }\n\n#ifdef MS_WINDOWS\n    return _PyOS_getfullpathname(path, abspath_p);\n#else\n    wchar_t cwd[MAXPATHLEN + 1];\n    cwd[Py_ARRAY_LENGTH(cwd) - 1] = 0;\n    if (!_Py_wgetcwd(cwd, Py_ARRAY_LENGTH(cwd) - 1)) {\n        /* unable to get the current directory */\n        return -1;\n    }\n\n    size_t cwd_len = wcslen(cwd);\n    size_t path_len = wcslen(path);\n    size_t len = cwd_len + 1 + path_len + 1;\n    if (len <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {\n        *abspath_p = PyMem_RawMalloc(len * sizeof(wchar_t));\n    }\n    else {\n        *abspath_p = NULL;\n    }\n    if (*abspath_p == NULL) {\n        return 0;\n    }\n\n    wchar_t *abspath = *abspath_p;\n    memcpy(abspath, cwd, cwd_len * sizeof(wchar_t));\n    abspath += cwd_len;\n\n    *abspath = (wchar_t)SEP;\n    abspath++;\n\n    memcpy(abspath, path, path_len * sizeof(wchar_t));\n    abspath += path_len;\n\n    *abspath = 0;\n    return 0;\n#endif\n}\n\n// The Windows Games API family implements the PathCch* APIs in the Xbox OS,\n// but does not expose them yet. Load them dynamically until\n// 1) they are officially exposed\n// 2) we stop supporting older versions of the GDK which do not expose them\n#if defined(MS_WINDOWS_GAMES) && !defined(MS_WINDOWS_DESKTOP)\nHRESULT\nPathCchSkipRoot(const wchar_t *path, const wchar_t **rootEnd)\n{\n    static int initialized = 0;\n    typedef HRESULT(__stdcall *PPathCchSkipRoot) (PCWSTR pszPath,\n                                                  PCWSTR *ppszRootEnd);\n    static PPathCchSkipRoot _PathCchSkipRoot;\n\n    if (initialized == 0) {\n        HMODULE pathapi = LoadLibraryExW(L\"api-ms-win-core-path-l1-1-0.dll\", NULL,\n                                         LOAD_LIBRARY_SEARCH_SYSTEM32);\n        if (pathapi) {\n            _PathCchSkipRoot = (PPathCchSkipRoot)GetProcAddress(\n                pathapi, \"PathCchSkipRoot\");\n        }\n        else {\n            _PathCchSkipRoot = NULL;\n        }\n        initialized = 1;\n    }\n\n    if (!_PathCchSkipRoot) {\n        return E_NOINTERFACE;\n    }\n\n    return _PathCchSkipRoot(path, rootEnd);\n}\n\nstatic HRESULT\nPathCchCombineEx(wchar_t *buffer, size_t bufsize, const wchar_t *dirname,\n                 const wchar_t *relfile, unsigned long flags)\n{\n    static int initialized = 0;\n    typedef HRESULT(__stdcall *PPathCchCombineEx) (PWSTR pszPathOut,\n                                                   size_t cchPathOut,\n                                                   PCWSTR pszPathIn,\n                                                   PCWSTR pszMore,\n                                                   unsigned long dwFlags);\n    static PPathCchCombineEx _PathCchCombineEx;\n\n    if (initialized == 0) {\n        HMODULE pathapi = LoadLibraryExW(L\"api-ms-win-core-path-l1-1-0.dll\", NULL,\n                                         LOAD_LIBRARY_SEARCH_SYSTEM32);\n        if (pathapi) {\n            _PathCchCombineEx = (PPathCchCombineEx)GetProcAddress(\n                pathapi, \"PathCchCombineEx\");\n        }\n        else {\n            _PathCchCombineEx = NULL;\n        }\n        initialized = 1;\n    }\n\n    if (!_PathCchCombineEx) {\n        return E_NOINTERFACE;\n    }\n\n    return _PathCchCombineEx(buffer, bufsize, dirname, relfile, flags);\n}\n\n#endif /* defined(MS_WINDOWS_GAMES) && !defined(MS_WINDOWS_DESKTOP) */\n\n// The caller must ensure \"buffer\" is big enough.\nstatic int\njoin_relfile(wchar_t *buffer, size_t bufsize,\n             const wchar_t *dirname, const wchar_t *relfile)\n{\n#ifdef MS_WINDOWS\n    if (FAILED(PathCchCombineEx(buffer, bufsize, dirname, relfile,\n        PATHCCH_ALLOW_LONG_PATHS))) {\n        return -1;\n    }\n#else\n    assert(!_Py_isabs(relfile));\n    size_t dirlen = wcslen(dirname);\n    size_t rellen = wcslen(relfile);\n    size_t maxlen = bufsize - 1;\n    if (maxlen > MAXPATHLEN || dirlen >= maxlen || rellen >= maxlen - dirlen) {\n        return -1;\n    }\n    if (dirlen == 0) {\n        // We do not add a leading separator.\n        wcscpy(buffer, relfile);\n    }\n    else {\n        if (dirname != buffer) {\n            wcscpy(buffer, dirname);\n        }\n        size_t relstart = dirlen;\n        if (dirlen > 1 && dirname[dirlen - 1] != SEP) {\n            buffer[dirlen] = SEP;\n            relstart += 1;\n        }\n        wcscpy(&buffer[relstart], relfile);\n    }\n#endif\n    return 0;\n}\n\n/* Join the two paths together, like os.path.join().  Return NULL\n   if memory could not be allocated.  The caller is responsible\n   for calling PyMem_RawFree() on the result. */\nwchar_t *\n_Py_join_relfile(const wchar_t *dirname, const wchar_t *relfile)\n{\n    assert(dirname != NULL && relfile != NULL);\n#ifndef MS_WINDOWS\n    assert(!_Py_isabs(relfile));\n#endif\n    size_t maxlen = wcslen(dirname) + 1 + wcslen(relfile);\n    size_t bufsize = maxlen + 1;\n    wchar_t *filename = PyMem_RawMalloc(bufsize * sizeof(wchar_t));\n    if (filename == NULL) {\n        return NULL;\n    }\n    assert(wcslen(dirname) < MAXPATHLEN);\n    assert(wcslen(relfile) < MAXPATHLEN - wcslen(dirname));\n    if (join_relfile(filename, bufsize, dirname, relfile) < 0) {\n        PyMem_RawFree(filename);\n        return NULL;\n    }\n    return filename;\n}\n\n/* Join the two paths together, like os.path.join().\n     dirname: the target buffer with the dirname already in place,\n              including trailing NUL\n     relfile: this must be a relative path\n     bufsize: total allocated size of the buffer\n   Return -1 if anything is wrong with the path lengths. */\nint\n_Py_add_relfile(wchar_t *dirname, const wchar_t *relfile, size_t bufsize)\n{\n    assert(dirname != NULL && relfile != NULL);\n    assert(bufsize > 0);\n    return join_relfile(dirname, bufsize, dirname, relfile);\n}\n\n\nsize_t\n_Py_find_basename(const wchar_t *filename)\n{\n    for (size_t i = wcslen(filename); i > 0; --i) {\n        if (filename[i] == SEP) {\n            return i + 1;\n        }\n    }\n    return 0;\n}\n\n/* In-place path normalisation. Returns the start of the normalized\n   path, which will be within the original buffer. Guaranteed to not\n   make the path longer, and will not fail. 'size' is the length of\n   the path, if known. If -1, the first null character will be assumed\n   to be the end of the path. */\nwchar_t *\n_Py_normpath(wchar_t *path, Py_ssize_t size)\n{\n    assert(path != NULL);\n    if (!path[0] || size == 0) {\n        return path;\n    }\n    wchar_t *pEnd = size >= 0 ? &path[size] : NULL;\n    wchar_t *p1 = path;     // sequentially scanned address in the path\n    wchar_t *p2 = path;     // destination of a scanned character to be ljusted\n    wchar_t *minP2 = path;  // the beginning of the destination range\n    wchar_t lastC = L'\\0';  // the last ljusted character, p2[-1] in most cases\n\n#define IS_END(x) (pEnd ? (x) == pEnd : !*(x))\n#ifdef ALTSEP\n#define IS_SEP(x) (*(x) == SEP || *(x) == ALTSEP)\n#else\n#define IS_SEP(x) (*(x) == SEP)\n#endif\n#define SEP_OR_END(x) (IS_SEP(x) || IS_END(x))\n\n    // Skip leading '.\\'\n    if (p1[0] == L'.' && IS_SEP(&p1[1])) {\n        path = &path[2];\n        while (IS_SEP(path) && !IS_END(path)) {\n            path++;\n        }\n        p1 = p2 = minP2 = path;\n        lastC = SEP;\n    }\n#ifdef MS_WINDOWS\n    // Skip past drive segment and update minP2\n    else if (p1[0] && p1[1] == L':') {\n        *p2++ = *p1++;\n        *p2++ = *p1++;\n        minP2 = p2;\n        lastC = L':';\n    }\n    // Skip past all \\\\-prefixed paths, including \\\\?\\, \\\\.\\,\n    // and network paths, including the first segment.\n    else if (IS_SEP(&p1[0]) && IS_SEP(&p1[1])) {\n        int sepCount = 2;\n        *p2++ = SEP;\n        *p2++ = SEP;\n        p1 += 2;\n        for (; !IS_END(p1) && sepCount; ++p1) {\n            if (IS_SEP(p1)) {\n                --sepCount;\n                *p2++ = lastC = SEP;\n            } else {\n                *p2++ = lastC = *p1;\n            }\n        }\n        if (sepCount) {\n            minP2 = p2;      // Invalid path\n        } else {\n            minP2 = p2 - 1;  // Absolute path has SEP at minP2\n        }\n    }\n#else\n    // Skip past two leading SEPs\n    else if (IS_SEP(&p1[0]) && IS_SEP(&p1[1]) && !IS_SEP(&p1[2])) {\n        *p2++ = *p1++;\n        *p2++ = *p1++;\n        minP2 = p2 - 1;  // Absolute path has SEP at minP2\n        lastC = SEP;\n    }\n#endif /* MS_WINDOWS */\n\n    /* if pEnd is specified, check that. Else, check for null terminator */\n    for (; !IS_END(p1); ++p1) {\n        wchar_t c = *p1;\n#ifdef ALTSEP\n        if (c == ALTSEP) {\n            c = SEP;\n        }\n#endif\n        if (lastC == SEP) {\n            if (c == L'.') {\n                int sep_at_1 = SEP_OR_END(&p1[1]);\n                int sep_at_2 = !sep_at_1 && SEP_OR_END(&p1[2]);\n                if (sep_at_2 && p1[1] == L'.') {\n                    wchar_t *p3 = p2;\n                    while (p3 != minP2 && *--p3 == SEP) { }\n                    while (p3 != minP2 && *(p3 - 1) != SEP) { --p3; }\n                    if (p2 == minP2\n                        || (p3[0] == L'.' && p3[1] == L'.' && IS_SEP(&p3[2])))\n                    {\n                        // Previous segment is also ../, so append instead.\n                        // Relative path does not absorb ../ at minP2 as well.\n                        *p2++ = L'.';\n                        *p2++ = L'.';\n                        lastC = L'.';\n                    } else if (p3[0] == SEP) {\n                        // Absolute path, so absorb segment\n                        p2 = p3 + 1;\n                    } else {\n                        p2 = p3;\n                    }\n                    p1 += 1;\n                } else if (sep_at_1) {\n                } else {\n                    *p2++ = lastC = c;\n                }\n            } else if (c == SEP) {\n            } else {\n                *p2++ = lastC = c;\n            }\n        } else {\n            *p2++ = lastC = c;\n        }\n    }\n    *p2 = L'\\0';\n    if (p2 != minP2) {\n        while (--p2 != minP2 && *p2 == SEP) {\n            *p2 = L'\\0';\n        }\n    }\n#undef SEP_OR_END\n#undef IS_SEP\n#undef IS_END\n    return path;\n}\n\n\n/* Get the current directory. buflen is the buffer size in wide characters\n   including the null character. Decode the path from the locale encoding.\n\n   Return NULL on getcwd() error, on decoding error, or if 'buf' is\n   too short. */\nwchar_t*\n_Py_wgetcwd(wchar_t *buf, size_t buflen)\n{\n#ifdef MS_WINDOWS\n    int ibuflen = (int)Py_MIN(buflen, INT_MAX);\n    return _wgetcwd(buf, ibuflen);\n#else\n    char fname[MAXPATHLEN];\n    wchar_t *wname;\n    size_t len;\n\n    if (getcwd(fname, Py_ARRAY_LENGTH(fname)) == NULL)\n        return NULL;\n    wname = Py_DecodeLocale(fname, &len);\n    if (wname == NULL)\n        return NULL;\n    /* wname must have space to store the trailing NUL character */\n    if (buflen <= len) {\n        PyMem_RawFree(wname);\n        return NULL;\n    }\n    wcsncpy(buf, wname, buflen);\n    PyMem_RawFree(wname);\n    return buf;\n#endif\n}\n\n/* Duplicate a file descriptor. The new file descriptor is created as\n   non-inheritable. Return a new file descriptor on success, raise an OSError\n   exception and return -1 on error.\n\n   The GIL is released to call dup(). The caller must hold the GIL. */\nint\n_Py_dup(int fd)\n{\n#ifdef MS_WINDOWS\n    HANDLE handle;\n#endif\n\n    assert(PyGILState_Check());\n\n#ifdef MS_WINDOWS\n    handle = _Py_get_osfhandle(fd);\n    if (handle == INVALID_HANDLE_VALUE)\n        return -1;\n\n    Py_BEGIN_ALLOW_THREADS\n    _Py_BEGIN_SUPPRESS_IPH\n    fd = dup(fd);\n    _Py_END_SUPPRESS_IPH\n    Py_END_ALLOW_THREADS\n    if (fd < 0) {\n        PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n\n    if (_Py_set_inheritable(fd, 0, NULL) < 0) {\n        _Py_BEGIN_SUPPRESS_IPH\n        close(fd);\n        _Py_END_SUPPRESS_IPH\n        return -1;\n    }\n#elif defined(HAVE_FCNTL_H) && defined(F_DUPFD_CLOEXEC)\n    Py_BEGIN_ALLOW_THREADS\n    _Py_BEGIN_SUPPRESS_IPH\n    fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);\n    _Py_END_SUPPRESS_IPH\n    Py_END_ALLOW_THREADS\n    if (fd < 0) {\n        PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n\n#elif HAVE_DUP\n    Py_BEGIN_ALLOW_THREADS\n    _Py_BEGIN_SUPPRESS_IPH\n    fd = dup(fd);\n    _Py_END_SUPPRESS_IPH\n    Py_END_ALLOW_THREADS\n    if (fd < 0) {\n        PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n\n    if (_Py_set_inheritable(fd, 0, NULL) < 0) {\n        _Py_BEGIN_SUPPRESS_IPH\n        close(fd);\n        _Py_END_SUPPRESS_IPH\n        return -1;\n    }\n#else\n    errno = ENOTSUP;\n    PyErr_SetFromErrno(PyExc_OSError);\n    return -1;\n#endif\n    return fd;\n}\n\n#ifndef MS_WINDOWS\n/* Get the blocking mode of the file descriptor.\n   Return 0 if the O_NONBLOCK flag is set, 1 if the flag is cleared,\n   raise an exception and return -1 on error. */\nint\n_Py_get_blocking(int fd)\n{\n    int flags;\n    _Py_BEGIN_SUPPRESS_IPH\n    flags = fcntl(fd, F_GETFL, 0);\n    _Py_END_SUPPRESS_IPH\n    if (flags < 0) {\n        PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n\n    return !(flags & O_NONBLOCK);\n}\n\n/* Set the blocking mode of the specified file descriptor.\n\n   Set the O_NONBLOCK flag if blocking is False, clear the O_NONBLOCK flag\n   otherwise.\n\n   Return 0 on success, raise an exception and return -1 on error. */\nint\n_Py_set_blocking(int fd, int blocking)\n{\n/* bpo-41462: On VxWorks, ioctl(FIONBIO) only works on sockets.\n   Use fcntl() instead. */\n#if defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO) && !defined(__VXWORKS__)\n    int arg = !blocking;\n    if (ioctl(fd, FIONBIO, &arg) < 0)\n        goto error;\n#else\n    int flags, res;\n\n    _Py_BEGIN_SUPPRESS_IPH\n    flags = fcntl(fd, F_GETFL, 0);\n    if (flags >= 0) {\n        if (blocking)\n            flags = flags & (~O_NONBLOCK);\n        else\n            flags = flags | O_NONBLOCK;\n\n        res = fcntl(fd, F_SETFL, flags);\n    } else {\n        res = -1;\n    }\n    _Py_END_SUPPRESS_IPH\n\n    if (res < 0)\n        goto error;\n#endif\n    return 0;\n\nerror:\n    PyErr_SetFromErrno(PyExc_OSError);\n    return -1;\n}\n#else   /* MS_WINDOWS */\nint\n_Py_get_blocking(int fd)\n{\n    HANDLE handle;\n    DWORD mode;\n    BOOL success;\n\n    handle = _Py_get_osfhandle(fd);\n    if (handle == INVALID_HANDLE_VALUE) {\n        return -1;\n    }\n\n    Py_BEGIN_ALLOW_THREADS\n    success = GetNamedPipeHandleStateW(handle, &mode,\n                                       NULL, NULL, NULL, NULL, 0);\n    Py_END_ALLOW_THREADS\n\n    if (!success) {\n        PyErr_SetFromWindowsErr(0);\n        return -1;\n    }\n\n    return !(mode & PIPE_NOWAIT);\n}\n\nint\n_Py_set_blocking(int fd, int blocking)\n{\n    HANDLE handle;\n    DWORD mode;\n    BOOL success;\n\n    handle = _Py_get_osfhandle(fd);\n    if (handle == INVALID_HANDLE_VALUE) {\n        return -1;\n    }\n\n    Py_BEGIN_ALLOW_THREADS\n    success = GetNamedPipeHandleStateW(handle, &mode,\n                                       NULL, NULL, NULL, NULL, 0);\n    if (success) {\n        if (blocking) {\n            mode &= ~PIPE_NOWAIT;\n        }\n        else {\n            mode |= PIPE_NOWAIT;\n        }\n        success = SetNamedPipeHandleState(handle, &mode, NULL, NULL);\n    }\n    Py_END_ALLOW_THREADS\n\n    if (!success) {\n        PyErr_SetFromWindowsErr(0);\n        return -1;\n    }\n    return 0;\n}\n\nvoid*\n_Py_get_osfhandle_noraise(int fd)\n{\n    void *handle;\n    _Py_BEGIN_SUPPRESS_IPH\n    handle = (void*)_get_osfhandle(fd);\n    _Py_END_SUPPRESS_IPH\n    return handle;\n}\n\nvoid*\n_Py_get_osfhandle(int fd)\n{\n    void *handle = _Py_get_osfhandle_noraise(fd);\n    if (handle == INVALID_HANDLE_VALUE)\n        PyErr_SetFromErrno(PyExc_OSError);\n\n    return handle;\n}\n\nint\n_Py_open_osfhandle_noraise(void *handle, int flags)\n{\n    int fd;\n    _Py_BEGIN_SUPPRESS_IPH\n    fd = _open_osfhandle((intptr_t)handle, flags);\n    _Py_END_SUPPRESS_IPH\n    return fd;\n}\n\nint\n_Py_open_osfhandle(void *handle, int flags)\n{\n    int fd = _Py_open_osfhandle_noraise(handle, flags);\n    if (fd == -1)\n        PyErr_SetFromErrno(PyExc_OSError);\n\n    return fd;\n}\n#endif  /* MS_WINDOWS */\n\nint\n_Py_GetLocaleconvNumeric(struct lconv *lc,\n                         PyObject **decimal_point, PyObject **thousands_sep)\n{\n    assert(decimal_point != NULL);\n    assert(thousands_sep != NULL);\n\n#ifndef MS_WINDOWS\n    int change_locale = 0;\n    if ((strlen(lc->decimal_point) > 1 || ((unsigned char)lc->decimal_point[0]) > 127)) {\n        change_locale = 1;\n    }\n    if ((strlen(lc->thousands_sep) > 1 || ((unsigned char)lc->thousands_sep[0]) > 127)) {\n        change_locale = 1;\n    }\n\n    /* Keep a copy of the LC_CTYPE locale */\n    char *oldloc = NULL, *loc = NULL;\n    if (change_locale) {\n        oldloc = setlocale(LC_CTYPE, NULL);\n        if (!oldloc) {\n            PyErr_SetString(PyExc_RuntimeWarning,\n                            \"failed to get LC_CTYPE locale\");\n            return -1;\n        }\n\n        oldloc = _PyMem_Strdup(oldloc);\n        if (!oldloc) {\n            PyErr_NoMemory();\n            return -1;\n        }\n\n        loc = setlocale(LC_NUMERIC, NULL);\n        if (loc != NULL && strcmp(loc, oldloc) == 0) {\n            loc = NULL;\n        }\n\n        if (loc != NULL) {\n            /* Only set the locale temporarily the LC_CTYPE locale\n               if LC_NUMERIC locale is different than LC_CTYPE locale and\n               decimal_point and/or thousands_sep are non-ASCII or longer than\n               1 byte */\n            setlocale(LC_CTYPE, loc);\n        }\n    }\n\n#define GET_LOCALE_STRING(ATTR) PyUnicode_DecodeLocale(lc->ATTR, NULL)\n#else /* MS_WINDOWS */\n/* Use _W_* fields of Windows strcut lconv */\n#define GET_LOCALE_STRING(ATTR) PyUnicode_FromWideChar(lc->_W_ ## ATTR, -1)\n#endif /* MS_WINDOWS */\n\n    int res = -1;\n\n    *decimal_point = GET_LOCALE_STRING(decimal_point);\n    if (*decimal_point == NULL) {\n        goto done;\n    }\n\n    *thousands_sep = GET_LOCALE_STRING(thousands_sep);\n    if (*thousands_sep == NULL) {\n        goto done;\n    }\n\n    res = 0;\n\ndone:\n#ifndef MS_WINDOWS\n    if (loc != NULL) {\n        setlocale(LC_CTYPE, oldloc);\n    }\n    PyMem_Free(oldloc);\n#endif\n    return res;\n\n#undef GET_LOCALE_STRING\n}\n\n/* Our selection logic for which function to use is as follows:\n * 1. If close_range(2) is available, always prefer that; it's better for\n *    contiguous ranges like this than fdwalk(3) which entails iterating over\n *    the entire fd space and simply doing nothing for those outside the range.\n * 2. If closefrom(2) is available, we'll attempt to use that next if we're\n *    closing up to sysconf(_SC_OPEN_MAX).\n * 2a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),\n *    as that will be more performant if the range happens to have any chunk of\n *    non-opened fd in the middle.\n * 2b. If fdwalk(3) isn't available, just do a plain close(2) loop.\n */\n#ifdef __FreeBSD__\n#  define USE_CLOSEFROM\n#endif /* __FreeBSD__ */\n\n#ifdef HAVE_FDWALK\n#  define USE_FDWALK\n#endif /* HAVE_FDWALK */\n\n#ifdef USE_FDWALK\nstatic int\n_fdwalk_close_func(void *lohi, int fd)\n{\n    int lo = ((int *)lohi)[0];\n    int hi = ((int *)lohi)[1];\n\n    if (fd >= hi) {\n        return 1;\n    }\n    else if (fd >= lo) {\n        /* Ignore errors */\n        (void)close(fd);\n    }\n    return 0;\n}\n#endif /* USE_FDWALK */\n\n/* Closes all file descriptors in [first, last], ignoring errors. */\nvoid\n_Py_closerange(int first, int last)\n{\n    first = Py_MAX(first, 0);\n    _Py_BEGIN_SUPPRESS_IPH\n#ifdef HAVE_CLOSE_RANGE\n    if (close_range(first, last, 0) == 0) {\n        /* close_range() ignores errors when it closes file descriptors.\n         * Possible reasons of an error return are lack of kernel support\n         * or denial of the underlying syscall by a seccomp sandbox on Linux.\n         * Fallback to other methods in case of any error. */\n    }\n    else\n#endif /* HAVE_CLOSE_RANGE */\n#ifdef USE_CLOSEFROM\n    if (last >= sysconf(_SC_OPEN_MAX)) {\n        /* Any errors encountered while closing file descriptors are ignored */\n        closefrom(first);\n    }\n    else\n#endif /* USE_CLOSEFROM */\n#ifdef USE_FDWALK\n    {\n        int lohi[2];\n        lohi[0] = first;\n        lohi[1] = last + 1;\n        fdwalk(_fdwalk_close_func, lohi);\n    }\n#else\n    {\n        for (int i = first; i <= last; i++) {\n            /* Ignore errors */\n            (void)close(i);\n        }\n    }\n#endif /* USE_FDWALK */\n    _Py_END_SUPPRESS_IPH\n}\n"
  },
  {
    "path": "Flowgraph.c",
    "content": "\n#include <stdbool.h>\n\n#include \"Python.h\"\n#include \"pycore_flowgraph.h\"\n#include \"pycore_compile.h\"\n#include \"pycore_pymem.h\"         // _PyMem_IsPtrFreed()\n\n#include \"pycore_opcode_utils.h\"\n#define NEED_OPCODE_METADATA\n#include \"opcode_metadata.h\"      // _PyOpcode_opcode_metadata, _PyOpcode_num_popped/pushed\n#undef NEED_OPCODE_METADATA\n\n\n#undef SUCCESS\n#undef ERROR\n#define SUCCESS 0\n#define ERROR -1\n\n#define RETURN_IF_ERROR(X)  \\\n    if ((X) == -1) {        \\\n        return ERROR;       \\\n    }\n\n#define DEFAULT_BLOCK_SIZE 16\n\ntypedef _PyCompilerSrcLocation location;\ntypedef _PyCfgJumpTargetLabel jump_target_label;\ntypedef _PyCfgBasicblock basicblock;\ntypedef _PyCfgBuilder cfg_builder;\ntypedef _PyCfgInstruction cfg_instr;\n\nstatic const jump_target_label NO_LABEL = {-1};\n\n#define SAME_LABEL(L1, L2) ((L1).id == (L2).id)\n#define IS_LABEL(L) (!SAME_LABEL((L), (NO_LABEL)))\n\n\nstatic inline int\nis_block_push(cfg_instr *i)\n{\n    return IS_BLOCK_PUSH_OPCODE(i->i_opcode);\n}\n\nstatic inline int\nis_jump(cfg_instr *i)\n{\n    return IS_JUMP_OPCODE(i->i_opcode);\n}\n\n/* One arg*/\n#define INSTR_SET_OP1(I, OP, ARG) \\\n    do { \\\n        assert(HAS_ARG(OP)); \\\n        _PyCfgInstruction *_instr__ptr_ = (I); \\\n        _instr__ptr_->i_opcode = (OP); \\\n        _instr__ptr_->i_oparg = (ARG); \\\n    } while (0);\n\n/* No args*/\n#define INSTR_SET_OP0(I, OP) \\\n    do { \\\n        assert(!HAS_ARG(OP)); \\\n        _PyCfgInstruction *_instr__ptr_ = (I); \\\n        _instr__ptr_->i_opcode = (OP); \\\n        _instr__ptr_->i_oparg = 0; \\\n    } while (0);\n\n/***** Blocks *****/\n\n/* Returns the offset of the next instruction in the current block's\n   b_instr array.  Resizes the b_instr as necessary.\n   Returns -1 on failure.\n*/\nstatic int\nbasicblock_next_instr(basicblock *b)\n{\n    assert(b != NULL);\n    RETURN_IF_ERROR(\n        _PyCompile_EnsureArrayLargeEnough(\n            b->b_iused + 1,\n            (void**)&b->b_instr,\n            &b->b_ialloc,\n            DEFAULT_BLOCK_SIZE,\n            sizeof(cfg_instr)));\n    return b->b_iused++;\n}\n\n/* Allocate a new block and return a pointer to it.\n   Returns NULL on error.\n*/\n\nstatic basicblock *\ncfg_builder_new_block(cfg_builder *g)\n{\n    basicblock *b = (basicblock *)PyObject_Calloc(1, sizeof(basicblock));\n    if (b == NULL) {\n        PyErr_NoMemory();\n        return NULL;\n    }\n    /* Extend the singly linked list of blocks with new block. */\n    b->b_list = g->g_block_list;\n    g->g_block_list = b;\n    b->b_label = NO_LABEL;\n    return b;\n}\n\nstatic int\nbasicblock_addop(basicblock *b, int opcode, int oparg, location loc)\n{\n    assert(IS_WITHIN_OPCODE_RANGE(opcode));\n    assert(!IS_ASSEMBLER_OPCODE(opcode));\n    assert(HAS_ARG(opcode) || HAS_TARGET(opcode) || oparg == 0);\n    assert(0 <= oparg && oparg < (1 << 30));\n\n    int off = basicblock_next_instr(b);\n    if (off < 0) {\n        return ERROR;\n    }\n    cfg_instr *i = &b->b_instr[off];\n    i->i_opcode = opcode;\n    i->i_oparg = oparg;\n    i->i_target = NULL;\n    i->i_loc = loc;\n\n    return SUCCESS;\n}\n\nstatic inline int\nbasicblock_append_instructions(basicblock *target, basicblock *source)\n{\n    for (int i = 0; i < source->b_iused; i++) {\n        int n = basicblock_next_instr(target);\n        if (n < 0) {\n            return ERROR;\n        }\n        target->b_instr[n] = source->b_instr[i];\n    }\n    return SUCCESS;\n}\n\nstatic basicblock *\ncopy_basicblock(cfg_builder *g, basicblock *block)\n{\n    /* Cannot copy a block if it has a fallthrough, since\n     * a block can only have one fallthrough predecessor.\n     */\n    assert(BB_NO_FALLTHROUGH(block));\n    basicblock *result = cfg_builder_new_block(g);\n    if (result == NULL) {\n        return NULL;\n    }\n    if (basicblock_append_instructions(result, block) < 0) {\n        return NULL;\n    }\n    return result;\n}\n\nint\n_PyBasicblock_InsertInstruction(basicblock *block, int pos, cfg_instr *instr) {\n    RETURN_IF_ERROR(basicblock_next_instr(block));\n    for (int i = block->b_iused - 1; i > pos; i--) {\n        block->b_instr[i] = block->b_instr[i-1];\n    }\n    block->b_instr[pos] = *instr;\n    return SUCCESS;\n}\n\nstatic int\ninstr_size(cfg_instr *instruction)\n{\n    return _PyCompile_InstrSize(instruction->i_opcode, instruction->i_oparg);\n}\n\nstatic int\nblocksize(basicblock *b)\n{\n    int size = 0;\n    for (int i = 0; i < b->b_iused; i++) {\n        size += instr_size(&b->b_instr[i]);\n    }\n    return size;\n}\n\n/* For debugging purposes only */\n#if 0\nstatic void\ndump_instr(cfg_instr *i)\n{\n    const char *jump = is_jump(i) ? \"jump \" : \"\";\n\n    char arg[128];\n\n    *arg = '\\0';\n    if (HAS_ARG(i->i_opcode)) {\n        sprintf(arg, \"arg: %d \", i->i_oparg);\n    }\n    if (HAS_TARGET(i->i_opcode)) {\n        sprintf(arg, \"target: %p [%d] \", i->i_target, i->i_oparg);\n    }\n    fprintf(stderr, \"line: %d, opcode: %d %s%s\\n\",\n                    i->i_loc.lineno, i->i_opcode, arg, jump);\n}\n\nstatic inline int\nbasicblock_returns(const basicblock *b) {\n    cfg_instr *last = _PyCfg_BasicblockLastInstr(b);\n    return last && (last->i_opcode == RETURN_VALUE || last->i_opcode == RETURN_CONST);\n}\n\nstatic void\ndump_basicblock(const basicblock *b)\n{\n    const char *b_return = basicblock_returns(b) ? \"return \" : \"\";\n    fprintf(stderr, \"%d: [EH=%d CLD=%d WRM=%d NO_FT=%d %p] used: %d, depth: %d, offset: %d %s\\n\",\n        b->b_label.id, b->b_except_handler, b->b_cold, b->b_warm, BB_NO_FALLTHROUGH(b), b, b->b_iused,\n        b->b_startdepth, b->b_offset, b_return);\n    if (b->b_instr) {\n        int i;\n        for (i = 0; i < b->b_iused; i++) {\n            fprintf(stderr, \"  [%02d] \", i);\n            dump_instr(b->b_instr + i);\n        }\n    }\n}\n\nvoid\n_PyCfgBuilder_DumpGraph(const basicblock *entryblock)\n{\n    for (const basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        dump_basicblock(b);\n    }\n}\n\n#endif\n\n\n/***** CFG construction and modification *****/\n\nstatic basicblock *\ncfg_builder_use_next_block(cfg_builder *g, basicblock *block)\n{\n    assert(block != NULL);\n    g->g_curblock->b_next = block;\n    g->g_curblock = block;\n    return block;\n}\n\ncfg_instr *\n_PyCfg_BasicblockLastInstr(const basicblock *b) {\n    assert(b->b_iused >= 0);\n    if (b->b_iused > 0) {\n        assert(b->b_instr != NULL);\n        return &b->b_instr[b->b_iused - 1];\n    }\n    return NULL;\n}\n\nstatic inline int\nbasicblock_exits_scope(const basicblock *b) {\n    cfg_instr *last = _PyCfg_BasicblockLastInstr(b);\n    return last && IS_SCOPE_EXIT_OPCODE(last->i_opcode);\n}\n\nstatic bool\ncfg_builder_current_block_is_terminated(cfg_builder *g)\n{\n    cfg_instr *last = _PyCfg_BasicblockLastInstr(g->g_curblock);\n    if (last && IS_TERMINATOR_OPCODE(last->i_opcode)) {\n        return true;\n    }\n    if (IS_LABEL(g->g_current_label)) {\n        if (last || IS_LABEL(g->g_curblock->b_label)) {\n            return true;\n        }\n        else {\n            /* current block is empty, label it */\n            g->g_curblock->b_label = g->g_current_label;\n            g->g_current_label = NO_LABEL;\n        }\n    }\n    return false;\n}\n\nstatic int\ncfg_builder_maybe_start_new_block(cfg_builder *g)\n{\n    if (cfg_builder_current_block_is_terminated(g)) {\n        basicblock *b = cfg_builder_new_block(g);\n        if (b == NULL) {\n            return ERROR;\n        }\n        b->b_label = g->g_current_label;\n        g->g_current_label = NO_LABEL;\n        cfg_builder_use_next_block(g, b);\n    }\n    return SUCCESS;\n}\n\n#ifndef NDEBUG\nstatic bool\ncfg_builder_check(cfg_builder *g)\n{\n    assert(g->g_entryblock->b_iused > 0);\n    for (basicblock *block = g->g_block_list; block != NULL; block = block->b_list) {\n        assert(!_PyMem_IsPtrFreed(block));\n        if (block->b_instr != NULL) {\n            assert(block->b_ialloc > 0);\n            assert(block->b_iused >= 0);\n            assert(block->b_ialloc >= block->b_iused);\n        }\n        else {\n            assert (block->b_iused == 0);\n            assert (block->b_ialloc == 0);\n        }\n    }\n    return true;\n}\n#endif\n\nint\n_PyCfgBuilder_Init(cfg_builder *g)\n{\n    g->g_block_list = NULL;\n    basicblock *block = cfg_builder_new_block(g);\n    if (block == NULL) {\n        return ERROR;\n    }\n    g->g_curblock = g->g_entryblock = block;\n    g->g_current_label = NO_LABEL;\n    return SUCCESS;\n}\n\nvoid\n_PyCfgBuilder_Fini(cfg_builder* g)\n{\n    assert(cfg_builder_check(g));\n    basicblock *b = g->g_block_list;\n    while (b != NULL) {\n        if (b->b_instr) {\n            PyObject_Free((void *)b->b_instr);\n        }\n        basicblock *next = b->b_list;\n        PyObject_Free((void *)b);\n        b = next;\n    }\n}\n\nint\n_PyCfgBuilder_UseLabel(cfg_builder *g, jump_target_label lbl)\n{\n    g->g_current_label = lbl;\n    return cfg_builder_maybe_start_new_block(g);\n}\n\nint\n_PyCfgBuilder_Addop(cfg_builder *g, int opcode, int oparg, location loc)\n{\n    RETURN_IF_ERROR(cfg_builder_maybe_start_new_block(g));\n    return basicblock_addop(g->g_curblock, opcode, oparg, loc);\n}\n\n\n/***** debugging helpers *****/\n\n#ifndef NDEBUG\nstatic int remove_redundant_nops(basicblock *bb);\n\nstatic bool\nno_redundant_nops(cfg_builder *g) {\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        if (remove_redundant_nops(b) != 0) {\n            return false;\n        }\n    }\n    return true;\n}\n\nstatic bool\nno_empty_basic_blocks(cfg_builder *g) {\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        if (b->b_iused == 0) {\n            return false;\n        }\n    }\n    return true;\n}\n\nstatic bool\nno_redundant_jumps(cfg_builder *g) {\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        cfg_instr *last = _PyCfg_BasicblockLastInstr(b);\n        if (last != NULL) {\n            if (IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {\n                assert(last->i_target != b->b_next);\n                if (last->i_target == b->b_next) {\n                    return false;\n                }\n            }\n        }\n    }\n    return true;\n}\n\n#endif\n\n/***** CFG preprocessing (jump targets and exceptions) *****/\n\nstatic int\nnormalize_jumps_in_block(cfg_builder *g, basicblock *b) {\n    cfg_instr *last = _PyCfg_BasicblockLastInstr(b);\n    if (last == NULL || !is_jump(last)) {\n        return SUCCESS;\n    }\n    assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));\n    bool is_forward = last->i_target->b_visited == 0;\n    switch(last->i_opcode) {\n        case JUMP:\n            assert(SAME_OPCODE_METADATA(JUMP, JUMP_FORWARD));\n            assert(SAME_OPCODE_METADATA(JUMP, JUMP_BACKWARD));\n            last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;\n            return SUCCESS;\n        case JUMP_NO_INTERRUPT:\n            assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_FORWARD));\n            assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));\n            last->i_opcode = is_forward ?\n                JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;\n            return SUCCESS;\n    }\n    int reversed_opcode = 0;\n    switch(last->i_opcode) {\n        case POP_JUMP_IF_NOT_NONE:\n            reversed_opcode = POP_JUMP_IF_NONE;\n            break;\n        case POP_JUMP_IF_NONE:\n            reversed_opcode = POP_JUMP_IF_NOT_NONE;\n            break;\n        case POP_JUMP_IF_FALSE:\n            reversed_opcode = POP_JUMP_IF_TRUE;\n            break;\n        case POP_JUMP_IF_TRUE:\n            reversed_opcode = POP_JUMP_IF_FALSE;\n            break;\n    }\n    if (is_forward) {\n        return SUCCESS;\n    }\n    /* transform 'conditional jump T' to\n     * 'reversed_jump b_next' followed by 'jump_backwards T'\n     */\n\n    basicblock *target = last->i_target;\n    basicblock *backwards_jump = cfg_builder_new_block(g);\n    if (backwards_jump == NULL) {\n        return ERROR;\n    }\n    basicblock_addop(backwards_jump, JUMP, target->b_label.id, NO_LOCATION);\n    backwards_jump->b_instr[0].i_target = target;\n    last->i_opcode = reversed_opcode;\n    last->i_target = b->b_next;\n\n    backwards_jump->b_cold = b->b_cold;\n    backwards_jump->b_next = b->b_next;\n    b->b_next = backwards_jump;\n    return SUCCESS;\n}\n\n\nstatic int\nnormalize_jumps(_PyCfgBuilder *g)\n{\n    basicblock *entryblock = g->g_entryblock;\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        b->b_visited = 0;\n    }\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        b->b_visited = 1;\n        RETURN_IF_ERROR(normalize_jumps_in_block(g, b));\n    }\n    return SUCCESS;\n}\n\nstatic void\nresolve_jump_offsets(basicblock *entryblock)\n{\n    int bsize, totsize, extended_arg_recompile;\n\n    /* Compute the size of each block and fixup jump args.\n       Replace block pointer with position in bytecode. */\n    do {\n        totsize = 0;\n        for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n            bsize = blocksize(b);\n            b->b_offset = totsize;\n            totsize += bsize;\n        }\n        extended_arg_recompile = 0;\n        for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n            bsize = b->b_offset;\n            for (int i = 0; i < b->b_iused; i++) {\n                cfg_instr *instr = &b->b_instr[i];\n                int isize = instr_size(instr);\n                /* jump offsets are computed relative to\n                 * the instruction pointer after fetching\n                 * the jump instruction.\n                 */\n                bsize += isize;\n                if (is_jump(instr)) {\n                    instr->i_oparg = instr->i_target->b_offset;\n                    if (instr->i_oparg < bsize) {\n                        assert(IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));\n                        instr->i_oparg = bsize - instr->i_oparg;\n                    }\n                    else {\n                        assert(!IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));\n                        instr->i_oparg -= bsize;\n                    }\n                    if (instr_size(instr) != isize) {\n                        extended_arg_recompile = 1;\n                    }\n                }\n            }\n        }\n\n    /* XXX: This is an awful hack that could hurt performance, but\n        on the bright side it should work until we come up\n        with a better solution.\n\n        The issue is that in the first loop blocksize() is called\n        which calls instr_size() which requires i_oparg be set\n        appropriately. There is a bootstrap problem because\n        i_oparg is calculated in the second loop above.\n\n        So we loop until we stop seeing new EXTENDED_ARGs.\n        The only EXTENDED_ARGs that could be popping up are\n        ones in jump instructions.  So this should converge\n        fairly quickly.\n    */\n    } while (extended_arg_recompile);\n}\n\nint\n_PyCfg_ResolveJumps(_PyCfgBuilder *g)\n{\n    RETURN_IF_ERROR(normalize_jumps(g));\n    assert(no_redundant_jumps(g));\n    resolve_jump_offsets(g->g_entryblock);\n    return SUCCESS;\n}\n\nstatic int\ncheck_cfg(cfg_builder *g) {\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        /* Raise SystemError if jump or exit is not last instruction in the block. */\n        for (int i = 0; i < b->b_iused; i++) {\n            int opcode = b->b_instr[i].i_opcode;\n            assert(!IS_ASSEMBLER_OPCODE(opcode));\n            if (IS_TERMINATOR_OPCODE(opcode)) {\n                if (i != b->b_iused - 1) {\n                    PyErr_SetString(PyExc_SystemError, \"malformed control flow graph.\");\n                    return ERROR;\n                }\n            }\n        }\n    }\n    return SUCCESS;\n}\n\n/* Calculate the actual jump target from the target_label */\nstatic int\ntranslate_jump_labels_to_targets(basicblock *entryblock)\n{\n    int max_label = -1;\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        if (b->b_label.id > max_label) {\n            max_label = b->b_label.id;\n        }\n    }\n    size_t mapsize = sizeof(basicblock *) * (max_label + 1);\n    basicblock **label2block = (basicblock **)PyMem_Malloc(mapsize);\n    if (!label2block) {\n        PyErr_NoMemory();\n        return ERROR;\n    }\n    memset(label2block, 0, mapsize);\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        if (b->b_label.id >= 0) {\n            label2block[b->b_label.id] = b;\n        }\n    }\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        for (int i = 0; i < b->b_iused; i++) {\n            cfg_instr *instr = &b->b_instr[i];\n            assert(instr->i_target == NULL);\n            if (HAS_TARGET(instr->i_opcode)) {\n                int lbl = instr->i_oparg;\n                assert(lbl >= 0 && lbl <= max_label);\n                instr->i_target = label2block[lbl];\n                assert(instr->i_target != NULL);\n                assert(instr->i_target->b_label.id == lbl);\n            }\n        }\n    }\n    PyMem_Free(label2block);\n    return SUCCESS;\n}\n\nint\n_PyCfg_JumpLabelsToTargets(basicblock *entryblock)\n{\n    return translate_jump_labels_to_targets(entryblock);\n}\n\nstatic int\nmark_except_handlers(basicblock *entryblock) {\n#ifndef NDEBUG\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        assert(!b->b_except_handler);\n    }\n#endif\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        for (int i=0; i < b->b_iused; i++) {\n            cfg_instr *instr = &b->b_instr[i];\n            if (is_block_push(instr)) {\n                instr->i_target->b_except_handler = 1;\n            }\n        }\n    }\n    return SUCCESS;\n}\n\n\ntypedef _PyCfgExceptStack ExceptStack;\n\nstatic basicblock *\npush_except_block(ExceptStack *stack, cfg_instr *setup) {\n    assert(is_block_push(setup));\n    int opcode = setup->i_opcode;\n    basicblock * target = setup->i_target;\n    if (opcode == SETUP_WITH || opcode == SETUP_CLEANUP) {\n        target->b_preserve_lasti = 1;\n    }\n    stack->handlers[++stack->depth] = target;\n    return target;\n}\n\nstatic basicblock *\npop_except_block(ExceptStack *stack) {\n    assert(stack->depth > 0);\n    return stack->handlers[--stack->depth];\n}\n\nstatic basicblock *\nexcept_stack_top(ExceptStack *stack) {\n    return stack->handlers[stack->depth];\n}\n\nstatic ExceptStack *\nmake_except_stack(void) {\n    ExceptStack *new = PyMem_Malloc(sizeof(ExceptStack));\n    if (new == NULL) {\n        PyErr_NoMemory();\n        return NULL;\n    }\n    new->depth = 0;\n    new->handlers[0] = NULL;\n    return new;\n}\n\nstatic ExceptStack *\ncopy_except_stack(ExceptStack *stack) {\n    ExceptStack *copy = PyMem_Malloc(sizeof(ExceptStack));\n    if (copy == NULL) {\n        PyErr_NoMemory();\n        return NULL;\n    }\n    memcpy(copy, stack, sizeof(ExceptStack));\n    return copy;\n}\n\nstatic basicblock**\nmake_cfg_traversal_stack(basicblock *entryblock) {\n    int nblocks = 0;\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        b->b_visited = 0;\n        nblocks++;\n    }\n    basicblock **stack = (basicblock **)PyMem_Malloc(sizeof(basicblock *) * nblocks);\n    if (!stack) {\n        PyErr_NoMemory();\n    }\n    return stack;\n}\n\nPy_LOCAL_INLINE(void)\nstackdepth_push(basicblock ***sp, basicblock *b, int depth)\n{\n    assert(b->b_startdepth < 0 || b->b_startdepth == depth);\n    if (b->b_startdepth < depth && b->b_startdepth < 100) {\n        assert(b->b_startdepth < 0);\n        b->b_startdepth = depth;\n        *(*sp)++ = b;\n    }\n}\n\n/* Find the flow path that needs the largest stack.  We assume that\n * cycles in the flow graph have no net effect on the stack depth.\n */\nint\n_PyCfg_Stackdepth(basicblock *entryblock, int code_flags)\n{\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        b->b_startdepth = INT_MIN;\n    }\n    basicblock **stack = make_cfg_traversal_stack(entryblock);\n    if (!stack) {\n        return ERROR;\n    }\n\n    int maxdepth = 0;\n    basicblock **sp = stack;\n    if (code_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) {\n        stackdepth_push(&sp, entryblock, 1);\n    } else {\n        stackdepth_push(&sp, entryblock, 0);\n    }\n\n    while (sp != stack) {\n        basicblock *b = *--sp;\n        int depth = b->b_startdepth;\n        assert(depth >= 0);\n        basicblock *next = b->b_next;\n        for (int i = 0; i < b->b_iused; i++) {\n            cfg_instr *instr = &b->b_instr[i];\n            int effect = PyCompile_OpcodeStackEffectWithJump(instr->i_opcode, instr->i_oparg, 0);\n            if (effect == PY_INVALID_STACK_EFFECT) {\n                PyErr_Format(PyExc_SystemError,\n                             \"compiler PyCompile_OpcodeStackEffectWithJump(opcode=%d, arg=%i) failed\",\n                             instr->i_opcode, instr->i_oparg);\n                return ERROR;\n            }\n            int new_depth = depth + effect;\n            assert(new_depth >= 0); /* invalid code or bug in stackdepth() */\n            if (new_depth > maxdepth) {\n                maxdepth = new_depth;\n            }\n            if (HAS_TARGET(instr->i_opcode)) {\n                effect = PyCompile_OpcodeStackEffectWithJump(instr->i_opcode, instr->i_oparg, 1);\n                assert(effect != PY_INVALID_STACK_EFFECT);\n                int target_depth = depth + effect;\n                assert(target_depth >= 0); /* invalid code or bug in stackdepth() */\n                if (target_depth > maxdepth) {\n                    maxdepth = target_depth;\n                }\n                stackdepth_push(&sp, instr->i_target, target_depth);\n            }\n            depth = new_depth;\n            assert(!IS_ASSEMBLER_OPCODE(instr->i_opcode));\n            if (IS_UNCONDITIONAL_JUMP_OPCODE(instr->i_opcode) ||\n                IS_SCOPE_EXIT_OPCODE(instr->i_opcode))\n            {\n                /* remaining code is dead */\n                next = NULL;\n                break;\n            }\n        }\n        if (next != NULL) {\n            assert(BB_HAS_FALLTHROUGH(b));\n            stackdepth_push(&sp, next, depth);\n        }\n    }\n    PyMem_Free(stack);\n    return maxdepth;\n}\n\nstatic int\nlabel_exception_targets(basicblock *entryblock) {\n    basicblock **todo_stack = make_cfg_traversal_stack(entryblock);\n    if (todo_stack == NULL) {\n        return ERROR;\n    }\n    ExceptStack *except_stack = make_except_stack();\n    if (except_stack == NULL) {\n        PyMem_Free(todo_stack);\n        PyErr_NoMemory();\n        return ERROR;\n    }\n    except_stack->depth = 0;\n    todo_stack[0] = entryblock;\n    entryblock->b_visited = 1;\n    entryblock->b_exceptstack = except_stack;\n    basicblock **todo = &todo_stack[1];\n    basicblock *handler = NULL;\n    while (todo > todo_stack) {\n        todo--;\n        basicblock *b = todo[0];\n        assert(b->b_visited == 1);\n        except_stack = b->b_exceptstack;\n        assert(except_stack != NULL);\n        b->b_exceptstack = NULL;\n        handler = except_stack_top(except_stack);\n        for (int i = 0; i < b->b_iused; i++) {\n            cfg_instr *instr = &b->b_instr[i];\n            if (is_block_push(instr)) {\n                if (!instr->i_target->b_visited) {\n                    ExceptStack *copy = copy_except_stack(except_stack);\n                    if (copy == NULL) {\n                        goto error;\n                    }\n                    instr->i_target->b_exceptstack = copy;\n                    todo[0] = instr->i_target;\n                    instr->i_target->b_visited = 1;\n                    todo++;\n                }\n                handler = push_except_block(except_stack, instr);\n            }\n            else if (instr->i_opcode == POP_BLOCK) {\n                handler = pop_except_block(except_stack);\n            }\n            else if (is_jump(instr)) {\n                instr->i_except = handler;\n                assert(i == b->b_iused -1);\n                if (!instr->i_target->b_visited) {\n                    if (BB_HAS_FALLTHROUGH(b)) {\n                        ExceptStack *copy = copy_except_stack(except_stack);\n                        if (copy == NULL) {\n                            goto error;\n                        }\n                        instr->i_target->b_exceptstack = copy;\n                    }\n                    else {\n                        instr->i_target->b_exceptstack = except_stack;\n                        except_stack = NULL;\n                    }\n                    todo[0] = instr->i_target;\n                    instr->i_target->b_visited = 1;\n                    todo++;\n                }\n            }\n            else {\n                if (instr->i_opcode == YIELD_VALUE) {\n                    instr->i_oparg = except_stack->depth;\n                }\n                instr->i_except = handler;\n            }\n        }\n        if (BB_HAS_FALLTHROUGH(b) && !b->b_next->b_visited) {\n            assert(except_stack != NULL);\n            b->b_next->b_exceptstack = except_stack;\n            todo[0] = b->b_next;\n            b->b_next->b_visited = 1;\n            todo++;\n        }\n        else if (except_stack != NULL) {\n           PyMem_Free(except_stack);\n        }\n    }\n#ifdef Py_DEBUG\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        assert(b->b_exceptstack == NULL);\n    }\n#endif\n    PyMem_Free(todo_stack);\n    return SUCCESS;\nerror:\n    PyMem_Free(todo_stack);\n    PyMem_Free(except_stack);\n    return ERROR;\n}\n\n/***** CFG optimizations *****/\n\nstatic int\nmark_reachable(basicblock *entryblock) {\n    basicblock **stack = make_cfg_traversal_stack(entryblock);\n    if (stack == NULL) {\n        return ERROR;\n    }\n    basicblock **sp = stack;\n    entryblock->b_predecessors = 1;\n    *sp++ = entryblock;\n    while (sp > stack) {\n        basicblock *b = *(--sp);\n        b->b_visited = 1;\n        if (b->b_next && BB_HAS_FALLTHROUGH(b)) {\n            if (!b->b_next->b_visited) {\n                assert(b->b_next->b_predecessors == 0);\n                *sp++ = b->b_next;\n            }\n            b->b_next->b_predecessors++;\n        }\n        for (int i = 0; i < b->b_iused; i++) {\n            basicblock *target;\n            cfg_instr *instr = &b->b_instr[i];\n            if (is_jump(instr) || is_block_push(instr)) {\n                target = instr->i_target;\n                if (!target->b_visited) {\n                    assert(target->b_predecessors == 0 || target == b->b_next);\n                    *sp++ = target;\n                }\n                target->b_predecessors++;\n            }\n        }\n    }\n    PyMem_Free(stack);\n    return SUCCESS;\n}\n\nstatic void\neliminate_empty_basic_blocks(cfg_builder *g) {\n    /* Eliminate empty blocks */\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        basicblock *next = b->b_next;\n        while (next && next->b_iused == 0) {\n            next = next->b_next;\n        }\n        b->b_next = next;\n    }\n    while(g->g_entryblock && g->g_entryblock->b_iused == 0) {\n        g->g_entryblock = g->g_entryblock->b_next;\n    }\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        assert(b->b_iused > 0);\n        for (int i = 0; i < b->b_iused; i++) {\n            cfg_instr *instr = &b->b_instr[i];\n            if (HAS_TARGET(instr->i_opcode)) {\n                basicblock *target = instr->i_target;\n                while (target->b_iused == 0) {\n                    target = target->b_next;\n                }\n                instr->i_target = target;\n                assert(instr->i_target && instr->i_target->b_iused > 0);\n            }\n        }\n    }\n}\n\nstatic int\nremove_redundant_nops(basicblock *bb) {\n    /* Remove NOPs when legal to do so. */\n    int dest = 0;\n    int prev_lineno = -1;\n    for (int src = 0; src < bb->b_iused; src++) {\n        int lineno = bb->b_instr[src].i_loc.lineno;\n        if (bb->b_instr[src].i_opcode == NOP) {\n            /* Eliminate no-op if it doesn't have a line number */\n            if (lineno < 0) {\n                continue;\n            }\n            /* or, if the previous instruction had the same line number. */\n            if (prev_lineno == lineno) {\n                continue;\n            }\n            /* or, if the next instruction has same line number or no line number */\n            if (src < bb->b_iused - 1) {\n                int next_lineno = bb->b_instr[src+1].i_loc.lineno;\n                if (next_lineno == lineno) {\n                    continue;\n                }\n                if (next_lineno < 0) {\n                    bb->b_instr[src+1].i_loc = bb->b_instr[src].i_loc;\n                    continue;\n                }\n            }\n            else {\n                basicblock* next = bb->b_next;\n                while (next && next->b_iused == 0) {\n                    next = next->b_next;\n                }\n                /* or if last instruction in BB and next BB has same line number */\n                if (next) {\n                    if (lineno == next->b_instr[0].i_loc.lineno) {\n                        continue;\n                    }\n                }\n            }\n\n        }\n        if (dest != src) {\n            bb->b_instr[dest] = bb->b_instr[src];\n        }\n        dest++;\n        prev_lineno = lineno;\n    }\n    assert(dest <= bb->b_iused);\n    int num_removed = bb->b_iused - dest;\n    bb->b_iused = dest;\n    return num_removed;\n}\n\nstatic int\nremove_redundant_nops_and_pairs(basicblock *entryblock)\n{\n    bool done = false;\n\n    while (! done) {\n        done = true;\n        cfg_instr *prev_instr = NULL;\n        cfg_instr *instr = NULL;\n        for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n            remove_redundant_nops(b);\n            if (IS_LABEL(b->b_label)) {\n                /* this block is a jump target, forget instr */\n                instr = NULL;\n            }\n            for (int i = 0; i < b->b_iused; i++) {\n                prev_instr = instr;\n                instr = &b->b_instr[i];\n                int prev_opcode = prev_instr ? prev_instr->i_opcode : 0;\n                int prev_oparg = prev_instr ? prev_instr->i_oparg : 0;\n                int opcode = instr->i_opcode;\n                bool is_redundant_pair = false;\n                if (opcode == POP_TOP) {\n                   if (prev_opcode == LOAD_CONST) {\n                       is_redundant_pair = true;\n                   }\n                   else if (prev_opcode == COPY && prev_oparg == 1) {\n                       is_redundant_pair = true;\n                   }\n                }\n                if (is_redundant_pair) {\n                    INSTR_SET_OP0(prev_instr, NOP);\n                    INSTR_SET_OP0(instr, NOP);\n                    done = false;\n                }\n            }\n            if ((instr && is_jump(instr)) || !BB_HAS_FALLTHROUGH(b)) {\n                instr = NULL;\n            }\n        }\n    }\n    return SUCCESS;\n}\n\nstatic int\nremove_redundant_jumps(cfg_builder *g) {\n    /* If a non-empty block ends with a jump instruction, check if the next\n     * non-empty block reached through normal flow control is the target\n     * of that jump. If it is, then the jump instruction is redundant and\n     * can be deleted.\n     */\n    assert(no_empty_basic_blocks(g));\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        cfg_instr *last = _PyCfg_BasicblockLastInstr(b);\n        assert(last != NULL);\n        assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));\n        if (IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {\n            if (last->i_target == NULL) {\n                PyErr_SetString(PyExc_SystemError, \"jump with NULL target\");\n                return ERROR;\n            }\n            if (last->i_target == b->b_next) {\n                assert(b->b_next->b_iused);\n                INSTR_SET_OP0(last, NOP);\n            }\n        }\n    }\n    return SUCCESS;\n}\n\n/* Maximum size of basic block that should be copied in optimizer */\n#define MAX_COPY_SIZE 4\n\n/* If this block ends with an unconditional jump to a small exit block, then\n * remove the jump and extend this block with the target.\n * Returns 1 if extended, 0 if no change, and -1 on error.\n */\nstatic int\ninline_small_exit_blocks(basicblock *bb) {\n    cfg_instr *last = _PyCfg_BasicblockLastInstr(bb);\n    if (last == NULL) {\n        return 0;\n    }\n    if (!IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {\n        return 0;\n    }\n    basicblock *target = last->i_target;\n    if (basicblock_exits_scope(target) && target->b_iused <= MAX_COPY_SIZE) {\n        INSTR_SET_OP0(last, NOP);\n        RETURN_IF_ERROR(basicblock_append_instructions(bb, target));\n        return 1;\n    }\n    return 0;\n}\n\n// Attempt to eliminate jumps to jumps by updating inst to jump to\n// target->i_target using the provided opcode. Return whether or not the\n// optimization was successful.\nstatic bool\njump_thread(cfg_instr *inst, cfg_instr *target, int opcode)\n{\n    assert(is_jump(inst));\n    assert(is_jump(target));\n    // bpo-45773: If inst->i_target == target->i_target, then nothing actually\n    // changes (and we fall into an infinite loop):\n    if ((inst->i_loc.lineno == target->i_loc.lineno || target->i_loc.lineno == -1) &&\n        inst->i_target != target->i_target)\n    {\n        inst->i_target = target->i_target;\n        inst->i_opcode = opcode;\n        return true;\n    }\n    return false;\n}\n\nstatic PyObject*\nget_const_value(int opcode, int oparg, PyObject *co_consts)\n{\n    PyObject *constant = NULL;\n    assert(HAS_CONST(opcode));\n    if (opcode == LOAD_CONST) {\n        constant = PyList_GET_ITEM(co_consts, oparg);\n    }\n\n    if (constant == NULL) {\n        PyErr_SetString(PyExc_SystemError,\n                        \"Internal error: failed to get value of a constant\");\n        return NULL;\n    }\n    return Py_NewRef(constant);\n}\n\n/* Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cn, BUILD_TUPLE n\n   with    LOAD_CONST (c1, c2, ... cn).\n   The consts table must still be in list form so that the\n   new constant (c1, c2, ... cn) can be appended.\n   Called with codestr pointing to the first LOAD_CONST.\n*/\nstatic int\nfold_tuple_on_constants(PyObject *const_cache,\n                        cfg_instr *inst,\n                        int n, PyObject *consts)\n{\n    /* Pre-conditions */\n    assert(PyDict_CheckExact(const_cache));\n    assert(PyList_CheckExact(consts));\n    assert(inst[n].i_opcode == BUILD_TUPLE);\n    assert(inst[n].i_oparg == n);\n\n    for (int i = 0; i < n; i++) {\n        if (!HAS_CONST(inst[i].i_opcode)) {\n            return SUCCESS;\n        }\n    }\n\n    /* Buildup new tuple of constants */\n    PyObject *newconst = PyTuple_New(n);\n    if (newconst == NULL) {\n        return ERROR;\n    }\n    for (int i = 0; i < n; i++) {\n        int op = inst[i].i_opcode;\n        int arg = inst[i].i_oparg;\n        PyObject *constant = get_const_value(op, arg, consts);\n        if (constant == NULL) {\n            return ERROR;\n        }\n        PyTuple_SET_ITEM(newconst, i, constant);\n    }\n    if (_PyCompile_ConstCacheMergeOne(const_cache, &newconst) < 0) {\n        Py_DECREF(newconst);\n        return ERROR;\n    }\n\n    Py_ssize_t index;\n    for (index = 0; index < PyList_GET_SIZE(consts); index++) {\n        if (PyList_GET_ITEM(consts, index) == newconst) {\n            break;\n        }\n    }\n    if (index == PyList_GET_SIZE(consts)) {\n        if ((size_t)index >= (size_t)INT_MAX - 1) {\n            Py_DECREF(newconst);\n            PyErr_SetString(PyExc_OverflowError, \"too many constants\");\n            return ERROR;\n        }\n        if (PyList_Append(consts, newconst)) {\n            Py_DECREF(newconst);\n            return ERROR;\n        }\n    }\n    Py_DECREF(newconst);\n    for (int i = 0; i < n; i++) {\n        INSTR_SET_OP0(&inst[i], NOP);\n    }\n    INSTR_SET_OP1(&inst[n], LOAD_CONST, (int)index);\n    return SUCCESS;\n}\n\n#define VISITED (-1)\n\n// Replace an arbitrary run of SWAPs and NOPs with an optimal one that has the\n// same effect.\nstatic int\nswaptimize(basicblock *block, int *ix)\n{\n    // NOTE: \"./python -m test test_patma\" serves as a good, quick stress test\n    // for this function. Make sure to blow away cached *.pyc files first!\n    assert(*ix < block->b_iused);\n    cfg_instr *instructions = &block->b_instr[*ix];\n    // Find the length of the current sequence of SWAPs and NOPs, and record the\n    // maximum depth of the stack manipulations:\n    assert(instructions[0].i_opcode == SWAP);\n    int depth = instructions[0].i_oparg;\n    int len = 0;\n    int more = false;\n    int limit = block->b_iused - *ix;\n    while (++len < limit) {\n        int opcode = instructions[len].i_opcode;\n        if (opcode == SWAP) {\n            depth = Py_MAX(depth, instructions[len].i_oparg);\n            more = true;\n        }\n        else if (opcode != NOP) {\n            break;\n        }\n    }\n    // It's already optimal if there's only one SWAP:\n    if (!more) {\n        return SUCCESS;\n    }\n    // Create an array with elements {0, 1, 2, ..., depth - 1}:\n    int *stack = PyMem_Malloc(depth * sizeof(int));\n    if (stack == NULL) {\n        PyErr_NoMemory();\n        return ERROR;\n    }\n    for (int i = 0; i < depth; i++) {\n        stack[i] = i;\n    }\n    // Simulate the combined effect of these instructions by \"running\" them on\n    // our \"stack\":\n    for (int i = 0; i < len; i++) {\n        if (instructions[i].i_opcode == SWAP) {\n            int oparg = instructions[i].i_oparg;\n            int top = stack[0];\n            // SWAPs are 1-indexed:\n            stack[0] = stack[oparg - 1];\n            stack[oparg - 1] = top;\n        }\n    }\n    // Now we can begin! Our approach here is based on a solution to a closely\n    // related problem (https://cs.stackexchange.com/a/13938). It's easiest to\n    // think of this algorithm as determining the steps needed to efficiently\n    // \"un-shuffle\" our stack. By performing the moves in *reverse* order,\n    // though, we can efficiently *shuffle* it! For this reason, we will be\n    // replacing instructions starting from the *end* of the run. Since the\n    // solution is optimal, we don't need to worry about running out of space:\n    int current = len - 1;\n    for (int i = 0; i < depth; i++) {\n        // Skip items that have already been visited, or just happen to be in\n        // the correct location:\n        if (stack[i] == VISITED || stack[i] == i) {\n            continue;\n        }\n        // Okay, we've found an item that hasn't been visited. It forms a cycle\n        // with other items; traversing the cycle and swapping each item with\n        // the next will put them all in the correct place. The weird\n        // loop-and-a-half is necessary to insert 0 into every cycle, since we\n        // can only swap from that position:\n        int j = i;\n        while (true) {\n            // Skip the actual swap if our item is zero, since swapping the top\n            // item with itself is pointless:\n            if (j) {\n                assert(0 <= current);\n                // SWAPs are 1-indexed:\n                instructions[current].i_opcode = SWAP;\n                instructions[current--].i_oparg = j + 1;\n            }\n            if (stack[j] == VISITED) {\n                // Completed the cycle:\n                assert(j == i);\n                break;\n            }\n            int next_j = stack[j];\n            stack[j] = VISITED;\n            j = next_j;\n        }\n    }\n    // NOP out any unused instructions:\n    while (0 <= current) {\n        INSTR_SET_OP0(&instructions[current--], NOP);\n    }\n    PyMem_Free(stack);\n    *ix += len - 1;\n    return SUCCESS;\n}\n\n\n// This list is pretty small, since it's only okay to reorder opcodes that:\n// - can't affect control flow (like jumping or raising exceptions)\n// - can't invoke arbitrary code (besides finalizers)\n// - only touch the TOS (and pop it when finished)\n#define SWAPPABLE(opcode) \\\n    ((opcode) == STORE_FAST || \\\n     (opcode) == STORE_FAST_MAYBE_NULL || \\\n     (opcode) == POP_TOP)\n\n#define STORES_TO(instr) \\\n    (((instr).i_opcode == STORE_FAST || \\\n      (instr).i_opcode == STORE_FAST_MAYBE_NULL) \\\n     ? (instr).i_oparg : -1)\n\nstatic int\nnext_swappable_instruction(basicblock *block, int i, int lineno)\n{\n    while (++i < block->b_iused) {\n        cfg_instr *instruction = &block->b_instr[i];\n        if (0 <= lineno && instruction->i_loc.lineno != lineno) {\n            // Optimizing across this instruction could cause user-visible\n            // changes in the names bound between line tracing events!\n            return -1;\n        }\n        if (instruction->i_opcode == NOP) {\n            continue;\n        }\n        if (SWAPPABLE(instruction->i_opcode)) {\n            return i;\n        }\n        return -1;\n    }\n    return -1;\n}\n\n// Attempt to apply SWAPs statically by swapping *instructions* rather than\n// stack items. For example, we can replace SWAP(2), POP_TOP, STORE_FAST(42)\n// with the more efficient NOP, STORE_FAST(42), POP_TOP.\nstatic void\napply_static_swaps(basicblock *block, int i)\n{\n    // SWAPs are to our left, and potential swaperands are to our right:\n    for (; 0 <= i; i--) {\n        assert(i < block->b_iused);\n        cfg_instr *swap = &block->b_instr[i];\n        if (swap->i_opcode != SWAP) {\n            if (swap->i_opcode == NOP || SWAPPABLE(swap->i_opcode)) {\n                // Nope, but we know how to handle these. Keep looking:\n                continue;\n            }\n            // We can't reason about what this instruction does. Bail:\n            return;\n        }\n        int j = next_swappable_instruction(block, i, -1);\n        if (j < 0) {\n            return;\n        }\n        int k = j;\n        int lineno = block->b_instr[j].i_loc.lineno;\n        for (int count = swap->i_oparg - 1; 0 < count; count--) {\n            k = next_swappable_instruction(block, k, lineno);\n            if (k < 0) {\n                return;\n            }\n        }\n        // The reordering is not safe if the two instructions to be swapped\n        // store to the same location, or if any intervening instruction stores\n        // to the same location as either of them.\n        int store_j = STORES_TO(block->b_instr[j]);\n        int store_k = STORES_TO(block->b_instr[k]);\n        if (store_j >= 0 || store_k >= 0) {\n            if (store_j == store_k) {\n                return;\n            }\n            for (int idx = j + 1; idx < k; idx++) {\n                int store_idx = STORES_TO(block->b_instr[idx]);\n                if (store_idx >= 0 && (store_idx == store_j || store_idx == store_k)) {\n                    return;\n                }\n            }\n        }\n\n        // Success!\n        INSTR_SET_OP0(swap, NOP);\n        cfg_instr temp = block->b_instr[j];\n        block->b_instr[j] = block->b_instr[k];\n        block->b_instr[k] = temp;\n    }\n}\n\nstatic int\noptimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)\n{\n    assert(PyDict_CheckExact(const_cache));\n    assert(PyList_CheckExact(consts));\n    cfg_instr nop;\n    INSTR_SET_OP0(&nop, NOP);\n    cfg_instr *target = &nop;\n    int opcode = 0;\n    int oparg = 0;\n    int nextop = 0;\n    for (int i = 0; i < bb->b_iused; i++) {\n        cfg_instr *inst = &bb->b_instr[i];\n        bool is_copy_of_load_const = (opcode == LOAD_CONST &&\n                                      inst->i_opcode == COPY &&\n                                      inst->i_oparg == 1);\n        if (! is_copy_of_load_const) {\n            opcode = inst->i_opcode;\n            oparg = inst->i_oparg;\n            if (HAS_TARGET(opcode)) {\n                assert(inst->i_target->b_iused > 0);\n                target = &inst->i_target->b_instr[0];\n                assert(!IS_ASSEMBLER_OPCODE(target->i_opcode));\n            }\n            else {\n                target = &nop;\n            }\n        }\n        nextop = i+1 < bb->b_iused ? bb->b_instr[i+1].i_opcode : 0;\n        assert(!IS_ASSEMBLER_OPCODE(opcode));\n        switch (opcode) {\n            /* Remove LOAD_CONST const; conditional jump */\n            case LOAD_CONST:\n            {\n                PyObject* cnt;\n                int is_true;\n                int jump_if_true;\n                switch(nextop) {\n                    case POP_JUMP_IF_FALSE:\n                    case POP_JUMP_IF_TRUE:\n                        cnt = get_const_value(opcode, oparg, consts);\n                        if (cnt == NULL) {\n                            goto error;\n                        }\n                        is_true = PyObject_IsTrue(cnt);\n                        Py_DECREF(cnt);\n                        if (is_true == -1) {\n                            goto error;\n                        }\n                        INSTR_SET_OP0(inst, NOP);\n                        jump_if_true = nextop == POP_JUMP_IF_TRUE;\n                        if (is_true == jump_if_true) {\n                            bb->b_instr[i+1].i_opcode = JUMP;\n                        }\n                        else {\n                            INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);\n                        }\n                        break;\n                    case IS_OP:\n                        cnt = get_const_value(opcode, oparg, consts);\n                        if (cnt == NULL) {\n                            goto error;\n                        }\n                        int jump_op = i+2 < bb->b_iused ? bb->b_instr[i+2].i_opcode : 0;\n                        if (Py_IsNone(cnt) && (jump_op == POP_JUMP_IF_FALSE || jump_op == POP_JUMP_IF_TRUE)) {\n                            unsigned char nextarg = bb->b_instr[i+1].i_oparg;\n                            INSTR_SET_OP0(inst, NOP);\n                            INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);\n                            bb->b_instr[i+2].i_opcode = nextarg ^ (jump_op == POP_JUMP_IF_FALSE) ?\n                                    POP_JUMP_IF_NOT_NONE : POP_JUMP_IF_NONE;\n                        }\n                        Py_DECREF(cnt);\n                        break;\n                    case RETURN_VALUE:\n                        INSTR_SET_OP0(inst, NOP);\n                        INSTR_SET_OP1(&bb->b_instr[++i], RETURN_CONST, oparg);\n                        break;\n                }\n                break;\n            }\n                /* Try to fold tuples of constants.\n                   Skip over BUILD_TUPLE(1) UNPACK_SEQUENCE(1).\n                   Replace BUILD_TUPLE(2) UNPACK_SEQUENCE(2) with SWAP(2).\n                   Replace BUILD_TUPLE(3) UNPACK_SEQUENCE(3) with SWAP(3). */\n            case BUILD_TUPLE:\n                if (nextop == UNPACK_SEQUENCE && oparg == bb->b_instr[i+1].i_oparg) {\n                    switch(oparg) {\n                        case 1:\n                            INSTR_SET_OP0(inst, NOP);\n                            INSTR_SET_OP0(&bb->b_instr[i + 1], NOP);\n                            continue;\n                        case 2:\n                        case 3:\n                            INSTR_SET_OP0(inst, NOP);\n                            bb->b_instr[i+1].i_opcode = SWAP;\n                            continue;\n                    }\n                }\n                if (i >= oparg) {\n                    if (fold_tuple_on_constants(const_cache, inst-oparg, oparg, consts)) {\n                        goto error;\n                    }\n                }\n                break;\n            case POP_JUMP_IF_NOT_NONE:\n            case POP_JUMP_IF_NONE:\n                switch (target->i_opcode) {\n                    case JUMP:\n                        i -= jump_thread(inst, target, inst->i_opcode);\n                }\n                break;\n            case POP_JUMP_IF_FALSE:\n                switch (target->i_opcode) {\n                    case JUMP:\n                        i -= jump_thread(inst, target, POP_JUMP_IF_FALSE);\n                }\n                break;\n            case POP_JUMP_IF_TRUE:\n                switch (target->i_opcode) {\n                    case JUMP:\n                        i -= jump_thread(inst, target, POP_JUMP_IF_TRUE);\n                }\n                break;\n            case JUMP:\n                switch (target->i_opcode) {\n                    case JUMP:\n                        i -= jump_thread(inst, target, JUMP);\n                }\n                break;\n            case FOR_ITER:\n                if (target->i_opcode == JUMP) {\n                    /* This will not work now because the jump (at target) could\n                     * be forward or backward and FOR_ITER only jumps forward. We\n                     * can re-enable this if ever we implement a backward version\n                     * of FOR_ITER.\n                     */\n                    /*\n                    i -= jump_thread(inst, target, FOR_ITER);\n                    */\n                }\n                break;\n            case STORE_FAST:\n                if (opcode == nextop &&\n                    oparg == bb->b_instr[i+1].i_oparg &&\n                    bb->b_instr[i].i_loc.lineno == bb->b_instr[i+1].i_loc.lineno) {\n                    bb->b_instr[i].i_opcode = POP_TOP;\n                    bb->b_instr[i].i_oparg = 0;\n                }\n                break;\n            case SWAP:\n                if (oparg == 1) {\n                    INSTR_SET_OP0(inst, NOP);\n                }\n                break;\n            case KW_NAMES:\n                break;\n            case PUSH_NULL:\n                if (nextop == LOAD_GLOBAL && (inst[1].i_opcode & 1) == 0) {\n                    INSTR_SET_OP0(inst, NOP);\n                    inst[1].i_oparg |= 1;\n                }\n                break;\n            default:\n                /* All HAS_CONST opcodes should be handled with LOAD_CONST */\n                assert (!HAS_CONST(inst->i_opcode));\n        }\n    }\n\n    for (int i = 0; i < bb->b_iused; i++) {\n        cfg_instr *inst = &bb->b_instr[i];\n        if (inst->i_opcode == SWAP) {\n            if (swaptimize(bb, &i) < 0) {\n                goto error;\n            }\n            apply_static_swaps(bb, i);\n        }\n    }\n    return SUCCESS;\nerror:\n    return ERROR;\n}\n\n\n/* Perform optimizations on a control flow graph.\n   The consts object should still be in list form to allow new constants\n   to be appended.\n\n   Code trasnformations that reduce code size initially fill the gaps with\n   NOPs.  Later those NOPs are removed.\n*/\nstatic int\noptimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)\n{\n    assert(PyDict_CheckExact(const_cache));\n    RETURN_IF_ERROR(check_cfg(g));\n    eliminate_empty_basic_blocks(g);\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        RETURN_IF_ERROR(inline_small_exit_blocks(b));\n    }\n    assert(no_empty_basic_blocks(g));\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        RETURN_IF_ERROR(optimize_basic_block(const_cache, b, consts));\n        assert(b->b_predecessors == 0);\n    }\n    RETURN_IF_ERROR(remove_redundant_nops_and_pairs(g->g_entryblock));\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        RETURN_IF_ERROR(inline_small_exit_blocks(b));\n    }\n    RETURN_IF_ERROR(mark_reachable(g->g_entryblock));\n\n    /* Delete unreachable instructions */\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n       if (b->b_predecessors == 0) {\n            b->b_iused = 0;\n       }\n    }\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        remove_redundant_nops(b);\n    }\n    eliminate_empty_basic_blocks(g);\n    assert(no_redundant_nops(g));\n    RETURN_IF_ERROR(remove_redundant_jumps(g));\n    return SUCCESS;\n}\n\nstatic void\nmake_super_instruction(cfg_instr *inst1, cfg_instr *inst2, int super_op)\n{\n    int32_t line1 = inst1->i_loc.lineno;\n    int32_t line2 = inst2->i_loc.lineno;\n    /* Skip if instructions are on different lines */\n    if (line1 >= 0 && line2 >= 0 && line1 != line2) {\n        return;\n    }\n    if (inst1->i_oparg >= 16 || inst2->i_oparg >= 16) {\n        return;\n    }\n    INSTR_SET_OP1(inst1, super_op, (inst1->i_oparg << 4) | inst2->i_oparg);\n    INSTR_SET_OP0(inst2, NOP);\n}\n\nstatic void\ninsert_superinstructions(cfg_builder *g)\n{\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n\n        for (int i = 0; i < b->b_iused; i++) {\n            cfg_instr *inst = &b->b_instr[i];\n            int nextop = i+1 < b->b_iused ? b->b_instr[i+1].i_opcode : 0;\n            switch(inst->i_opcode) {\n                case LOAD_FAST:\n                    if (nextop == LOAD_FAST) {\n                        make_super_instruction(inst, &b->b_instr[i + 1], LOAD_FAST_LOAD_FAST);\n                    }\n                    break;\n                case STORE_FAST:\n                    switch (nextop) {\n                        case LOAD_FAST:\n                            make_super_instruction(inst, &b->b_instr[i + 1], STORE_FAST_LOAD_FAST);\n                            break;\n                        case STORE_FAST:\n                            make_super_instruction(inst, &b->b_instr[i + 1], STORE_FAST_STORE_FAST);\n                            break;\n                    }\n                    break;\n            }\n        }\n    }\n    for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {\n        remove_redundant_nops(b);\n    }\n    eliminate_empty_basic_blocks(g);\n    assert(no_redundant_nops(g));\n}\n\n// helper functions for add_checks_for_loads_of_unknown_variables\nstatic inline void\nmaybe_push(basicblock *b, uint64_t unsafe_mask, basicblock ***sp)\n{\n    // Push b if the unsafe mask is giving us any new information.\n    // To avoid overflowing the stack, only allow each block once.\n    // Use b->b_visited=1 to mean that b is currently on the stack.\n    uint64_t both = b->b_unsafe_locals_mask | unsafe_mask;\n    if (b->b_unsafe_locals_mask != both) {\n        b->b_unsafe_locals_mask = both;\n        // More work left to do.\n        if (!b->b_visited) {\n            // not on the stack, so push it.\n            *(*sp)++ = b;\n            b->b_visited = 1;\n        }\n    }\n}\n\nstatic void\nscan_block_for_locals(basicblock *b, basicblock ***sp)\n{\n    // bit i is set if local i is potentially uninitialized\n    uint64_t unsafe_mask = b->b_unsafe_locals_mask;\n    for (int i = 0; i < b->b_iused; i++) {\n        cfg_instr *instr = &b->b_instr[i];\n        assert(instr->i_opcode != EXTENDED_ARG);\n        if (instr->i_except != NULL) {\n            maybe_push(instr->i_except, unsafe_mask, sp);\n        }\n        if (instr->i_oparg >= 64) {\n            continue;\n        }\n        assert(instr->i_oparg >= 0);\n        uint64_t bit = (uint64_t)1 << instr->i_oparg;\n        switch (instr->i_opcode) {\n            case DELETE_FAST:\n            case LOAD_FAST_AND_CLEAR:\n            case STORE_FAST_MAYBE_NULL:\n                unsafe_mask |= bit;\n                break;\n            case STORE_FAST:\n                unsafe_mask &= ~bit;\n                break;\n            case LOAD_FAST_CHECK:\n                // If this doesn't raise, then the local is defined.\n                unsafe_mask &= ~bit;\n                break;\n            case LOAD_FAST:\n                if (unsafe_mask & bit) {\n                    instr->i_opcode = LOAD_FAST_CHECK;\n                }\n                unsafe_mask &= ~bit;\n                break;\n        }\n    }\n    if (b->b_next && BB_HAS_FALLTHROUGH(b)) {\n        maybe_push(b->b_next, unsafe_mask, sp);\n    }\n    cfg_instr *last = _PyCfg_BasicblockLastInstr(b);\n    if (last && is_jump(last)) {\n        assert(last->i_target != NULL);\n        maybe_push(last->i_target, unsafe_mask, sp);\n    }\n}\n\nstatic int\nfast_scan_many_locals(basicblock *entryblock, int nlocals)\n{\n    assert(nlocals > 64);\n    Py_ssize_t *states = PyMem_Calloc(nlocals - 64, sizeof(Py_ssize_t));\n    if (states == NULL) {\n        PyErr_NoMemory();\n        return ERROR;\n    }\n    Py_ssize_t blocknum = 0;\n    // state[i - 64] == blocknum if local i is guaranteed to\n    // be initialized, i.e., if it has had a previous LOAD_FAST or\n    // STORE_FAST within that basicblock (not followed by\n    // DELETE_FAST/LOAD_FAST_AND_CLEAR/STORE_FAST_MAYBE_NULL).\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        blocknum++;\n        for (int i = 0; i < b->b_iused; i++) {\n            cfg_instr *instr = &b->b_instr[i];\n            assert(instr->i_opcode != EXTENDED_ARG);\n            int arg = instr->i_oparg;\n            if (arg < 64) {\n                continue;\n            }\n            assert(arg >= 0);\n            switch (instr->i_opcode) {\n                case DELETE_FAST:\n                case LOAD_FAST_AND_CLEAR:\n                case STORE_FAST_MAYBE_NULL:\n                    states[arg - 64] = blocknum - 1;\n                    break;\n                case STORE_FAST:\n                    states[arg - 64] = blocknum;\n                    break;\n                case LOAD_FAST:\n                    if (states[arg - 64] != blocknum) {\n                        instr->i_opcode = LOAD_FAST_CHECK;\n                    }\n                    states[arg - 64] = blocknum;\n                    break;\n                    Py_UNREACHABLE();\n            }\n        }\n    }\n    PyMem_Free(states);\n    return SUCCESS;\n}\n\nstatic int\nremove_unused_consts(basicblock *entryblock, PyObject *consts)\n{\n    assert(PyList_CheckExact(consts));\n    Py_ssize_t nconsts = PyList_GET_SIZE(consts);\n    if (nconsts == 0) {\n        return SUCCESS;  /* nothing to do */\n    }\n\n    Py_ssize_t *index_map = NULL;\n    Py_ssize_t *reverse_index_map = NULL;\n    int err = ERROR;\n\n    index_map = PyMem_Malloc(nconsts * sizeof(Py_ssize_t));\n    if (index_map == NULL) {\n        goto end;\n    }\n    for (Py_ssize_t i = 1; i < nconsts; i++) {\n        index_map[i] = -1;\n    }\n    // The first constant may be docstring; keep it always.\n    index_map[0] = 0;\n\n    /* mark used consts */\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        for (int i = 0; i < b->b_iused; i++) {\n            if (HAS_CONST(b->b_instr[i].i_opcode)) {\n                int index = b->b_instr[i].i_oparg;\n                index_map[index] = index;\n            }\n        }\n    }\n    /* now index_map[i] == i if consts[i] is used, -1 otherwise */\n    /* condense consts */\n    Py_ssize_t n_used_consts = 0;\n    for (int i = 0; i < nconsts; i++) {\n        if (index_map[i] != -1) {\n            assert(index_map[i] == i);\n            index_map[n_used_consts++] = index_map[i];\n        }\n    }\n    if (n_used_consts == nconsts) {\n        /* nothing to do */\n        err = SUCCESS;\n        goto end;\n    }\n\n    /* move all used consts to the beginning of the consts list */\n    assert(n_used_consts < nconsts);\n    for (Py_ssize_t i = 0; i < n_used_consts; i++) {\n        Py_ssize_t old_index = index_map[i];\n        assert(i <= old_index && old_index < nconsts);\n        if (i != old_index) {\n            PyObject *value = PyList_GET_ITEM(consts, index_map[i]);\n            assert(value != NULL);\n            PyList_SetItem(consts, i, Py_NewRef(value));\n        }\n    }\n\n    /* truncate the consts list at its new size */\n    if (PyList_SetSlice(consts, n_used_consts, nconsts, NULL) < 0) {\n        goto end;\n    }\n    /* adjust const indices in the bytecode */\n    reverse_index_map = PyMem_Malloc(nconsts * sizeof(Py_ssize_t));\n    if (reverse_index_map == NULL) {\n        goto end;\n    }\n    for (Py_ssize_t i = 0; i < nconsts; i++) {\n        reverse_index_map[i] = -1;\n    }\n    for (Py_ssize_t i = 0; i < n_used_consts; i++) {\n        assert(index_map[i] != -1);\n        assert(reverse_index_map[index_map[i]] == -1);\n        reverse_index_map[index_map[i]] = i;\n    }\n\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        for (int i = 0; i < b->b_iused; i++) {\n            if (HAS_CONST(b->b_instr[i].i_opcode)) {\n                int index = b->b_instr[i].i_oparg;\n                assert(reverse_index_map[index] >= 0);\n                assert(reverse_index_map[index] < n_used_consts);\n                b->b_instr[i].i_oparg = (int)reverse_index_map[index];\n            }\n        }\n    }\n\n    err = SUCCESS;\nend:\n    PyMem_Free(index_map);\n    PyMem_Free(reverse_index_map);\n    return err;\n}\n\n\n\nstatic int\nadd_checks_for_loads_of_uninitialized_variables(basicblock *entryblock,\n                                                int nlocals,\n                                                int nparams)\n{\n    if (nlocals == 0) {\n        return SUCCESS;\n    }\n    if (nlocals > 64) {\n        // To avoid O(nlocals**2) compilation, locals beyond the first\n        // 64 are only analyzed one basicblock at a time: initialization\n        // info is not passed between basicblocks.\n        if (fast_scan_many_locals(entryblock, nlocals) < 0) {\n            return ERROR;\n        }\n        nlocals = 64;\n    }\n    basicblock **stack = make_cfg_traversal_stack(entryblock);\n    if (stack == NULL) {\n        return ERROR;\n    }\n    basicblock **sp = stack;\n\n    // First origin of being uninitialized:\n    // The non-parameter locals in the entry block.\n    uint64_t start_mask = 0;\n    for (int i = nparams; i < nlocals; i++) {\n        start_mask |= (uint64_t)1 << i;\n    }\n    maybe_push(entryblock, start_mask, &sp);\n\n    // Second origin of being uninitialized:\n    // There could be DELETE_FAST somewhere, so\n    // be sure to scan each basicblock at least once.\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        scan_block_for_locals(b, &sp);\n    }\n    // Now propagate the uncertainty from the origins we found: Use\n    // LOAD_FAST_CHECK for any LOAD_FAST where the local could be undefined.\n    while (sp > stack) {\n        basicblock *b = *--sp;\n        // mark as no longer on stack\n        b->b_visited = 0;\n        scan_block_for_locals(b, &sp);\n    }\n    PyMem_Free(stack);\n    return SUCCESS;\n}\n\n\nstatic int\nmark_warm(basicblock *entryblock) {\n    basicblock **stack = make_cfg_traversal_stack(entryblock);\n    if (stack == NULL) {\n        return ERROR;\n    }\n    basicblock **sp = stack;\n\n    *sp++ = entryblock;\n    entryblock->b_visited = 1;\n    while (sp > stack) {\n        basicblock *b = *(--sp);\n        assert(!b->b_except_handler);\n        b->b_warm = 1;\n        basicblock *next = b->b_next;\n        if (next && BB_HAS_FALLTHROUGH(b) && !next->b_visited) {\n            *sp++ = next;\n            next->b_visited = 1;\n        }\n        for (int i=0; i < b->b_iused; i++) {\n            cfg_instr *instr = &b->b_instr[i];\n            if (is_jump(instr) && !instr->i_target->b_visited) {\n                *sp++ = instr->i_target;\n                instr->i_target->b_visited = 1;\n            }\n        }\n    }\n    PyMem_Free(stack);\n    return SUCCESS;\n}\n\nstatic int\nmark_cold(basicblock *entryblock) {\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        assert(!b->b_cold && !b->b_warm);\n    }\n    if (mark_warm(entryblock) < 0) {\n        return ERROR;\n    }\n\n    basicblock **stack = make_cfg_traversal_stack(entryblock);\n    if (stack == NULL) {\n        return ERROR;\n    }\n\n    basicblock **sp = stack;\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        if (b->b_except_handler) {\n            assert(!b->b_warm);\n            *sp++ = b;\n            b->b_visited = 1;\n        }\n    }\n\n    while (sp > stack) {\n        basicblock *b = *(--sp);\n        b->b_cold = 1;\n        basicblock *next = b->b_next;\n        if (next && BB_HAS_FALLTHROUGH(b)) {\n            if (!next->b_warm && !next->b_visited) {\n                *sp++ = next;\n                next->b_visited = 1;\n            }\n        }\n        for (int i = 0; i < b->b_iused; i++) {\n            cfg_instr *instr = &b->b_instr[i];\n            if (is_jump(instr)) {\n                assert(i == b->b_iused - 1);\n                basicblock *target = b->b_instr[i].i_target;\n                if (!target->b_warm && !target->b_visited) {\n                    *sp++ = target;\n                    target->b_visited = 1;\n                }\n            }\n        }\n    }\n    PyMem_Free(stack);\n    return SUCCESS;\n}\n\n\nstatic int\npush_cold_blocks_to_end(cfg_builder *g, int code_flags) {\n    basicblock *entryblock = g->g_entryblock;\n    if (entryblock->b_next == NULL) {\n        /* single basicblock, no need to reorder */\n        return SUCCESS;\n    }\n    RETURN_IF_ERROR(mark_cold(entryblock));\n\n    /* If we have a cold block with fallthrough to a warm block, add */\n    /* an explicit jump instead of fallthrough */\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        if (b->b_cold && BB_HAS_FALLTHROUGH(b) && b->b_next && b->b_next->b_warm) {\n            basicblock *explicit_jump = cfg_builder_new_block(g);\n            if (explicit_jump == NULL) {\n                return ERROR;\n            }\n            basicblock_addop(explicit_jump, JUMP, b->b_next->b_label.id, NO_LOCATION);\n            explicit_jump->b_cold = 1;\n            explicit_jump->b_next = b->b_next;\n            b->b_next = explicit_jump;\n\n            /* set target */\n            cfg_instr *last = _PyCfg_BasicblockLastInstr(explicit_jump);\n            last->i_target = explicit_jump->b_next;\n        }\n    }\n\n    assert(!entryblock->b_cold);  /* First block can't be cold */\n    basicblock *cold_blocks = NULL;\n    basicblock *cold_blocks_tail = NULL;\n\n    basicblock *b = entryblock;\n    while(b->b_next) {\n        assert(!b->b_cold);\n        while (b->b_next && !b->b_next->b_cold) {\n            b = b->b_next;\n        }\n        if (b->b_next == NULL) {\n            /* no more cold blocks */\n            break;\n        }\n\n        /* b->b_next is the beginning of a cold streak */\n        assert(!b->b_cold && b->b_next->b_cold);\n\n        basicblock *b_end = b->b_next;\n        while (b_end->b_next && b_end->b_next->b_cold) {\n            b_end = b_end->b_next;\n        }\n\n        /* b_end is the end of the cold streak */\n        assert(b_end && b_end->b_cold);\n        assert(b_end->b_next == NULL || !b_end->b_next->b_cold);\n\n        if (cold_blocks == NULL) {\n            cold_blocks = b->b_next;\n        }\n        else {\n            cold_blocks_tail->b_next = b->b_next;\n        }\n        cold_blocks_tail = b_end;\n        b->b_next = b_end->b_next;\n        b_end->b_next = NULL;\n    }\n    assert(b != NULL && b->b_next == NULL);\n    b->b_next = cold_blocks;\n\n    if (cold_blocks != NULL) {\n        RETURN_IF_ERROR(remove_redundant_jumps(g));\n    }\n    return SUCCESS;\n}\n\nvoid\n_PyCfg_ConvertPseudoOps(basicblock *entryblock)\n{\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        for (int i = 0; i < b->b_iused; i++) {\n            cfg_instr *instr = &b->b_instr[i];\n            if (is_block_push(instr) || instr->i_opcode == POP_BLOCK) {\n                assert(SAME_OPCODE_METADATA(instr->i_opcode, NOP));\n                INSTR_SET_OP0(instr, NOP);\n            }\n            else if (instr->i_opcode == STORE_FAST_MAYBE_NULL) {\n                assert(SAME_OPCODE_METADATA(STORE_FAST_MAYBE_NULL, STORE_FAST));\n                instr->i_opcode = STORE_FAST;\n            }\n        }\n    }\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        remove_redundant_nops(b);\n    }\n}\n\nstatic inline bool\nis_exit_without_lineno(basicblock *b) {\n    if (!basicblock_exits_scope(b)) {\n        return false;\n    }\n    for (int i = 0; i < b->b_iused; i++) {\n        if (b->b_instr[i].i_loc.lineno >= 0) {\n            return false;\n        }\n    }\n    return true;\n}\n\n/* PEP 626 mandates that the f_lineno of a frame is correct\n * after a frame terminates. It would be prohibitively expensive\n * to continuously update the f_lineno field at runtime,\n * so we make sure that all exiting instruction (raises and returns)\n * have a valid line number, allowing us to compute f_lineno lazily.\n * We can do this by duplicating the exit blocks without line number\n * so that none have more than one predecessor. We can then safely\n * copy the line number from the sole predecessor block.\n */\nstatic int\nduplicate_exits_without_lineno(cfg_builder *g)\n{\n    assert(no_empty_basic_blocks(g));\n    /* Copy all exit blocks without line number that are targets of a jump.\n     */\n    basicblock *entryblock = g->g_entryblock;\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        cfg_instr *last = _PyCfg_BasicblockLastInstr(b);\n        assert(last != NULL);\n        if (is_jump(last)) {\n            basicblock *target = last->i_target;\n            if (is_exit_without_lineno(target) && target->b_predecessors > 1) {\n                basicblock *new_target = copy_basicblock(g, target);\n                if (new_target == NULL) {\n                    return ERROR;\n                }\n                new_target->b_instr[0].i_loc = last->i_loc;\n                last->i_target = new_target;\n                target->b_predecessors--;\n                new_target->b_predecessors = 1;\n                new_target->b_next = target->b_next;\n                target->b_next = new_target;\n            }\n        }\n    }\n\n    /* Any remaining reachable exit blocks without line number can only be reached by\n     * fall through, and thus can only have a single predecessor */\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        if (BB_HAS_FALLTHROUGH(b) && b->b_next && b->b_iused > 0) {\n            if (is_exit_without_lineno(b->b_next)) {\n                cfg_instr *last = _PyCfg_BasicblockLastInstr(b);\n                assert(last != NULL);\n                b->b_next->b_instr[0].i_loc = last->i_loc;\n            }\n        }\n    }\n    return SUCCESS;\n}\n\n\n/* If an instruction has no line number, but it's predecessor in the BB does,\n * then copy the line number. If a successor block has no line number, and only\n * one predecessor, then inherit the line number.\n * This ensures that all exit blocks (with one predecessor) receive a line number.\n * Also reduces the size of the line number table,\n * but has no impact on the generated line number events.\n */\nstatic void\npropagate_line_numbers(basicblock *entryblock) {\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        cfg_instr *last = _PyCfg_BasicblockLastInstr(b);\n        if (last == NULL) {\n            continue;\n        }\n\n        location prev_location = NO_LOCATION;\n        for (int i = 0; i < b->b_iused; i++) {\n            if (b->b_instr[i].i_loc.lineno < 0) {\n                b->b_instr[i].i_loc = prev_location;\n            }\n            else {\n                prev_location = b->b_instr[i].i_loc;\n            }\n        }\n        if (BB_HAS_FALLTHROUGH(b) && b->b_next->b_predecessors == 1) {\n            assert(b->b_next->b_iused);\n            if (b->b_next->b_instr[0].i_loc.lineno < 0) {\n                b->b_next->b_instr[0].i_loc = prev_location;\n            }\n        }\n        if (is_jump(last)) {\n            basicblock *target = last->i_target;\n            if (target->b_predecessors == 1) {\n                if (target->b_instr[0].i_loc.lineno < 0) {\n                    target->b_instr[0].i_loc = prev_location;\n                }\n            }\n        }\n    }\n}\n\n/* Make sure that all returns have a line number, even if early passes\n * have failed to propagate a correct line number.\n * The resulting line number may not be correct according to PEP 626,\n * but should be \"good enough\", and no worse than in older versions. */\nstatic void\nguarantee_lineno_for_exits(basicblock *entryblock, int firstlineno) {\n    int lineno = firstlineno;\n    assert(lineno > 0);\n    for (basicblock *b = entryblock; b != NULL; b = b->b_next) {\n        cfg_instr *last = _PyCfg_BasicblockLastInstr(b);\n        if (last == NULL) {\n            continue;\n        }\n        if (last->i_loc.lineno < 0) {\n            if (last->i_opcode == RETURN_VALUE) {\n                for (int i = 0; i < b->b_iused; i++) {\n                    assert(b->b_instr[i].i_loc.lineno < 0);\n\n                    b->b_instr[i].i_loc.lineno = lineno;\n                }\n            }\n        }\n        else {\n            lineno = last->i_loc.lineno;\n        }\n    }\n}\n\nstatic int\nresolve_line_numbers(cfg_builder *g, int firstlineno)\n{\n    RETURN_IF_ERROR(duplicate_exits_without_lineno(g));\n    propagate_line_numbers(g->g_entryblock);\n    guarantee_lineno_for_exits(g->g_entryblock, firstlineno);\n    return SUCCESS;\n}\n\nint\n_PyCfg_OptimizeCodeUnit(cfg_builder *g, PyObject *consts, PyObject *const_cache,\n                       int code_flags, int nlocals, int nparams, int firstlineno)\n{\n    assert(cfg_builder_check(g));\n    /** Preprocessing **/\n    /* Map labels to targets and mark exception handlers */\n    RETURN_IF_ERROR(translate_jump_labels_to_targets(g->g_entryblock));\n    RETURN_IF_ERROR(mark_except_handlers(g->g_entryblock));\n    RETURN_IF_ERROR(label_exception_targets(g->g_entryblock));\n\n    /** Optimization **/\n    RETURN_IF_ERROR(optimize_cfg(g, consts, const_cache));\n    RETURN_IF_ERROR(remove_unused_consts(g->g_entryblock, consts));\n    RETURN_IF_ERROR(\n        add_checks_for_loads_of_uninitialized_variables(\n            g->g_entryblock, nlocals, nparams));\n    insert_superinstructions(g);\n\n    RETURN_IF_ERROR(push_cold_blocks_to_end(g, code_flags));\n    RETURN_IF_ERROR(resolve_line_numbers(g, firstlineno));\n    return SUCCESS;\n}\n"
  },
  {
    "path": "Formatter_Unicode.c",
    "content": "/* implements the unicode (as opposed to string) version of the\n   built-in formatters for string, int, float.  that is, the versions\n   of int.__float__, etc., that take and return unicode objects */\n\n#include \"Python.h\"\n#include \"pycore_fileutils.h\"     // _Py_GetLocaleconvNumeric()\n#include \"pycore_long.h\"          // _PyLong_FormatWriter()\n#include <locale.h>\n\n/* Raises an exception about an unknown presentation type for this\n * type. */\n\nstatic void\nunknown_presentation_type(Py_UCS4 presentation_type,\n                          const char* type_name)\n{\n    /* %c might be out-of-range, hence the two cases. */\n    if (presentation_type > 32 && presentation_type < 128)\n        PyErr_Format(PyExc_ValueError,\n                     \"Unknown format code '%c' \"\n                     \"for object of type '%.200s'\",\n                     (char)presentation_type,\n                     type_name);\n    else\n        PyErr_Format(PyExc_ValueError,\n                     \"Unknown format code '\\\\x%x' \"\n                     \"for object of type '%.200s'\",\n                     (unsigned int)presentation_type,\n                     type_name);\n}\n\nstatic void\ninvalid_thousands_separator_type(char specifier, Py_UCS4 presentation_type)\n{\n    assert(specifier == ',' || specifier == '_');\n    if (presentation_type > 32 && presentation_type < 128)\n        PyErr_Format(PyExc_ValueError,\n                     \"Cannot specify '%c' with '%c'.\",\n                     specifier, (char)presentation_type);\n    else\n        PyErr_Format(PyExc_ValueError,\n                     \"Cannot specify '%c' with '\\\\x%x'.\",\n                     specifier, (unsigned int)presentation_type);\n}\n\nstatic void\ninvalid_comma_and_underscore(void)\n{\n    PyErr_Format(PyExc_ValueError, \"Cannot specify both ',' and '_'.\");\n}\n\n/*\n    get_integer consumes 0 or more decimal digit characters from an\n    input string, updates *result with the corresponding positive\n    integer, and returns the number of digits consumed.\n\n    returns -1 on error.\n*/\nstatic int\nget_integer(PyObject *str, Py_ssize_t *ppos, Py_ssize_t end,\n                  Py_ssize_t *result)\n{\n    Py_ssize_t accumulator, digitval, pos = *ppos;\n    int numdigits;\n    int kind = PyUnicode_KIND(str);\n    const void *data = PyUnicode_DATA(str);\n\n    accumulator = numdigits = 0;\n    for (; pos < end; pos++, numdigits++) {\n        digitval = Py_UNICODE_TODECIMAL(PyUnicode_READ(kind, data, pos));\n        if (digitval < 0)\n            break;\n        /*\n           Detect possible overflow before it happens:\n\n              accumulator * 10 + digitval > PY_SSIZE_T_MAX if and only if\n              accumulator > (PY_SSIZE_T_MAX - digitval) / 10.\n        */\n        if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) {\n            PyErr_Format(PyExc_ValueError,\n                         \"Too many decimal digits in format string\");\n            *ppos = pos;\n            return -1;\n        }\n        accumulator = accumulator * 10 + digitval;\n    }\n    *ppos = pos;\n    *result = accumulator;\n    return numdigits;\n}\n\n/************************************************************************/\n/*********** standard format specifier parsing **************************/\n/************************************************************************/\n\n/* returns true if this character is a specifier alignment token */\nPy_LOCAL_INLINE(int)\nis_alignment_token(Py_UCS4 c)\n{\n    switch (c) {\n    case '<': case '>': case '=': case '^':\n        return 1;\n    default:\n        return 0;\n    }\n}\n\n/* returns true if this character is a sign element */\nPy_LOCAL_INLINE(int)\nis_sign_element(Py_UCS4 c)\n{\n    switch (c) {\n    case ' ': case '+': case '-':\n        return 1;\n    default:\n        return 0;\n    }\n}\n\n/* Locale type codes. LT_NO_LOCALE must be zero. */\nenum LocaleType {\n    LT_NO_LOCALE = 0,\n    LT_DEFAULT_LOCALE = ',',\n    LT_UNDERSCORE_LOCALE = '_',\n    LT_UNDER_FOUR_LOCALE,\n    LT_CURRENT_LOCALE\n};\n\ntypedef struct {\n    Py_UCS4 fill_char;\n    Py_UCS4 align;\n    int alternate;\n    int no_neg_0;\n    Py_UCS4 sign;\n    Py_ssize_t width;\n    enum LocaleType thousands_separators;\n    Py_ssize_t precision;\n    Py_UCS4 type;\n} InternalFormatSpec;\n\n\n/*\n  ptr points to the start of the format_spec, end points just past its end.\n  fills in format with the parsed information.\n  returns 1 on success, 0 on failure.\n  if failure, sets the exception\n*/\nstatic int\nparse_internal_render_format_spec(PyObject *obj,\n                                  PyObject *format_spec,\n                                  Py_ssize_t start, Py_ssize_t end,\n                                  InternalFormatSpec *format,\n                                  char default_type,\n                                  char default_align)\n{\n    Py_ssize_t pos = start;\n    int kind = PyUnicode_KIND(format_spec);\n    const void *data = PyUnicode_DATA(format_spec);\n    /* end-pos is used throughout this code to specify the length of\n       the input string */\n#define READ_spec(index) PyUnicode_READ(kind, data, index)\n\n    Py_ssize_t consumed;\n    int align_specified = 0;\n    int fill_char_specified = 0;\n\n    format->fill_char = ' ';\n    format->align = default_align;\n    format->alternate = 0;\n    format->no_neg_0 = 0;\n    format->sign = '\\0';\n    format->width = -1;\n    format->thousands_separators = LT_NO_LOCALE;\n    format->precision = -1;\n    format->type = default_type;\n\n    /* If the second char is an alignment token,\n       then parse the fill char */\n    if (end-pos >= 2 && is_alignment_token(READ_spec(pos+1))) {\n        format->align = READ_spec(pos+1);\n        format->fill_char = READ_spec(pos);\n        fill_char_specified = 1;\n        align_specified = 1;\n        pos += 2;\n    }\n    else if (end-pos >= 1 && is_alignment_token(READ_spec(pos))) {\n        format->align = READ_spec(pos);\n        align_specified = 1;\n        ++pos;\n    }\n\n    /* Parse the various sign options */\n    if (end-pos >= 1 && is_sign_element(READ_spec(pos))) {\n        format->sign = READ_spec(pos);\n        ++pos;\n    }\n\n    /* If the next character is z, request coercion of negative 0.\n       Applies only to floats. */\n    if (end-pos >= 1 && READ_spec(pos) == 'z') {\n        format->no_neg_0 = 1;\n        ++pos;\n    }\n\n    /* If the next character is #, we're in alternate mode.  This only\n       applies to integers. */\n    if (end-pos >= 1 && READ_spec(pos) == '#') {\n        format->alternate = 1;\n        ++pos;\n    }\n\n    /* The special case for 0-padding (backwards compat) */\n    if (!fill_char_specified && end-pos >= 1 && READ_spec(pos) == '0') {\n        format->fill_char = '0';\n        if (!align_specified && default_align == '>') {\n            format->align = '=';\n        }\n        ++pos;\n    }\n\n    consumed = get_integer(format_spec, &pos, end, &format->width);\n    if (consumed == -1)\n        /* Overflow error. Exception already set. */\n        return 0;\n\n    /* If consumed is 0, we didn't consume any characters for the\n       width. In that case, reset the width to -1, because\n       get_integer() will have set it to zero. -1 is how we record\n       that the width wasn't specified. */\n    if (consumed == 0)\n        format->width = -1;\n\n    /* Comma signifies add thousands separators */\n    if (end-pos && READ_spec(pos) == ',') {\n        format->thousands_separators = LT_DEFAULT_LOCALE;\n        ++pos;\n    }\n    /* Underscore signifies add thousands separators */\n    if (end-pos && READ_spec(pos) == '_') {\n        if (format->thousands_separators != LT_NO_LOCALE) {\n            invalid_comma_and_underscore();\n            return 0;\n        }\n        format->thousands_separators = LT_UNDERSCORE_LOCALE;\n        ++pos;\n    }\n    if (end-pos && READ_spec(pos) == ',') {\n        if (format->thousands_separators == LT_UNDERSCORE_LOCALE) {\n            invalid_comma_and_underscore();\n            return 0;\n        }\n    }\n\n    /* Parse field precision */\n    if (end-pos && READ_spec(pos) == '.') {\n        ++pos;\n\n        consumed = get_integer(format_spec, &pos, end, &format->precision);\n        if (consumed == -1)\n            /* Overflow error. Exception already set. */\n            return 0;\n\n        /* Not having a precision after a dot is an error. */\n        if (consumed == 0) {\n            PyErr_Format(PyExc_ValueError,\n                         \"Format specifier missing precision\");\n            return 0;\n        }\n\n    }\n\n    /* Finally, parse the type field. */\n\n    if (end-pos > 1) {\n        /* More than one char remains, so this is an invalid format\n           specifier. */\n        /* Create a temporary object that contains the format spec we're\n           operating on.  It's format_spec[start:end] (in Python syntax). */\n        PyObject* actual_format_spec = PyUnicode_FromKindAndData(kind,\n                                         (char*)data + kind*start,\n                                         end-start);\n        if (actual_format_spec != NULL) {\n            PyErr_Format(PyExc_ValueError,\n                \"Invalid format specifier '%U' for object of type '%.200s'\",\n                actual_format_spec, Py_TYPE(obj)->tp_name);\n            Py_DECREF(actual_format_spec);\n        }\n        return 0;\n    }\n\n    if (end-pos == 1) {\n        format->type = READ_spec(pos);\n        ++pos;\n    }\n\n    /* Do as much validating as we can, just by looking at the format\n       specifier.  Do not take into account what type of formatting\n       we're doing (int, float, string). */\n\n    if (format->thousands_separators) {\n        switch (format->type) {\n        case 'd':\n        case 'e':\n        case 'f':\n        case 'g':\n        case 'E':\n        case 'G':\n        case '%':\n        case 'F':\n        case '\\0':\n            /* These are allowed. See PEP 378.*/\n            break;\n        case 'b':\n        case 'o':\n        case 'x':\n        case 'X':\n            /* Underscores are allowed in bin/oct/hex. See PEP 515. */\n            if (format->thousands_separators == LT_UNDERSCORE_LOCALE) {\n                /* Every four digits, not every three, in bin/oct/hex. */\n                format->thousands_separators = LT_UNDER_FOUR_LOCALE;\n                break;\n            }\n            /* fall through */\n        default:\n            invalid_thousands_separator_type(format->thousands_separators, format->type);\n            return 0;\n        }\n    }\n\n    assert (format->align <= 127);\n    assert (format->sign <= 127);\n    return 1;\n}\n\n/* Calculate the padding needed. */\nstatic void\ncalc_padding(Py_ssize_t nchars, Py_ssize_t width, Py_UCS4 align,\n             Py_ssize_t *n_lpadding, Py_ssize_t *n_rpadding,\n             Py_ssize_t *n_total)\n{\n    if (width >= 0) {\n        if (nchars > width)\n            *n_total = nchars;\n        else\n            *n_total = width;\n    }\n    else {\n        /* not specified, use all of the chars and no more */\n        *n_total = nchars;\n    }\n\n    /* Figure out how much leading space we need, based on the\n       aligning */\n    if (align == '>')\n        *n_lpadding = *n_total - nchars;\n    else if (align == '^')\n        *n_lpadding = (*n_total - nchars) / 2;\n    else if (align == '<' || align == '=')\n        *n_lpadding = 0;\n    else {\n        /* We should never have an unspecified alignment. */\n        Py_UNREACHABLE();\n    }\n\n    *n_rpadding = *n_total - nchars - *n_lpadding;\n}\n\n/* Do the padding, and return a pointer to where the caller-supplied\n   content goes. */\nstatic int\nfill_padding(_PyUnicodeWriter *writer,\n             Py_ssize_t nchars,\n             Py_UCS4 fill_char, Py_ssize_t n_lpadding,\n             Py_ssize_t n_rpadding)\n{\n    Py_ssize_t pos;\n\n    /* Pad on left. */\n    if (n_lpadding) {\n        pos = writer->pos;\n        _PyUnicode_FastFill(writer->buffer, pos, n_lpadding, fill_char);\n    }\n\n    /* Pad on right. */\n    if (n_rpadding) {\n        pos = writer->pos + nchars + n_lpadding;\n        _PyUnicode_FastFill(writer->buffer, pos, n_rpadding, fill_char);\n    }\n\n    /* Pointer to the user content. */\n    writer->pos += n_lpadding;\n    return 0;\n}\n\n/************************************************************************/\n/*********** common routines for numeric formatting *********************/\n/************************************************************************/\n\n/* Locale info needed for formatting integers and the part of floats\n   before and including the decimal. Note that locales only support\n   8-bit chars, not unicode. */\ntypedef struct {\n    PyObject *decimal_point;\n    PyObject *thousands_sep;\n    const char *grouping;\n    char *grouping_buffer;\n} LocaleInfo;\n\n#define LocaleInfo_STATIC_INIT {0, 0, 0, 0}\n\n/* describes the layout for an integer, see the comment in\n   calc_number_widths() for details */\ntypedef struct {\n    Py_ssize_t n_lpadding;\n    Py_ssize_t n_prefix;\n    Py_ssize_t n_spadding;\n    Py_ssize_t n_rpadding;\n    char sign;\n    Py_ssize_t n_sign;      /* number of digits needed for sign (0/1) */\n    Py_ssize_t n_grouped_digits; /* Space taken up by the digits, including\n                                    any grouping chars. */\n    Py_ssize_t n_decimal;   /* 0 if only an integer */\n    Py_ssize_t n_remainder; /* Digits in decimal and/or exponent part,\n                               excluding the decimal itself, if\n                               present. */\n\n    /* These 2 are not the widths of fields, but are needed by\n       STRINGLIB_GROUPING. */\n    Py_ssize_t n_digits;    /* The number of digits before a decimal\n                               or exponent. */\n    Py_ssize_t n_min_width; /* The min_width we used when we computed\n                               the n_grouped_digits width. */\n} NumberFieldWidths;\n\n\n/* Given a number of the form:\n   digits[remainder]\n   where ptr points to the start and end points to the end, find where\n    the integer part ends. This could be a decimal, an exponent, both,\n    or neither.\n   If a decimal point is present, set *has_decimal and increment\n    remainder beyond it.\n   Results are undefined (but shouldn't crash) for improperly\n    formatted strings.\n*/\nstatic void\nparse_number(PyObject *s, Py_ssize_t pos, Py_ssize_t end,\n             Py_ssize_t *n_remainder, int *has_decimal)\n{\n    Py_ssize_t remainder;\n    int kind = PyUnicode_KIND(s);\n    const void *data = PyUnicode_DATA(s);\n\n    while (pos<end && Py_ISDIGIT(PyUnicode_READ(kind, data, pos)))\n        ++pos;\n    remainder = pos;\n\n    /* Does remainder start with a decimal point? */\n    *has_decimal = pos<end && PyUnicode_READ(kind, data, remainder) == '.';\n\n    /* Skip the decimal point. */\n    if (*has_decimal)\n        remainder++;\n\n    *n_remainder = end - remainder;\n}\n\n/* not all fields of format are used.  for example, precision is\n   unused.  should this take discrete params in order to be more clear\n   about what it does?  or is passing a single format parameter easier\n   and more efficient enough to justify a little obfuscation?\n   Return -1 on error. */\nstatic Py_ssize_t\ncalc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix,\n                   Py_UCS4 sign_char, Py_ssize_t n_start,\n                   Py_ssize_t n_end, Py_ssize_t n_remainder,\n                   int has_decimal, const LocaleInfo *locale,\n                   const InternalFormatSpec *format, Py_UCS4 *maxchar)\n{\n    Py_ssize_t n_non_digit_non_padding;\n    Py_ssize_t n_padding;\n\n    spec->n_digits = n_end - n_start - n_remainder - (has_decimal?1:0);\n    spec->n_lpadding = 0;\n    spec->n_prefix = n_prefix;\n    spec->n_decimal = has_decimal ? PyUnicode_GET_LENGTH(locale->decimal_point) : 0;\n    spec->n_remainder = n_remainder;\n    spec->n_spadding = 0;\n    spec->n_rpadding = 0;\n    spec->sign = '\\0';\n    spec->n_sign = 0;\n\n    /* the output will look like:\n       |                                                                                         |\n       | <lpadding> <sign> <prefix> <spadding> <grouped_digits> <decimal> <remainder> <rpadding> |\n       |                                                                                         |\n\n       sign is computed from format->sign and the actual\n       sign of the number\n\n       prefix is given (it's for the '0x' prefix)\n\n       digits is already known\n\n       the total width is either given, or computed from the\n       actual digits\n\n       only one of lpadding, spadding, and rpadding can be non-zero,\n       and it's calculated from the width and other fields\n    */\n\n    /* compute the various parts we're going to write */\n    switch (format->sign) {\n    case '+':\n        /* always put a + or - */\n        spec->n_sign = 1;\n        spec->sign = (sign_char == '-' ? '-' : '+');\n        break;\n    case ' ':\n        spec->n_sign = 1;\n        spec->sign = (sign_char == '-' ? '-' : ' ');\n        break;\n    default:\n        /* Not specified, or the default (-) */\n        if (sign_char == '-') {\n            spec->n_sign = 1;\n            spec->sign = '-';\n        }\n    }\n\n    /* The number of chars used for non-digits and non-padding. */\n    n_non_digit_non_padding = spec->n_sign + spec->n_prefix + spec->n_decimal +\n        spec->n_remainder;\n\n    /* min_width can go negative, that's okay. format->width == -1 means\n       we don't care. */\n    if (format->fill_char == '0' && format->align == '=')\n        spec->n_min_width = format->width - n_non_digit_non_padding;\n    else\n        spec->n_min_width = 0;\n\n    if (spec->n_digits == 0)\n        /* This case only occurs when using 'c' formatting, we need\n           to special case it because the grouping code always wants\n           to have at least one character. */\n        spec->n_grouped_digits = 0;\n    else {\n        Py_UCS4 grouping_maxchar;\n        spec->n_grouped_digits = _PyUnicode_InsertThousandsGrouping(\n            NULL, 0,\n            NULL, 0, spec->n_digits,\n            spec->n_min_width,\n            locale->grouping, locale->thousands_sep, &grouping_maxchar);\n        if (spec->n_grouped_digits == -1) {\n            return -1;\n        }\n        *maxchar = Py_MAX(*maxchar, grouping_maxchar);\n    }\n\n    /* Given the desired width and the total of digit and non-digit\n       space we consume, see if we need any padding. format->width can\n       be negative (meaning no padding), but this code still works in\n       that case. */\n    n_padding = format->width -\n                        (n_non_digit_non_padding + spec->n_grouped_digits);\n    if (n_padding > 0) {\n        /* Some padding is needed. Determine if it's left, space, or right. */\n        switch (format->align) {\n        case '<':\n            spec->n_rpadding = n_padding;\n            break;\n        case '^':\n            spec->n_lpadding = n_padding / 2;\n            spec->n_rpadding = n_padding - spec->n_lpadding;\n            break;\n        case '=':\n            spec->n_spadding = n_padding;\n            break;\n        case '>':\n            spec->n_lpadding = n_padding;\n            break;\n        default:\n            /* Shouldn't get here */\n            Py_UNREACHABLE();\n        }\n    }\n\n    if (spec->n_lpadding || spec->n_spadding || spec->n_rpadding)\n        *maxchar = Py_MAX(*maxchar, format->fill_char);\n\n    if (spec->n_decimal)\n        *maxchar = Py_MAX(*maxchar, PyUnicode_MAX_CHAR_VALUE(locale->decimal_point));\n\n    return spec->n_lpadding + spec->n_sign + spec->n_prefix +\n        spec->n_spadding + spec->n_grouped_digits + spec->n_decimal +\n        spec->n_remainder + spec->n_rpadding;\n}\n\n/* Fill in the digit parts of a number's string representation,\n   as determined in calc_number_widths().\n   Return -1 on error, or 0 on success. */\nstatic int\nfill_number(_PyUnicodeWriter *writer, const NumberFieldWidths *spec,\n            PyObject *digits, Py_ssize_t d_start,\n            PyObject *prefix, Py_ssize_t p_start,\n            Py_UCS4 fill_char,\n            LocaleInfo *locale, int toupper)\n{\n    /* Used to keep track of digits, decimal, and remainder. */\n    Py_ssize_t d_pos = d_start;\n    const int kind = writer->kind;\n    const void *data = writer->data;\n    Py_ssize_t r;\n\n    if (spec->n_lpadding) {\n        _PyUnicode_FastFill(writer->buffer,\n                            writer->pos, spec->n_lpadding, fill_char);\n        writer->pos += spec->n_lpadding;\n    }\n    if (spec->n_sign == 1) {\n        PyUnicode_WRITE(kind, data, writer->pos, spec->sign);\n        writer->pos++;\n    }\n    if (spec->n_prefix) {\n        _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,\n                                      prefix, p_start,\n                                      spec->n_prefix);\n        if (toupper) {\n            Py_ssize_t t;\n            for (t = 0; t < spec->n_prefix; t++) {\n                Py_UCS4 c = PyUnicode_READ(kind, data, writer->pos + t);\n                c = Py_TOUPPER(c);\n                assert (c <= 127);\n                PyUnicode_WRITE(kind, data, writer->pos + t, c);\n            }\n        }\n        writer->pos += spec->n_prefix;\n    }\n    if (spec->n_spadding) {\n        _PyUnicode_FastFill(writer->buffer,\n                            writer->pos, spec->n_spadding, fill_char);\n        writer->pos += spec->n_spadding;\n    }\n\n    /* Only for type 'c' special case, it has no digits. */\n    if (spec->n_digits != 0) {\n        /* Fill the digits with InsertThousandsGrouping. */\n        r = _PyUnicode_InsertThousandsGrouping(\n                writer, spec->n_grouped_digits,\n                digits, d_pos, spec->n_digits,\n                spec->n_min_width,\n                locale->grouping, locale->thousands_sep, NULL);\n        if (r == -1)\n            return -1;\n        assert(r == spec->n_grouped_digits);\n        d_pos += spec->n_digits;\n    }\n    if (toupper) {\n        Py_ssize_t t;\n        for (t = 0; t < spec->n_grouped_digits; t++) {\n            Py_UCS4 c = PyUnicode_READ(kind, data, writer->pos + t);\n            c = Py_TOUPPER(c);\n            if (c > 127) {\n                PyErr_SetString(PyExc_SystemError, \"non-ascii grouped digit\");\n                return -1;\n            }\n            PyUnicode_WRITE(kind, data, writer->pos + t, c);\n        }\n    }\n    writer->pos += spec->n_grouped_digits;\n\n    if (spec->n_decimal) {\n        _PyUnicode_FastCopyCharacters(\n            writer->buffer, writer->pos,\n            locale->decimal_point, 0, spec->n_decimal);\n        writer->pos += spec->n_decimal;\n        d_pos += 1;\n    }\n\n    if (spec->n_remainder) {\n        _PyUnicode_FastCopyCharacters(\n            writer->buffer, writer->pos,\n            digits, d_pos, spec->n_remainder);\n        writer->pos += spec->n_remainder;\n        /* d_pos += spec->n_remainder; */\n    }\n\n    if (spec->n_rpadding) {\n        _PyUnicode_FastFill(writer->buffer,\n                            writer->pos, spec->n_rpadding,\n                            fill_char);\n        writer->pos += spec->n_rpadding;\n    }\n    return 0;\n}\n\nstatic const char no_grouping[1] = {CHAR_MAX};\n\n/* Find the decimal point character(s?), thousands_separator(s?), and\n   grouping description, either for the current locale if type is\n   LT_CURRENT_LOCALE, a hard-coded locale if LT_DEFAULT_LOCALE or\n   LT_UNDERSCORE_LOCALE/LT_UNDER_FOUR_LOCALE, or none if LT_NO_LOCALE. */\nstatic int\nget_locale_info(enum LocaleType type, LocaleInfo *locale_info)\n{\n    switch (type) {\n    case LT_CURRENT_LOCALE: {\n        struct lconv *lc = localeconv();\n        if (_Py_GetLocaleconvNumeric(lc,\n                                     &locale_info->decimal_point,\n                                     &locale_info->thousands_sep) < 0) {\n            return -1;\n        }\n\n        /* localeconv() grouping can become a dangling pointer or point\n           to a different string if another thread calls localeconv() during\n           the string formatting. Copy the string to avoid this risk. */\n        locale_info->grouping_buffer = _PyMem_Strdup(lc->grouping);\n        if (locale_info->grouping_buffer == NULL) {\n            PyErr_NoMemory();\n            return -1;\n        }\n        locale_info->grouping = locale_info->grouping_buffer;\n        break;\n    }\n    case LT_DEFAULT_LOCALE:\n    case LT_UNDERSCORE_LOCALE:\n    case LT_UNDER_FOUR_LOCALE:\n        locale_info->decimal_point = PyUnicode_FromOrdinal('.');\n        locale_info->thousands_sep = PyUnicode_FromOrdinal(\n            type == LT_DEFAULT_LOCALE ? ',' : '_');\n        if (!locale_info->decimal_point || !locale_info->thousands_sep)\n            return -1;\n        if (type != LT_UNDER_FOUR_LOCALE)\n            locale_info->grouping = \"\\3\"; /* Group every 3 characters.  The\n                                         (implicit) trailing 0 means repeat\n                                         infinitely. */\n        else\n            locale_info->grouping = \"\\4\"; /* Bin/oct/hex group every four. */\n        break;\n    case LT_NO_LOCALE:\n        locale_info->decimal_point = PyUnicode_FromOrdinal('.');\n        locale_info->thousands_sep = PyUnicode_New(0, 0);\n        if (!locale_info->decimal_point || !locale_info->thousands_sep)\n            return -1;\n        locale_info->grouping = no_grouping;\n        break;\n    }\n    return 0;\n}\n\nstatic void\nfree_locale_info(LocaleInfo *locale_info)\n{\n    Py_XDECREF(locale_info->decimal_point);\n    Py_XDECREF(locale_info->thousands_sep);\n    PyMem_Free(locale_info->grouping_buffer);\n}\n\n/************************************************************************/\n/*********** string formatting ******************************************/\n/************************************************************************/\n\nstatic int\nformat_string_internal(PyObject *value, const InternalFormatSpec *format,\n                       _PyUnicodeWriter *writer)\n{\n    Py_ssize_t lpad;\n    Py_ssize_t rpad;\n    Py_ssize_t total;\n    Py_ssize_t len;\n    int result = -1;\n    Py_UCS4 maxchar;\n\n    assert(PyUnicode_IS_READY(value));\n    len = PyUnicode_GET_LENGTH(value);\n\n    /* sign is not allowed on strings */\n    if (format->sign != '\\0') {\n        if (format->sign == ' ') {\n            PyErr_SetString(PyExc_ValueError,\n                \"Space not allowed in string format specifier\");\n        }\n        else {\n            PyErr_SetString(PyExc_ValueError,\n                \"Sign not allowed in string format specifier\");\n        }\n        goto done;\n    }\n\n    /* negative 0 coercion is not allowed on strings */\n    if (format->no_neg_0) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"Negative zero coercion (z) not allowed in string format \"\n                        \"specifier\");\n        goto done;\n    }\n\n    /* alternate is not allowed on strings */\n    if (format->alternate) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"Alternate form (#) not allowed in string format \"\n                        \"specifier\");\n        goto done;\n    }\n\n    /* '=' alignment not allowed on strings */\n    if (format->align == '=') {\n        PyErr_SetString(PyExc_ValueError,\n                        \"'=' alignment not allowed \"\n                        \"in string format specifier\");\n        goto done;\n    }\n\n    if ((format->width == -1 || format->width <= len)\n        && (format->precision == -1 || format->precision >= len)) {\n        /* Fast path */\n        return _PyUnicodeWriter_WriteStr(writer, value);\n    }\n\n    /* if precision is specified, output no more that format.precision\n       characters */\n    if (format->precision >= 0 && len >= format->precision) {\n        len = format->precision;\n    }\n\n    calc_padding(len, format->width, format->align, &lpad, &rpad, &total);\n\n    maxchar = writer->maxchar;\n    if (lpad != 0 || rpad != 0)\n        maxchar = Py_MAX(maxchar, format->fill_char);\n    if (PyUnicode_MAX_CHAR_VALUE(value) > maxchar) {\n        Py_UCS4 valmaxchar = _PyUnicode_FindMaxChar(value, 0, len);\n        maxchar = Py_MAX(maxchar, valmaxchar);\n    }\n\n    /* allocate the resulting string */\n    if (_PyUnicodeWriter_Prepare(writer, total, maxchar) == -1)\n        goto done;\n\n    /* Write into that space. First the padding. */\n    result = fill_padding(writer, len, format->fill_char, lpad, rpad);\n    if (result == -1)\n        goto done;\n\n    /* Then the source string. */\n    if (len) {\n        _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,\n                                      value, 0, len);\n    }\n    writer->pos += (len + rpad);\n    result = 0;\n\ndone:\n    return result;\n}\n\n\n/************************************************************************/\n/*********** long formatting ********************************************/\n/************************************************************************/\n\nstatic int\nformat_long_internal(PyObject *value, const InternalFormatSpec *format,\n                     _PyUnicodeWriter *writer)\n{\n    int result = -1;\n    Py_UCS4 maxchar = 127;\n    PyObject *tmp = NULL;\n    Py_ssize_t inumeric_chars;\n    Py_UCS4 sign_char = '\\0';\n    Py_ssize_t n_digits;       /* count of digits need from the computed\n                                  string */\n    Py_ssize_t n_remainder = 0; /* Used only for 'c' formatting, which\n                                   produces non-digits */\n    Py_ssize_t n_prefix = 0;   /* Count of prefix chars, (e.g., '0x') */\n    Py_ssize_t n_total;\n    Py_ssize_t prefix = 0;\n    NumberFieldWidths spec;\n    long x;\n\n    /* Locale settings, either from the actual locale or\n       from a hard-code pseudo-locale */\n    LocaleInfo locale = LocaleInfo_STATIC_INIT;\n\n    /* no precision allowed on integers */\n    if (format->precision != -1) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"Precision not allowed in integer format specifier\");\n        goto done;\n    }\n    /* no negative zero coercion on integers */\n    if (format->no_neg_0) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"Negative zero coercion (z) not allowed in integer\"\n                        \" format specifier\");\n        goto done;\n    }\n\n    /* special case for character formatting */\n    if (format->type == 'c') {\n        /* error to specify a sign */\n        if (format->sign != '\\0') {\n            PyErr_SetString(PyExc_ValueError,\n                            \"Sign not allowed with integer\"\n                            \" format specifier 'c'\");\n            goto done;\n        }\n        /* error to request alternate format */\n        if (format->alternate) {\n            PyErr_SetString(PyExc_ValueError,\n                            \"Alternate form (#) not allowed with integer\"\n                            \" format specifier 'c'\");\n            goto done;\n        }\n\n        /* taken from unicodeobject.c formatchar() */\n        /* Integer input truncated to a character */\n        x = PyLong_AsLong(value);\n        if (x == -1 && PyErr_Occurred())\n            goto done;\n        if (x < 0 || x > 0x10ffff) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"%c arg not in range(0x110000)\");\n            goto done;\n        }\n        tmp = PyUnicode_FromOrdinal(x);\n        inumeric_chars = 0;\n        n_digits = 1;\n        maxchar = Py_MAX(maxchar, (Py_UCS4)x);\n\n        /* As a sort-of hack, we tell calc_number_widths that we only\n           have \"remainder\" characters. calc_number_widths thinks\n           these are characters that don't get formatted, only copied\n           into the output string. We do this for 'c' formatting,\n           because the characters are likely to be non-digits. */\n        n_remainder = 1;\n    }\n    else {\n        int base;\n        int leading_chars_to_skip = 0;  /* Number of characters added by\n                                           PyNumber_ToBase that we want to\n                                           skip over. */\n\n        /* Compute the base and how many characters will be added by\n           PyNumber_ToBase */\n        switch (format->type) {\n        case 'b':\n            base = 2;\n            leading_chars_to_skip = 2; /* 0b */\n            break;\n        case 'o':\n            base = 8;\n            leading_chars_to_skip = 2; /* 0o */\n            break;\n        case 'x':\n        case 'X':\n            base = 16;\n            leading_chars_to_skip = 2; /* 0x */\n            break;\n        default:  /* shouldn't be needed, but stops a compiler warning */\n        case 'd':\n        case 'n':\n            base = 10;\n            break;\n        }\n\n        if (format->sign != '+' && format->sign != ' '\n            && format->width == -1\n            && format->type != 'X' && format->type != 'n'\n            && !format->thousands_separators\n            && PyLong_CheckExact(value))\n        {\n            /* Fast path */\n            return _PyLong_FormatWriter(writer, value, base, format->alternate);\n        }\n\n        /* The number of prefix chars is the same as the leading\n           chars to skip */\n        if (format->alternate)\n            n_prefix = leading_chars_to_skip;\n\n        /* Do the hard part, converting to a string in a given base */\n        tmp = _PyLong_Format(value, base);\n        if (tmp == NULL)\n            goto done;\n\n        inumeric_chars = 0;\n        n_digits = PyUnicode_GET_LENGTH(tmp);\n\n        prefix = inumeric_chars;\n\n        /* Is a sign character present in the output?  If so, remember it\n           and skip it */\n        if (PyUnicode_READ_CHAR(tmp, inumeric_chars) == '-') {\n            sign_char = '-';\n            ++prefix;\n            ++leading_chars_to_skip;\n        }\n\n        /* Skip over the leading chars (0x, 0b, etc.) */\n        n_digits -= leading_chars_to_skip;\n        inumeric_chars += leading_chars_to_skip;\n    }\n\n    /* Determine the grouping, separator, and decimal point, if any. */\n    if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :\n                        format->thousands_separators,\n                        &locale) == -1)\n        goto done;\n\n    /* Calculate how much memory we'll need. */\n    n_total = calc_number_widths(&spec, n_prefix, sign_char, inumeric_chars,\n                                 inumeric_chars + n_digits, n_remainder, 0,\n                                 &locale, format, &maxchar);\n    if (n_total == -1) {\n        goto done;\n    }\n\n    /* Allocate the memory. */\n    if (_PyUnicodeWriter_Prepare(writer, n_total, maxchar) == -1)\n        goto done;\n\n    /* Populate the memory. */\n    result = fill_number(writer, &spec,\n                         tmp, inumeric_chars,\n                         tmp, prefix, format->fill_char,\n                         &locale, format->type == 'X');\n\ndone:\n    Py_XDECREF(tmp);\n    free_locale_info(&locale);\n    return result;\n}\n\n/************************************************************************/\n/*********** float formatting *******************************************/\n/************************************************************************/\n\n/* much of this is taken from unicodeobject.c */\nstatic int\nformat_float_internal(PyObject *value,\n                      const InternalFormatSpec *format,\n                      _PyUnicodeWriter *writer)\n{\n    char *buf = NULL;       /* buffer returned from PyOS_double_to_string */\n    Py_ssize_t n_digits;\n    Py_ssize_t n_remainder;\n    Py_ssize_t n_total;\n    int has_decimal;\n    double val;\n    int precision, default_precision = 6;\n    Py_UCS4 type = format->type;\n    int add_pct = 0;\n    Py_ssize_t index;\n    NumberFieldWidths spec;\n    int flags = 0;\n    int result = -1;\n    Py_UCS4 maxchar = 127;\n    Py_UCS4 sign_char = '\\0';\n    int float_type; /* Used to see if we have a nan, inf, or regular float. */\n    PyObject *unicode_tmp = NULL;\n\n    /* Locale settings, either from the actual locale or\n       from a hard-code pseudo-locale */\n    LocaleInfo locale = LocaleInfo_STATIC_INIT;\n\n    if (format->precision > INT_MAX) {\n        PyErr_SetString(PyExc_ValueError, \"precision too big\");\n        goto done;\n    }\n    precision = (int)format->precision;\n\n    if (format->alternate)\n        flags |= Py_DTSF_ALT;\n    if (format->no_neg_0)\n        flags |= Py_DTSF_NO_NEG_0;\n\n    if (type == '\\0') {\n        /* Omitted type specifier.  Behaves in the same way as repr(x)\n           and str(x) if no precision is given, else like 'g', but with\n           at least one digit after the decimal point. */\n        flags |= Py_DTSF_ADD_DOT_0;\n        type = 'r';\n        default_precision = 0;\n    }\n\n    if (type == 'n')\n        /* 'n' is the same as 'g', except for the locale used to\n           format the result. We take care of that later. */\n        type = 'g';\n\n    val = PyFloat_AsDouble(value);\n    if (val == -1.0 && PyErr_Occurred())\n        goto done;\n\n    if (type == '%') {\n        type = 'f';\n        val *= 100;\n        add_pct = 1;\n    }\n\n    if (precision < 0)\n        precision = default_precision;\n    else if (type == 'r')\n        type = 'g';\n\n    /* Cast \"type\", because if we're in unicode we need to pass an\n       8-bit char. This is safe, because we've restricted what \"type\"\n       can be. */\n    buf = PyOS_double_to_string(val, (char)type, precision, flags,\n                                &float_type);\n    if (buf == NULL)\n        goto done;\n    n_digits = strlen(buf);\n\n    if (add_pct) {\n        /* We know that buf has a trailing zero (since we just called\n           strlen() on it), and we don't use that fact any more. So we\n           can just write over the trailing zero. */\n        buf[n_digits] = '%';\n        n_digits += 1;\n    }\n\n    if (format->sign != '+' && format->sign != ' '\n        && format->width == -1\n        && format->type != 'n'\n        && !format->thousands_separators)\n    {\n        /* Fast path */\n        result = _PyUnicodeWriter_WriteASCIIString(writer, buf, n_digits);\n        PyMem_Free(buf);\n        return result;\n    }\n\n    /* Since there is no unicode version of PyOS_double_to_string,\n       just use the 8 bit version and then convert to unicode. */\n    unicode_tmp = _PyUnicode_FromASCII(buf, n_digits);\n    PyMem_Free(buf);\n    if (unicode_tmp == NULL)\n        goto done;\n\n    /* Is a sign character present in the output?  If so, remember it\n       and skip it */\n    index = 0;\n    if (PyUnicode_READ_CHAR(unicode_tmp, index) == '-') {\n        sign_char = '-';\n        ++index;\n        --n_digits;\n    }\n\n    /* Determine if we have any \"remainder\" (after the digits, might include\n       decimal or exponent or both (or neither)) */\n    parse_number(unicode_tmp, index, index + n_digits, &n_remainder, &has_decimal);\n\n    /* Determine the grouping, separator, and decimal point, if any. */\n    if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :\n                        format->thousands_separators,\n                        &locale) == -1)\n        goto done;\n\n    /* Calculate how much memory we'll need. */\n    n_total = calc_number_widths(&spec, 0, sign_char, index,\n                                 index + n_digits, n_remainder, has_decimal,\n                                 &locale, format, &maxchar);\n    if (n_total == -1) {\n        goto done;\n    }\n\n    /* Allocate the memory. */\n    if (_PyUnicodeWriter_Prepare(writer, n_total, maxchar) == -1)\n        goto done;\n\n    /* Populate the memory. */\n    result = fill_number(writer, &spec,\n                         unicode_tmp, index,\n                         NULL, 0, format->fill_char,\n                         &locale, 0);\n\ndone:\n    Py_XDECREF(unicode_tmp);\n    free_locale_info(&locale);\n    return result;\n}\n\n/************************************************************************/\n/*********** complex formatting *****************************************/\n/************************************************************************/\n\nstatic int\nformat_complex_internal(PyObject *value,\n                        const InternalFormatSpec *format,\n                        _PyUnicodeWriter *writer)\n{\n    double re;\n    double im;\n    char *re_buf = NULL;       /* buffer returned from PyOS_double_to_string */\n    char *im_buf = NULL;       /* buffer returned from PyOS_double_to_string */\n\n    InternalFormatSpec tmp_format = *format;\n    Py_ssize_t n_re_digits;\n    Py_ssize_t n_im_digits;\n    Py_ssize_t n_re_remainder;\n    Py_ssize_t n_im_remainder;\n    Py_ssize_t n_re_total;\n    Py_ssize_t n_im_total;\n    int re_has_decimal;\n    int im_has_decimal;\n    int precision, default_precision = 6;\n    Py_UCS4 type = format->type;\n    Py_ssize_t i_re;\n    Py_ssize_t i_im;\n    NumberFieldWidths re_spec;\n    NumberFieldWidths im_spec;\n    int flags = 0;\n    int result = -1;\n    Py_UCS4 maxchar = 127;\n    int rkind;\n    void *rdata;\n    Py_UCS4 re_sign_char = '\\0';\n    Py_UCS4 im_sign_char = '\\0';\n    int re_float_type; /* Used to see if we have a nan, inf, or regular float. */\n    int im_float_type;\n    int add_parens = 0;\n    int skip_re = 0;\n    Py_ssize_t lpad;\n    Py_ssize_t rpad;\n    Py_ssize_t total;\n    PyObject *re_unicode_tmp = NULL;\n    PyObject *im_unicode_tmp = NULL;\n\n    /* Locale settings, either from the actual locale or\n       from a hard-code pseudo-locale */\n    LocaleInfo locale = LocaleInfo_STATIC_INIT;\n\n    if (format->precision > INT_MAX) {\n        PyErr_SetString(PyExc_ValueError, \"precision too big\");\n        goto done;\n    }\n    precision = (int)format->precision;\n\n    /* Zero padding is not allowed. */\n    if (format->fill_char == '0') {\n        PyErr_SetString(PyExc_ValueError,\n                        \"Zero padding is not allowed in complex format \"\n                        \"specifier\");\n        goto done;\n    }\n\n    /* Neither is '=' alignment . */\n    if (format->align == '=') {\n        PyErr_SetString(PyExc_ValueError,\n                        \"'=' alignment flag is not allowed in complex format \"\n                        \"specifier\");\n        goto done;\n    }\n\n    re = PyComplex_RealAsDouble(value);\n    if (re == -1.0 && PyErr_Occurred())\n        goto done;\n    im = PyComplex_ImagAsDouble(value);\n    if (im == -1.0 && PyErr_Occurred())\n        goto done;\n\n    if (format->alternate)\n        flags |= Py_DTSF_ALT;\n    if (format->no_neg_0)\n        flags |= Py_DTSF_NO_NEG_0;\n\n    if (type == '\\0') {\n        /* Omitted type specifier. Should be like str(self). */\n        type = 'r';\n        default_precision = 0;\n        if (re == 0.0 && copysign(1.0, re) == 1.0)\n            skip_re = 1;\n        else\n            add_parens = 1;\n    }\n\n    if (type == 'n')\n        /* 'n' is the same as 'g', except for the locale used to\n           format the result. We take care of that later. */\n        type = 'g';\n\n    if (precision < 0)\n        precision = default_precision;\n    else if (type == 'r')\n        type = 'g';\n\n    /* Cast \"type\", because if we're in unicode we need to pass an\n       8-bit char. This is safe, because we've restricted what \"type\"\n       can be. */\n    re_buf = PyOS_double_to_string(re, (char)type, precision, flags,\n                                   &re_float_type);\n    if (re_buf == NULL)\n        goto done;\n    im_buf = PyOS_double_to_string(im, (char)type, precision, flags,\n                                   &im_float_type);\n    if (im_buf == NULL)\n        goto done;\n\n    n_re_digits = strlen(re_buf);\n    n_im_digits = strlen(im_buf);\n\n    /* Since there is no unicode version of PyOS_double_to_string,\n       just use the 8 bit version and then convert to unicode. */\n    re_unicode_tmp = _PyUnicode_FromASCII(re_buf, n_re_digits);\n    if (re_unicode_tmp == NULL)\n        goto done;\n    i_re = 0;\n\n    im_unicode_tmp = _PyUnicode_FromASCII(im_buf, n_im_digits);\n    if (im_unicode_tmp == NULL)\n        goto done;\n    i_im = 0;\n\n    /* Is a sign character present in the output?  If so, remember it\n       and skip it */\n    if (PyUnicode_READ_CHAR(re_unicode_tmp, i_re) == '-') {\n        re_sign_char = '-';\n        ++i_re;\n        --n_re_digits;\n    }\n    if (PyUnicode_READ_CHAR(im_unicode_tmp, i_im) == '-') {\n        im_sign_char = '-';\n        ++i_im;\n        --n_im_digits;\n    }\n\n    /* Determine if we have any \"remainder\" (after the digits, might include\n       decimal or exponent or both (or neither)) */\n    parse_number(re_unicode_tmp, i_re, i_re + n_re_digits,\n                 &n_re_remainder, &re_has_decimal);\n    parse_number(im_unicode_tmp, i_im, i_im + n_im_digits,\n                 &n_im_remainder, &im_has_decimal);\n\n    /* Determine the grouping, separator, and decimal point, if any. */\n    if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE :\n                        format->thousands_separators,\n                        &locale) == -1)\n        goto done;\n\n    /* Turn off any padding. We'll do it later after we've composed\n       the numbers without padding. */\n    tmp_format.fill_char = '\\0';\n    tmp_format.align = '<';\n    tmp_format.width = -1;\n\n    /* Calculate how much memory we'll need. */\n    n_re_total = calc_number_widths(&re_spec, 0, re_sign_char,\n                                    i_re, i_re + n_re_digits, n_re_remainder,\n                                    re_has_decimal, &locale, &tmp_format,\n                                    &maxchar);\n    if (n_re_total == -1) {\n        goto done;\n    }\n\n    /* Same formatting, but always include a sign, unless the real part is\n     * going to be omitted, in which case we use whatever sign convention was\n     * requested by the original format. */\n    if (!skip_re)\n        tmp_format.sign = '+';\n    n_im_total = calc_number_widths(&im_spec, 0, im_sign_char,\n                                    i_im, i_im + n_im_digits, n_im_remainder,\n                                    im_has_decimal, &locale, &tmp_format,\n                                    &maxchar);\n    if (n_im_total == -1) {\n        goto done;\n    }\n\n    if (skip_re)\n        n_re_total = 0;\n\n    /* Add 1 for the 'j', and optionally 2 for parens. */\n    calc_padding(n_re_total + n_im_total + 1 + add_parens * 2,\n                 format->width, format->align, &lpad, &rpad, &total);\n\n    if (lpad || rpad)\n        maxchar = Py_MAX(maxchar, format->fill_char);\n\n    if (_PyUnicodeWriter_Prepare(writer, total, maxchar) == -1)\n        goto done;\n    rkind = writer->kind;\n    rdata = writer->data;\n\n    /* Populate the memory. First, the padding. */\n    result = fill_padding(writer,\n                          n_re_total + n_im_total + 1 + add_parens * 2,\n                          format->fill_char, lpad, rpad);\n    if (result == -1)\n        goto done;\n\n    if (add_parens) {\n        PyUnicode_WRITE(rkind, rdata, writer->pos, '(');\n        writer->pos++;\n    }\n\n    if (!skip_re) {\n        result = fill_number(writer, &re_spec,\n                             re_unicode_tmp, i_re,\n                             NULL, 0,\n                             0,\n                             &locale, 0);\n        if (result == -1)\n            goto done;\n    }\n    result = fill_number(writer, &im_spec,\n                         im_unicode_tmp, i_im,\n                         NULL, 0,\n                         0,\n                         &locale, 0);\n    if (result == -1)\n        goto done;\n    PyUnicode_WRITE(rkind, rdata, writer->pos, 'j');\n    writer->pos++;\n\n    if (add_parens) {\n        PyUnicode_WRITE(rkind, rdata, writer->pos, ')');\n        writer->pos++;\n    }\n\n    writer->pos += rpad;\n\ndone:\n    PyMem_Free(re_buf);\n    PyMem_Free(im_buf);\n    Py_XDECREF(re_unicode_tmp);\n    Py_XDECREF(im_unicode_tmp);\n    free_locale_info(&locale);\n    return result;\n}\n\n/************************************************************************/\n/*********** built in formatters ****************************************/\n/************************************************************************/\nstatic int\nformat_obj(PyObject *obj, _PyUnicodeWriter *writer)\n{\n    PyObject *str;\n    int err;\n\n    str = PyObject_Str(obj);\n    if (str == NULL)\n        return -1;\n    err = _PyUnicodeWriter_WriteStr(writer, str);\n    Py_DECREF(str);\n    return err;\n}\n\nint\n_PyUnicode_FormatAdvancedWriter(_PyUnicodeWriter *writer,\n                                PyObject *obj,\n                                PyObject *format_spec,\n                                Py_ssize_t start, Py_ssize_t end)\n{\n    InternalFormatSpec format;\n\n    assert(PyUnicode_Check(obj));\n\n    /* check for the special case of zero length format spec, make\n       it equivalent to str(obj) */\n    if (start == end) {\n        if (PyUnicode_CheckExact(obj))\n            return _PyUnicodeWriter_WriteStr(writer, obj);\n        else\n            return format_obj(obj, writer);\n    }\n\n    /* parse the format_spec */\n    if (!parse_internal_render_format_spec(obj, format_spec, start, end,\n                                           &format, 's', '<'))\n        return -1;\n\n    /* type conversion? */\n    switch (format.type) {\n    case 's':\n        /* no type conversion needed, already a string.  do the formatting */\n        return format_string_internal(obj, &format, writer);\n    default:\n        /* unknown */\n        unknown_presentation_type(format.type, Py_TYPE(obj)->tp_name);\n        return -1;\n    }\n}\n\nint\n_PyLong_FormatAdvancedWriter(_PyUnicodeWriter *writer,\n                             PyObject *obj,\n                             PyObject *format_spec,\n                             Py_ssize_t start, Py_ssize_t end)\n{\n    PyObject *tmp = NULL;\n    InternalFormatSpec format;\n    int result = -1;\n\n    /* check for the special case of zero length format spec, make\n       it equivalent to str(obj) */\n    if (start == end) {\n        if (PyLong_CheckExact(obj))\n            return _PyLong_FormatWriter(writer, obj, 10, 0);\n        else\n            return format_obj(obj, writer);\n    }\n\n    /* parse the format_spec */\n    if (!parse_internal_render_format_spec(obj, format_spec, start, end,\n                                           &format, 'd', '>'))\n        goto done;\n\n    /* type conversion? */\n    switch (format.type) {\n    case 'b':\n    case 'c':\n    case 'd':\n    case 'o':\n    case 'x':\n    case 'X':\n    case 'n':\n        /* no type conversion needed, already an int.  do the formatting */\n        result = format_long_internal(obj, &format, writer);\n        break;\n\n    case 'e':\n    case 'E':\n    case 'f':\n    case 'F':\n    case 'g':\n    case 'G':\n    case '%':\n        /* convert to float */\n        tmp = PyNumber_Float(obj);\n        if (tmp == NULL)\n            goto done;\n        result = format_float_internal(tmp, &format, writer);\n        break;\n\n    default:\n        /* unknown */\n        unknown_presentation_type(format.type, Py_TYPE(obj)->tp_name);\n        goto done;\n    }\n\ndone:\n    Py_XDECREF(tmp);\n    return result;\n}\n\nint\n_PyFloat_FormatAdvancedWriter(_PyUnicodeWriter *writer,\n                              PyObject *obj,\n                              PyObject *format_spec,\n                              Py_ssize_t start, Py_ssize_t end)\n{\n    InternalFormatSpec format;\n\n    /* check for the special case of zero length format spec, make\n       it equivalent to str(obj) */\n    if (start == end)\n        return format_obj(obj, writer);\n\n    /* parse the format_spec */\n    if (!parse_internal_render_format_spec(obj, format_spec, start, end,\n                                           &format, '\\0', '>'))\n        return -1;\n\n    /* type conversion? */\n    switch (format.type) {\n    case '\\0': /* No format code: like 'g', but with at least one decimal. */\n    case 'e':\n    case 'E':\n    case 'f':\n    case 'F':\n    case 'g':\n    case 'G':\n    case 'n':\n    case '%':\n        /* no conversion, already a float.  do the formatting */\n        return format_float_internal(obj, &format, writer);\n\n    default:\n        /* unknown */\n        unknown_presentation_type(format.type, Py_TYPE(obj)->tp_name);\n        return -1;\n    }\n}\n\nint\n_PyComplex_FormatAdvancedWriter(_PyUnicodeWriter *writer,\n                                PyObject *obj,\n                                PyObject *format_spec,\n                                Py_ssize_t start, Py_ssize_t end)\n{\n    InternalFormatSpec format;\n\n    /* check for the special case of zero length format spec, make\n       it equivalent to str(obj) */\n    if (start == end)\n        return format_obj(obj, writer);\n\n    /* parse the format_spec */\n    if (!parse_internal_render_format_spec(obj, format_spec, start, end,\n                                           &format, '\\0', '>'))\n        return -1;\n\n    /* type conversion? */\n    switch (format.type) {\n    case '\\0': /* No format code: like 'g', but with at least one decimal. */\n    case 'e':\n    case 'E':\n    case 'f':\n    case 'F':\n    case 'g':\n    case 'G':\n    case 'n':\n        /* no conversion, already a complex.  do the formatting */\n        return format_complex_internal(obj, &format, writer);\n\n    default:\n        /* unknown */\n        unknown_presentation_type(format.type, Py_TYPE(obj)->tp_name);\n        return -1;\n    }\n}\n"
  },
  {
    "path": "Frame.c",
    "content": "\n#define _PY_INTERPRETER\n\n#include \"Python.h\"\n#include \"frameobject.h\"\n#include \"pycore_code.h\"          // stats\n#include \"pycore_frame.h\"\n#include \"pycore_object.h\"        // _PyObject_GC_UNTRACK()\n#include \"opcode.h\"\n\nint\n_PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg)\n{\n    Py_VISIT(frame->frame_obj);\n    Py_VISIT(frame->f_locals);\n    Py_VISIT(frame->f_funcobj);\n    Py_VISIT(frame->f_code);\n   /* locals */\n    PyObject **locals = _PyFrame_GetLocalsArray(frame);\n    int i = 0;\n    /* locals and stack */\n    for (; i <frame->stacktop; i++) {\n        Py_VISIT(locals[i]);\n    }\n    return 0;\n}\n\nPyFrameObject *\n_PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)\n{\n    assert(frame->frame_obj == NULL);\n    PyObject *exc = PyErr_GetRaisedException();\n\n    PyFrameObject *f = _PyFrame_New_NoTrack(frame->f_code);\n    if (f == NULL) {\n        Py_XDECREF(exc);\n        return NULL;\n    }\n    PyErr_SetRaisedException(exc);\n    if (frame->frame_obj) {\n        // GH-97002: How did we get into this horrible situation? Most likely,\n        // allocating f triggered a GC collection, which ran some code that\n        // *also* created the same frame... while we were in the middle of\n        // creating it! See test_sneaky_frame_object in test_frame.py for a\n        // concrete example.\n        //\n        // Regardless, just throw f away and use that frame instead, since it's\n        // already been exposed to user code. It's actually a bit tricky to do\n        // this, since we aren't backed by a real _PyInterpreterFrame anymore.\n        // Just pretend that we have an owned, cleared frame so frame_dealloc\n        // doesn't make the situation worse:\n        f->f_frame = (_PyInterpreterFrame *)f->_f_frame_data;\n        f->f_frame->owner = FRAME_CLEARED;\n        f->f_frame->frame_obj = f;\n        Py_DECREF(f);\n        return frame->frame_obj;\n    }\n    assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);\n    assert(frame->owner != FRAME_CLEARED);\n    f->f_frame = frame;\n    frame->frame_obj = f;\n    return f;\n}\n\nvoid\n_PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)\n{\n    assert(src->stacktop >= src->f_code->co_nlocalsplus);\n    Py_ssize_t size = ((char*)&src->localsplus[src->stacktop]) - (char *)src;\n    memcpy(dest, src, size);\n    // Don't leave a dangling pointer to the old frame when creating generators\n    // and coroutines:\n    dest->previous = NULL;\n}\n\n\nstatic void\ntake_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)\n{\n    assert(frame->owner != FRAME_OWNED_BY_CSTACK);\n    assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);\n    assert(frame->owner != FRAME_CLEARED);\n    Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame;\n    Py_INCREF(frame->f_code);\n    memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);\n    frame = (_PyInterpreterFrame *)f->_f_frame_data;\n    f->f_frame = frame;\n    frame->owner = FRAME_OWNED_BY_FRAME_OBJECT;\n    if (_PyFrame_IsIncomplete(frame)) {\n        // This may be a newly-created generator or coroutine frame. Since it's\n        // dead anyways, just pretend that the first RESUME ran:\n        PyCodeObject *code = frame->f_code;\n        frame->prev_instr = _PyCode_CODE(code) + code->_co_firsttraceable;\n    }\n    assert(!_PyFrame_IsIncomplete(frame));\n    assert(f->f_back == NULL);\n    _PyInterpreterFrame *prev = _PyFrame_GetFirstComplete(frame->previous);\n    frame->previous = NULL;\n    if (prev) {\n        assert(prev->owner != FRAME_OWNED_BY_CSTACK);\n        /* Link PyFrameObjects.f_back and remove link through _PyInterpreterFrame.previous */\n        PyFrameObject *back = _PyFrame_GetFrameObject(prev);\n        if (back == NULL) {\n            /* Memory error here. */\n            assert(PyErr_ExceptionMatches(PyExc_MemoryError));\n            /* Nothing we can do about it */\n            PyErr_Clear();\n        }\n        else {\n            f->f_back = (PyFrameObject *)Py_NewRef(back);\n        }\n    }\n    if (!_PyObject_GC_IS_TRACKED((PyObject *)f)) {\n        _PyObject_GC_TRACK((PyObject *)f);\n    }\n}\n\nvoid\n_PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)\n{\n    /* It is the responsibility of the owning generator/coroutine\n     * to have cleared the enclosing generator, if any. */\n    assert(frame->owner != FRAME_OWNED_BY_GENERATOR ||\n        _PyFrame_GetGenerator(frame)->gi_frame_state == FRAME_CLEARED);\n    // GH-99729: Clearing this frame can expose the stack (via finalizers). It's\n    // crucial that this frame has been unlinked, and is no longer visible:\n    assert(_PyThreadState_GET()->cframe->current_frame != frame);\n    if (frame->frame_obj) {\n        PyFrameObject *f = frame->frame_obj;\n        frame->frame_obj = NULL;\n        if (Py_REFCNT(f) > 1) {\n            take_ownership(f, frame);\n            Py_DECREF(f);\n            return;\n        }\n        Py_DECREF(f);\n    }\n    assert(frame->stacktop >= 0);\n    for (int i = 0; i < frame->stacktop; i++) {\n        Py_XDECREF(frame->localsplus[i]);\n    }\n    Py_XDECREF(frame->frame_obj);\n    Py_XDECREF(frame->f_locals);\n    Py_DECREF(frame->f_funcobj);\n}\n\n/* Unstable API functions */\n\nPyObject *\nPyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame)\n{\n    PyObject *code = (PyObject *)frame->f_code;\n    Py_INCREF(code);\n    return code;\n}\n\nint\nPyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame)\n{\n    return _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);\n}\n\nint\nPyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame)\n{\n    int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);\n    return PyCode_Addr2Line(frame->f_code, addr);\n}\n"
  },
  {
    "path": "Frozen.c",
    "content": "\n/* Frozen modules initializer\n *\n * Frozen modules are written to header files by Programs/_freeze_module.\n * These files are typically put in Python/frozen_modules/.  Each holds\n * an array of bytes named \"_Py_M__<module>\", which is used below.\n *\n * These files must be regenerated any time the corresponding .pyc\n * file would change (including with changes to the compiler, bytecode\n * format, marshal format).  This can be done with \"make regen-frozen\".\n * That make target just runs Tools/build/freeze_modules.py.\n *\n * The freeze_modules.py script also determines which modules get\n * frozen.  Update the list at the top of the script to add, remove,\n * or modify the target modules.  Then run the script\n * (or run \"make regen-frozen\").\n *\n * The script does the following:\n *\n * 1. run Programs/_freeze_module on the target modules\n * 2. update the includes and _PyImport_FrozenModules[] in this file\n * 3. update the FROZEN_FILES variable in Makefile.pre.in\n * 4. update the per-module targets in Makefile.pre.in\n * 5. update the lists of modules in PCbuild/_freeze_module.vcxproj and\n *    PCbuild/_freeze_module.vcxproj.filters\n *\n * (Note that most of the data in this file is auto-generated by the script.)\n *\n * Those steps can also be done manually, though this is not recommended.\n * Expect such manual changes to be removed the next time\n * freeze_modules.py runs.\n * */\n\n/* In order to test the support for frozen modules, by default we\n   define some simple frozen modules: __hello__, __phello__ (a package),\n   and __phello__.spam.  Loading any will print some famous words... */\n\n#include \"Python.h\"\n#include \"pycore_import.h\"\n\n#include <stdbool.h>\n\n/* Includes for frozen modules: */\n#include \"frozen_modules/importlib._bootstrap.h\"\n#include \"frozen_modules/importlib._bootstrap_external.h\"\n#include \"frozen_modules/zipimport.h\"\n#include \"frozen_modules/abc.h\"\n#include \"frozen_modules/codecs.h\"\n#include \"frozen_modules/io.h\"\n#include \"frozen_modules/_collections_abc.h\"\n#include \"frozen_modules/_sitebuiltins.h\"\n#include \"frozen_modules/genericpath.h\"\n#include \"frozen_modules/ntpath.h\"\n#include \"frozen_modules/posixpath.h\"\n#include \"frozen_modules/os.h\"\n#include \"frozen_modules/site.h\"\n#include \"frozen_modules/stat.h\"\n#include \"frozen_modules/importlib.util.h\"\n#include \"frozen_modules/importlib.machinery.h\"\n#include \"frozen_modules/runpy.h\"\n#include \"frozen_modules/__hello__.h\"\n#include \"frozen_modules/__phello__.h\"\n#include \"frozen_modules/__phello__.ham.h\"\n#include \"frozen_modules/__phello__.ham.eggs.h\"\n#include \"frozen_modules/__phello__.spam.h\"\n#include \"frozen_modules/frozen_only.h\"\n/* End includes */\n\n#define GET_CODE(name) _Py_get_##name##_toplevel\n\n/* Start extern declarations */\nextern PyObject *_Py_get_importlib__bootstrap_toplevel(void);\nextern PyObject *_Py_get_importlib__bootstrap_external_toplevel(void);\nextern PyObject *_Py_get_zipimport_toplevel(void);\nextern PyObject *_Py_get_abc_toplevel(void);\nextern PyObject *_Py_get_codecs_toplevel(void);\nextern PyObject *_Py_get_io_toplevel(void);\nextern PyObject *_Py_get__collections_abc_toplevel(void);\nextern PyObject *_Py_get__sitebuiltins_toplevel(void);\nextern PyObject *_Py_get_genericpath_toplevel(void);\nextern PyObject *_Py_get_ntpath_toplevel(void);\nextern PyObject *_Py_get_posixpath_toplevel(void);\nextern PyObject *_Py_get_posixpath_toplevel(void);\nextern PyObject *_Py_get_os_toplevel(void);\nextern PyObject *_Py_get_site_toplevel(void);\nextern PyObject *_Py_get_stat_toplevel(void);\nextern PyObject *_Py_get_importlib_util_toplevel(void);\nextern PyObject *_Py_get_importlib_machinery_toplevel(void);\nextern PyObject *_Py_get_runpy_toplevel(void);\nextern PyObject *_Py_get___hello___toplevel(void);\nextern PyObject *_Py_get___hello___toplevel(void);\nextern PyObject *_Py_get___hello___toplevel(void);\nextern PyObject *_Py_get___hello___toplevel(void);\nextern PyObject *_Py_get___phello___toplevel(void);\nextern PyObject *_Py_get___phello___toplevel(void);\nextern PyObject *_Py_get___phello___ham_toplevel(void);\nextern PyObject *_Py_get___phello___ham_toplevel(void);\nextern PyObject *_Py_get___phello___ham_eggs_toplevel(void);\nextern PyObject *_Py_get___phello___spam_toplevel(void);\nextern PyObject *_Py_get_frozen_only_toplevel(void);\n/* End extern declarations */\n\nstatic const struct _frozen bootstrap_modules[] = {\n    {\"_frozen_importlib\", _Py_M__importlib__bootstrap, (int)sizeof(_Py_M__importlib__bootstrap), false, GET_CODE(importlib__bootstrap)},\n    {\"_frozen_importlib_external\", _Py_M__importlib__bootstrap_external, (int)sizeof(_Py_M__importlib__bootstrap_external), false, GET_CODE(importlib__bootstrap_external)},\n    {\"zipimport\", _Py_M__zipimport, (int)sizeof(_Py_M__zipimport), false, GET_CODE(zipimport)},\n    {0, 0, 0} /* bootstrap sentinel */\n};\nstatic const struct _frozen stdlib_modules[] = {\n    /* stdlib - startup, without site (python -S) */\n    {\"abc\", _Py_M__abc, (int)sizeof(_Py_M__abc), false, GET_CODE(abc)},\n    {\"codecs\", _Py_M__codecs, (int)sizeof(_Py_M__codecs), false, GET_CODE(codecs)},\n    {\"io\", _Py_M__io, (int)sizeof(_Py_M__io), false, GET_CODE(io)},\n\n    /* stdlib - startup, with site */\n    {\"_collections_abc\", _Py_M___collections_abc, (int)sizeof(_Py_M___collections_abc), false, GET_CODE(_collections_abc)},\n    {\"_sitebuiltins\", _Py_M___sitebuiltins, (int)sizeof(_Py_M___sitebuiltins), false, GET_CODE(_sitebuiltins)},\n    {\"genericpath\", _Py_M__genericpath, (int)sizeof(_Py_M__genericpath), false, GET_CODE(genericpath)},\n    {\"ntpath\", _Py_M__ntpath, (int)sizeof(_Py_M__ntpath), false, GET_CODE(ntpath)},\n    {\"posixpath\", _Py_M__posixpath, (int)sizeof(_Py_M__posixpath), false, GET_CODE(posixpath)},\n    {\"os.path\", _Py_M__posixpath, (int)sizeof(_Py_M__posixpath), false, GET_CODE(posixpath)},\n    {\"os\", _Py_M__os, (int)sizeof(_Py_M__os), false, GET_CODE(os)},\n    {\"site\", _Py_M__site, (int)sizeof(_Py_M__site), false, GET_CODE(site)},\n    {\"stat\", _Py_M__stat, (int)sizeof(_Py_M__stat), false, GET_CODE(stat)},\n\n    /* runpy - run module with -m */\n    {\"importlib.util\", _Py_M__importlib_util, (int)sizeof(_Py_M__importlib_util), false, GET_CODE(importlib_util)},\n    {\"importlib.machinery\", _Py_M__importlib_machinery, (int)sizeof(_Py_M__importlib_machinery), false, GET_CODE(importlib_machinery)},\n    {\"runpy\", _Py_M__runpy, (int)sizeof(_Py_M__runpy), false, GET_CODE(runpy)},\n    {0, 0, 0} /* stdlib sentinel */\n};\nstatic const struct _frozen test_modules[] = {\n    {\"__hello__\", _Py_M____hello__, (int)sizeof(_Py_M____hello__), false, GET_CODE(__hello__)},\n    {\"__hello_alias__\", _Py_M____hello__, (int)sizeof(_Py_M____hello__), false, GET_CODE(__hello__)},\n    {\"__phello_alias__\", _Py_M____hello__, (int)sizeof(_Py_M____hello__), true, GET_CODE(__hello__)},\n    {\"__phello_alias__.spam\", _Py_M____hello__, (int)sizeof(_Py_M____hello__), false, GET_CODE(__hello__)},\n    {\"__phello__\", _Py_M____phello__, (int)sizeof(_Py_M____phello__), true, GET_CODE(__phello__)},\n    {\"__phello__.__init__\", _Py_M____phello__, (int)sizeof(_Py_M____phello__), false, GET_CODE(__phello__)},\n    {\"__phello__.ham\", _Py_M____phello___ham, (int)sizeof(_Py_M____phello___ham), true, GET_CODE(__phello___ham)},\n    {\"__phello__.ham.__init__\", _Py_M____phello___ham, (int)sizeof(_Py_M____phello___ham), false, GET_CODE(__phello___ham)},\n    {\"__phello__.ham.eggs\", _Py_M____phello___ham_eggs, (int)sizeof(_Py_M____phello___ham_eggs), false, GET_CODE(__phello___ham_eggs)},\n    {\"__phello__.spam\", _Py_M____phello___spam, (int)sizeof(_Py_M____phello___spam), false, GET_CODE(__phello___spam)},\n    {\"__hello_only__\", _Py_M__frozen_only, (int)sizeof(_Py_M__frozen_only), false, GET_CODE(frozen_only)},\n    {0, 0, 0} /* test sentinel */\n};\nconst struct _frozen *_PyImport_FrozenBootstrap = bootstrap_modules;\nconst struct _frozen *_PyImport_FrozenStdlib = stdlib_modules;\nconst struct _frozen *_PyImport_FrozenTest = test_modules;\n\nstatic const struct _module_alias aliases[] = {\n    {\"_frozen_importlib\", \"importlib._bootstrap\"},\n    {\"_frozen_importlib_external\", \"importlib._bootstrap_external\"},\n    {\"os.path\", \"posixpath\"},\n    {\"__hello_alias__\", \"__hello__\"},\n    {\"__phello_alias__\", \"__hello__\"},\n    {\"__phello_alias__.spam\", \"__hello__\"},\n    {\"__phello__.__init__\", \"<__phello__\"},\n    {\"__phello__.ham.__init__\", \"<__phello__.ham\"},\n    {\"__hello_only__\", NULL},\n    {0, 0} /* aliases sentinel */\n};\nconst struct _module_alias *_PyImport_FrozenAliases = aliases;\n\n\n/* Embedding apps may change this pointer to point to their favorite\n   collection of frozen modules: */\n\nconst struct _frozen *PyImport_FrozenModules = NULL;\n"
  },
  {
    "path": "FrozenMain.c",
    "content": "/* Python interpreter main program for frozen scripts */\n\n#include \"Python.h\"\n#include \"pycore_runtime.h\"  // _PyRuntime_Initialize()\n#include <locale.h>\n\n#ifdef MS_WINDOWS\nextern void PyWinFreeze_ExeInit(void);\nextern void PyWinFreeze_ExeTerm(void);\nextern int PyInitFrozenExtensions(void);\n#endif\n\n/* Main program */\n\nint\nPy_FrozenMain(int argc, char **argv)\n{\n    PyStatus status = _PyRuntime_Initialize();\n    if (PyStatus_Exception(status)) {\n        Py_ExitStatusException(status);\n    }\n\n    PyConfig config;\n    PyConfig_InitPythonConfig(&config);\n    // Suppress errors from getpath.c\n    config.pathconfig_warnings = 0;\n    // Don't parse command line options like -E\n    config.parse_argv = 0;\n\n    status = PyConfig_SetBytesArgv(&config, argc, argv);\n    if (PyStatus_Exception(status)) {\n        PyConfig_Clear(&config);\n        Py_ExitStatusException(status);\n    }\n\n    const char *p;\n    int inspect = 0;\n    if ((p = Py_GETENV(\"PYTHONINSPECT\")) && *p != '\\0') {\n        inspect = 1;\n    }\n\n#ifdef MS_WINDOWS\n    PyInitFrozenExtensions();\n#endif /* MS_WINDOWS */\n\n    status = Py_InitializeFromConfig(&config);\n    PyConfig_Clear(&config);\n    if (PyStatus_Exception(status)) {\n        Py_ExitStatusException(status);\n    }\n\n#ifdef MS_WINDOWS\n    PyWinFreeze_ExeInit();\n#endif\n\n    if (_Py_GetConfig()->verbose) {\n        fprintf(stderr, \"Python %s\\n%s\\n\",\n                Py_GetVersion(), Py_GetCopyright());\n    }\n\n    int sts = 1;\n    int n = PyImport_ImportFrozenModule(\"__main__\");\n    if (n == 0) {\n        Py_FatalError(\"the __main__ module is not frozen\");\n    }\n    if (n < 0) {\n        PyErr_Print();\n        sts = 1;\n    }\n    else {\n        sts = 0;\n    }\n\n    if (inspect && isatty((int)fileno(stdin))) {\n        sts = PyRun_AnyFile(stdin, \"<stdin>\") != 0;\n    }\n\n#ifdef MS_WINDOWS\n    PyWinFreeze_ExeTerm();\n#endif\n    if (Py_FinalizeEx() < 0) {\n        sts = 120;\n    }\n    return sts;\n}\n"
  },
  {
    "path": "Future.c",
    "content": "#include \"Python.h\"\n#include \"pycore_ast.h\"           // _PyAST_GetDocString()\n\n#define UNDEFINED_FUTURE_FEATURE \"future feature %.100s is not defined\"\n\nstatic int\nfuture_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *filename)\n{\n    int i;\n\n    assert(s->kind == ImportFrom_kind);\n\n    asdl_alias_seq *names = s->v.ImportFrom.names;\n    for (i = 0; i < asdl_seq_LEN(names); i++) {\n        alias_ty name = (alias_ty)asdl_seq_GET(names, i);\n        const char *feature = PyUnicode_AsUTF8(name->name);\n        if (!feature)\n            return 0;\n        if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {\n            continue;\n        } else if (strcmp(feature, FUTURE_GENERATORS) == 0) {\n            continue;\n        } else if (strcmp(feature, FUTURE_DIVISION) == 0) {\n            continue;\n        } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {\n            continue;\n        } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {\n            continue;\n        } else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {\n            continue;\n        } else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {\n            continue;\n        } else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) {\n            ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;\n        } else if (strcmp(feature, FUTURE_GENERATOR_STOP) == 0) {\n            continue;\n        } else if (strcmp(feature, FUTURE_ANNOTATIONS) == 0) {\n            ff->ff_features |= CO_FUTURE_ANNOTATIONS;\n        } else if (strcmp(feature, \"braces\") == 0) {\n            PyErr_SetString(PyExc_SyntaxError,\n                            \"not a chance\");\n            PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);\n            return 0;\n        } else {\n            PyErr_Format(PyExc_SyntaxError,\n                         UNDEFINED_FUTURE_FEATURE, feature);\n            PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);\n            return 0;\n        }\n    }\n    return 1;\n}\n\nstatic int\nfuture_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)\n{\n    if (!(mod->kind == Module_kind || mod->kind == Interactive_kind)) {\n        return 1;\n    }\n\n    Py_ssize_t n = asdl_seq_LEN(mod->v.Module.body);\n    if (n == 0) {\n        return 1;\n    }\n\n    Py_ssize_t i = 0;\n    if (_PyAST_GetDocString(mod->v.Module.body) != NULL) {\n        i++;\n    }\n\n    for (; i < n; i++) {\n        stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);\n\n        /* The only things that can precede a future statement\n         *  are another future statement and a doc string.\n         */\n\n        if (s->kind == ImportFrom_kind) {\n            identifier modname = s->v.ImportFrom.module;\n            if (modname &&\n                _PyUnicode_EqualToASCIIString(modname, \"__future__\")) {\n                if (!future_check_features(ff, s, filename)) {\n                    return 0;\n                }\n                ff->ff_location = SRC_LOCATION_FROM_AST(s);\n            }\n            else {\n                return 1;\n            }\n        }\n        else {\n            return 1;\n        }\n    }\n    return 1;\n}\n\n\nint\n_PyFuture_FromAST(mod_ty mod, PyObject *filename, PyFutureFeatures *ff)\n{\n    ff->ff_features = 0;\n    ff->ff_location = (_PyCompilerSrcLocation){-1, -1, -1, -1};\n\n    if (!future_parse(ff, mod, filename)) {\n        return 0;\n    }\n    return 1;\n}\n"
  },
  {
    "path": "Game/CMakeLists.txt",
    "content": "enable_language(ASM_NASM)\nset(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)\nset(CMAKE_ASM_NASM_LINK_EXECUTABLE \"ld <CMAKE_ASM_NASM_LINK_FLAGS> <LINK_FLAGS> <OBJECTS>  -o <TARGET> <LINK_LIBRARIES>\")\nset(CMAKE_ASM_NASM_FLAGS_DEBUG \"-g -Fdwarf\")\n\nset(SOURCE_FILES\n    graphics.asm\n    linked_list.asm\n    main.asm\n    memory.asm\n    utils.asm\n)\nset_source_files_properties(${SOURCE_FILES} PROPERTIES LANGUAGE ASM_NASM)\n\nadd_executable(asm_game\n    ${SOURCE_FILES}\n)\n\ntarget_link_libraries(asm_game X11)\ntarget_link_options(asm_game PRIVATE --dynamic-linker /lib64/ld-linux-x86-64.so.2)\n"
  },
  {
    "path": "Game/graphics.asm",
    "content": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;         Distributed under the Boost Software License, Version 1.0.          ;;\n;;            (See accompanying file LICENSE or copy at                        ;;\n;;                 https://www.boost.org/LICENSE_1_0.txt)                      ;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\nglobal create_window\nglobal try_get_event\n\nextern XBlackPixel\nextern XCheckWindowEvent\nextern XClearWindow\nextern XCreateGC\nextern XCreateSimpleWindow\nextern XDefaultRootWindow\nextern XDefaultScreen\nextern XFillRectangle\nextern XFlush\nextern XLookupKeysym\nextern XMapWindow\nextern XNextEvent\nextern XSync\nextern XOpenDisplay\nextern XSelectInput\nextern XSetForeground\nextern XWhitePixel\n\nextern assert_not_null\nextern assert_null\nextern render_begin\nextern draw_rectangle\nextern render_end\nextern print\nextern print_num\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; This file contains functions for creating a window and rendering to it.\n\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Create and display an X Window.\n;\ncreate_window:\n    push rbp\n    mov rbp, rsp\n\n    ; X11 window setup\n\n    mov rdi, 0x0\n    call XOpenDisplay\n    mov [display], rax\n    mov rdi, rax\n    lea rsi, [x_open_display_failed]\n    call assert_not_null\n\n    call XDefaultScreen\n    mov [screen_number], rax\n\n    mov rdi, [display]\n    mov rsi, [screen_number]\n    call XWhitePixel\n    mov [white_colour], rax\n\n    mov rdi, [display]\n    mov rsi, [screen_number]\n    call XBlackPixel\n    mov [black_colour], rax\n\n    mov rdi, [display]\n    call XDefaultRootWindow\n    mov [default_root_window], rax\n\n    mov rdi, [display]\n    mov rsi, [default_root_window]\n    mov rdx, 0x0\n    mov rcx, 0x0\n    mov r8, 0x320\n    mov r9, 0x320\n    mov rax, [black_colour]\n    push rax\n    push rax\n    push 0x0\n    call XCreateSimpleWindow\n    mov [window], rax\n    add rsp, 0x18\n\n    mov rdi, [display]\n    mov rsi, [window]\n    mov rdx, 0x20003\n    call XSelectInput\n\n    mov rdi, [display]\n    mov rsi, [window]\n    call XMapWindow\n\n    mov rdi, [display]\n    mov rsi, [window]\n    mov rdx, 0x0\n    mov rcx, 0x0\n    call XCreateGC\n    mov [gc], rax\n\n    ; wait until window has appeared\nwait_loop_start:\n    mov rdi, [display]\n    lea rsi, [event]\n    call XNextEvent\n\n    mov eax, [event]\n    cmp rax, 0x13\n    je wait_loop_end\n\n    jmp wait_loop_start\nwait_loop_end:\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Try and get an event\n;\n; @returns\n;   Address of an event, or 0x0 if no event was available.\n;\ntry_get_event:\n    push rbp\n    mov rbp, rsp\n\n    ; see if we want have events\n    mov rdi, [display]\n    mov rsi, [window]\n    mov rdx, 0x03\n    lea rcx, [event]\n    call XCheckWindowEvent\n\n    cmp rax, 0x0\n    je try_get_event_end\n\n    ; we got an event so return pointer to event object\n    lea rax, [event]\n\ntry_get_event_end:\n    pop rbp\n    ret\n\n; Perform pre-render tasks\nrender_begin:\n    push rbp\n    mov rbp, rsp\n\n    ; clear window\n    mov rdi, [display]\n    mov rsi, [window]\n    call XClearWindow\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Draw a rectangle.\n;\n; @param rdi\n;   X coord of rectangle\n;\n; @param rsi\n;   Y coord of rectangle\n;\n; @param rdx\n;   Width of rectangle\n;\n; @param rcx\n;   Height of rectangle\n;\ndraw_rectangle:\n    push rbp\n    mov rbp, rsp\n\n    ; push args to stack so we can easily pop them into the correct registers\n    push rcx\n    push rdx\n    push rsi\n    push rdi\n\n    ; set foreground color for drawing\n    mov rdi, [display]\n    mov rsi, [gc]\n    mov rdx, [white_colour]\n    call XSetForeground\n\n    ; draw paddle\n    mov rdi, [display]\n    mov rsi, [window]\n    mov rdx, [gc]\n    pop rcx\n    pop r8\n    pop r9 ; note that the last arg is now at at the top of the stack\n    call XFillRectangle\n    add rsp, 0x8\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Perform post-render tasks\n;\nrender_end:\n    push rbp\n    mov rbp, rsp\n\n    ; ensure all draw commands are flushed\n    mov rdi, [display]\n    call XFlush\n\n    pop rbp\n    ret\n\nsection .data\n    display: dq 0x0\n    screen_number: dq 0x0\n    black_colour: dq 0x0\n    white_colour: dq 0x0\n    default_root_window: dq 0x0\n    window: dq 0x0\n    gc: dq 0x0\n    event: resb 0xc0\n\nsection .rodata\n    hello_world: db \"hello world\", 0xa, 0x0\n    goodbye: db \"goodbye\", 0xa, 0x0\n    sleep_for: db \"sleep_for: \", 0x0\n    x_open_display_failed: db \"XOpenDisplay failed\", 0xa, 0x0\n    x_select_input_failed: db \"XSelectInput failed\", 0xa, 0x0\n    x_set_foreground_failed: db \"XSetForeground failed\", 0xa, 0x0\n"
  },
  {
    "path": "Game/linked_list.asm",
    "content": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;         Distributed under the Boost Software License, Version 1.0.          ;;\n;;            (See accompanying file LICENSE or copy at                        ;;\n;;                 https://www.boost.org/LICENSE_1_0.txt)                      ;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\nglobal linked_list_init\nglobal linked_list_iterator\nglobal linked_list_iterator_advance\nglobal linked_list_iterator_remove\nglobal linked_list_iterator_value\nglobal linked_list_push_back\n\nextern memory_malloc\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Simple linked list data structure. Consists of a head node then optional data nodes.\n; Each node has the following layout:\n; +-------+\n; | value | = 8 bytes\n; +-------+\n; |  ptr  | = 8 bytes\n; +-------+\n;\n; This means that each node can store 8 bytes of data, which could be anything, even a pointer to a larger allocated\n; block of data\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Create a new linked list.\n;\n; @returns\n;   A handle to the linked list which can be passed to further linked list methods.\n;\nlinked_list_init:\n    push rbp\n    mov rbp, rsp\n\n    mov rdi, 0x0\n    call allocate_node ; create the head node\n\n    ; we return the head node as the handle\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Insert a new value to the back of the linked list.\n;\n; @param rdi\n;   Handle to linked list to insert into.\n;\n; @param rsi\n;   Value to insert.\n;\n; @returns\n;   Address if newly created node.\n;\nlinked_list_push_back:\n    push rbp\n    mov rbp, rsp\n\n    mov rbx, rdi\n\n    ; find end of list\nlinked_list_push_back_find_end:\n    mov rcx, [rbx + 0x8] ; get next pointer\n    cmp rcx, 0x0 ; if null then we are at the last node\n    je linked_list_push_back_do_insert\n\n    add rbx, 0x10\n    jmp linked_list_push_back_find_end\n\nlinked_list_push_back_do_insert:\n    push rbx\n    mov rdi, rsi\n    call allocate_node ; allocate new node\n\n    pop rbx\n    mov [rbx + 0x8], rax ; set new node as next of last node\n    mov rax, [rbx + 0x8] ; set return value as address of new node\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Get an iterator to the start of the linked list. This is a handle that can ba passed to other iterator functions.\n;\n; @rdi\n;   Handle to list to get iterator for.\n;\n; @returns\n;   Iterator handle.\n;\nlinked_list_iterator:\n    push rbp\n    mov rbp, rsp\n\n    call linked_list_iterator_advance ; we can cheat here by just returning the address of the first node after the head\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Remove a node from the linked list. \n;\n; @param rdi\n;   Handle to linked list to remove node from.\n;\n; @parma rsi\n;   Iterator to remove\n; \nlinked_list_iterator_remove:\n    push rbp\n    mov rbp, rsp\n\nlinked_list_remove_find_begin:\n    mov rax, [rdi + 8]\n    cmp rax, 0x0\n    je linked_list_remove_end\n\n    cmp rax, rsi\n    je linked_list_remove_find_end\n\n    mov rdi, rax\n    jmp linked_list_remove_find_begin\n\nlinked_list_remove_find_end:\n\n    mov rbx, [rsi + 8] ; get next of node we are removing\n    mov [rdi + 8], rbx ; set prev nodes next to next of removing node\n\nlinked_list_remove_end: \n    pop rbp\n    ret\n\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Advance an iterator.\n;\n; @param rdi\n;   Handle to iterator to advance.\n;\n; @returns\n;   Handle to advanced iterator.\n;\nlinked_list_iterator_advance:\n    push rbp\n    mov rbp, rsp\n\n    mov rax, [rdi + 0x8]\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Get the value from an iterator.\n;\n; @param rdi\n;   Handle to iterator to get value for.\n;\n; @returns\n;   Value stored in node iterator is referencing.\n;\nlinked_list_iterator_value:\n    push rbp\n    mov rbp, rsp\n\n    mov rax, [rdi]\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Allocate a new node and store a value in it.\n;\n; @param rdi\n;   Value to store in node\n;\n; @returns\n;   Address of allocated node.\n;\nallocate_node:\n    push rbp\n    mov rbp, rsp\n\n    push rdi\n    \n    mov rdi, 0x10\n    call memory_malloc ; allocate space for node\n\n    pop rdi\n    mov rbx, 0x0\n    mov [rax], rdi ; store value in node\n    mov [rax + 0x8], rbx ; set next to be null\n\n    pop rbp\n    ret\n"
  },
  {
    "path": "Game/main.asm",
    "content": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;         Distributed under the Boost Software License, Version 1.0.          ;;\n;;            (See accompanying file LICENSE or copy at                        ;;\n;;                 https://www.boost.org/LICENSE_1_0.txt)                      ;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\nsection .text\n\nglobal _start\n\nextern XBlackPixel\nextern XClearWindow\nextern XFillRectangle\nextern XFlush\nextern XLookupKeysym\nextern XSync\nextern XSetForeground\nextern XWhitePixel\n\nextern assert_not_null\nextern assert_null\nextern create_window\nextern draw_rectangle\nextern exit\nextern get_time\nextern linked_list_init\nextern linked_list_iterator\nextern linked_list_iterator_advance\nextern linked_list_iterator_remove\nextern linked_list_iterator_value\nextern linked_list_push_back\nextern memory_malloc\nextern print\nextern print_num\nextern render_begin\nextern render_end\nextern sleep_ms\nextern try_get_event\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Entry point to the program\n;\n_start:\n\n    lea rdi, [hello_world]\n    call print\n\n    call create_entities\n    call create_window\n\nmain_loop_start:\n    ; get time at start of frame\n    call get_time\n    mov [frame_time], rax\n\n    call try_get_event\n    mov r12, rax\n\n    ; no event so go to game logic\n    cmp rax, 0x0\n    je game_logic\n\n    ; check if its a press event\n    mov eax, [r12]\n    cmp rax, 0x2\n    je handle_key\n\n    ; check if its a release event\n    mov eax, [r12]\n    cmp rax, 0x3\n    jne game_logic ; if not go to game logic\n\nhandle_key:\n    ; get the key code for the release event\n    lea rdi, [r12]\n    mov rsi, 0x0\n    call XLookupKeysym\n\n    ; see if its an XK_Escape\n    cmp rax, 0xff1b\n    jne handle_arrow_key\n\n    ; if its key press then exit the game\n    mov eax, [r12]\n    cmp rax, 0x2\n    je main_loop_end\n\nhandle_arrow_key:\n    ; if it's not an XK_Right then check if its an XK_Left\n    cmp rax, 0xff53\n    jne left_check\n\n    mov eax, [r12]\n    cmp rax, 0x2\n    jne right_release\n\n    mov rax, 0x1\n    mov [right_arrow_status], rax\n    jmp game_logic\n\nright_release:\n    mov rax, 0x0\n    mov [right_arrow_status], rax\n    jmp game_logic\n\nleft_check:\n    ; if its not an XK_Left then go to game logic\n    cmp rax, 0xff51\n    jne game_logic\n\n    mov eax, [r12]\n    cmp rax, 0x2\n    jne left_release\n\n    mov rax, 0x1\n    mov [left_arrow_status], rax\n    jmp game_logic\n\nleft_release:\n    mov rax, 0x0\n    mov [left_arrow_status], rax\n\ngame_logic:\n    mov rax, [right_arrow_status]\n    cmp rax, 0x0\n    je right_arrow_update_finish\n\n    mov rax, [paddle_x]\n    add rax, 10\n    mov [paddle_x], rax\nright_arrow_update_finish:\n\n    mov rax, [left_arrow_status]\n    cmp rax, 0x0\n    je left_arrow_update_finish\n\n    mov rax, [paddle_x]\n    sub rax, 10\n    mov [paddle_x], rax\nleft_arrow_update_finish:\n\n    call ball_update\n    call handle_collisions\n    call render\n    \n    ; get end frame time\n    call get_time\n\n    ; see if we have spent less than 30ms in this frame\n    mov rbx, [frame_time]\n    sub rax, rbx\n    cmp rax, 30\n\n    jg main_loop_start\n\n    ; sleep for remainder of 30ms\n    mov rbx, 30\n    sub rbx, rax\n    mov rdi, rbx\n    call sleep_ms\n        \n    jmp main_loop_start\nmain_loop_end:\n\n    lea rdi, [goodbye]\n    call print\n\n    mov rdi, 0x0\n    call exit\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Render the entity list.\n;\nrender:\n    push rbp\n    mov rbp, rsp\n\n    call render_begin\n\n    mov rdi, [entity_list]\n    call linked_list_iterator\n    push rax\n\nrender_loop_start:\n    mov rax, [rsp]\n    cmp rax, 0x0\n    je render_loop_end\n\n    mov rdi, [rsp]\n    call linked_list_iterator_value\n\n    mov rdi, [rax]\n    mov rsi, [rax + 8]\n    mov rdx, [rax + 16]\n    mov rcx, [rax + 24]\n    call draw_rectangle\n\n    mov rdi, [rsp]\n    call linked_list_iterator_advance\n    mov [rsp], rax\n    jmp render_loop_start\n\n    call render_end\nrender_loop_end:\n\n    add rsp, 0x8\n    pop rbp\n    ret\n\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Perform collision detections and resolutions.\n;\nhandle_collisions:\n    push rbp\n    mov rbp, rsp\n    sub rsp, 8\n\n    mov rdi, [entity_list]\n    call linked_list_iterator\n    mov [rsp], rax\n\n    mov rdi, [rsp]\n    call linked_list_iterator_advance ; move past first entity so we don't check ball collides with itself\n    mov [rsp], rax\n\n    ; check collision with paddle\n    mov rdi, [rsp]\n    call linked_list_iterator_value\n\n    lea rdi, [ball_x]\n    mov rsi, rax\n    call check_entity_collision\n\n    cmp rax, 0x0\n    je paddle_collision_end\n\n    call handle_ball_paddle_collision\n\npaddle_collision_end:\n\n    mov rdi, [rsp]\n    call linked_list_iterator_advance ; move passed paddle, onto the bricks\n    mov [rsp], rax\n\nbrick_collision_loop_start:\n    ; if we are at the end of the linked list then stop\n    mov rax, [rsp]\n    cmp rax, 0x0\n    je brick_collision_loop_end\n\n    ; get value from the iterator (which will be the address of an entity)\n    mov rdi, [rsp]\n    call linked_list_iterator_value\n\n    ; check if ball is colliding with block\n    lea rdi, [ball_x]\n    mov rsi, rax\n    call check_entity_collision\n\n    cmp rax, 0x0\n    jne handle_collision_found\n\n    ; if no collision then move iterator to next block\n    mov rdi, [rsp]\n    call linked_list_iterator_advance\n    mov [rsp], rax\n\n    jmp brick_collision_loop_start\n\nhandle_collision_found:\n    ; remove block from linked list\n    mov rdi, [entity_list]\n    mov rsi, [rsp]\n    call linked_list_iterator_remove\n\n    ; invert ball velocity\n    mov rax, 0xa\n    mov [ball_velocity_y], rax\n\nbrick_collision_loop_end:\n\n    add rsp, 8\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Handle ball paddle collision. This function assumes the collision has already been detected and needs resolving.\n;\nhandle_ball_paddle_collision: \n    push rbp\n    mov rbp, rsp\n\n    ; we can simply just grab the data we need without having to go through the linked list\n    mov rax, [ball_x]\n    mov rbx, [paddle_x]\n\n    ; check of collision happened on the left third of the paddle\n    add rbx, 6\n    cmp rax, rbx\n    jge check_middle\n\n    ; if it did then set the ball moving up and left\n    mov rax, -7\n    mov [ball_velocity_x], rax\n    mov [ball_velocity_y], rax\n    jmp handle_ball_paddle_collision_end\n\ncheck_middle:\n    ; check of collision happened on the middle third of the paddle\n    add rbx, 8\n    cmp rax, rbx\n    jge check_end\n\n    ; if it did then set the ball moving straight up\n    mov rax, 0\n    mov [ball_velocity_x], rax\n    mov rax, -10\n    mov [ball_velocity_y], rax\n    jmp handle_ball_paddle_collision_end\n\ncheck_end:\n    ; the only other choice is the paddle hit the right third, so move it up and right\n    mov rax, 7\n    mov [ball_velocity_x], rax\n    mov rax, -7\n    mov [ball_velocity_y], rax\n    jmp handle_ball_paddle_collision_end\n\nhandle_ball_paddle_collision_end:\n    pop rbp\n    ret\n\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Check collisions between two entities.\n;\n; @param rdi\n;   Address of first entity.\n;\n; @param rsi\n;   Address of second entity.\n;\n; @returns\n;   0x1 if collision was detected, otherwise 0x0.\n;\ncheck_entity_collision:\n    push rbp\n    mov rbp, rsp\n\n    ; rect1.x < rect2.x + rect2.w\n    mov rax, [rdi]\n    mov rbx, [rsi]\n    mov rcx, [rsi + 16]\n    add rbx, rcx\n    cmp rax, rbx\n    jge no_collision\n\n    ; rect1.x + rect1.w > rect2.x\n    mov rax, [rdi]\n    mov rbx, [rdi + 16]\n    add rax, rbx\n    mov rcx, [rsi]\n    cmp rax, rcx\n    jle no_collision\n\n    ; rect1.y < rect2.y + rect2.h\n    mov rax, [rdi + 8]\n    mov rbx, [rsi + 8]\n    mov rcx, [rsi + 24]\n    add rbx, rcx\n    cmp rax, rbx\n    jge no_collision\n\n    ; rect1.h + rect1.y > rect1.y\n    mov rax, [rdi + 24]\n    mov rbx, [rdi + 8]\n    add rax, rbx\n    mov rcx, [rsi + 8]\n    cmp rax, rcx\n    jle no_collision\n\n    mov rax, 0x1\n    jmp check_collision_end\n    \nno_collision:\n    mov rax, 0x0\n\ncheck_collision_end:\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Perform ball update logic\n;\nball_update:\n    push rbp\n    mov rbp, rsp\n\n    ; add y velocity to ball\n    mov rax, [ball_y]\n    add rax, [ball_velocity_y]\n    mov [ball_y], rax\n\n    ; add x velocity to ball\n    mov rax, [ball_x]\n    add rax, [ball_velocity_x]\n    mov [ball_x], rax\n\n    ; check if ball has gone off the top of the screen\n    mov rax, [ball_y]\n    cmp rax, 0x0\n    jg check_ball_right_side\n\n    ; invert y velocity\n    mov rax, 0xa\n    mov [ball_velocity_y], rax\n\ncheck_ball_right_side:\n\n    ; check if ball has gone of right of the screen\n    mov rax, [ball_x]\n    cmp rax, 800\n    jl check_ball_left_side\n\n    ; invert x velocity\n    mov rax, [ball_velocity_x]\n    neg rax\n    mov [ball_velocity_x], rax\n    jmp ball_update_end\n\ncheck_ball_left_side:\n    ; check if ball has gone of the left of the screen\n    mov rax, [ball_x]\n    cmp rax, 0\n    jg ball_update_end\n\n    ; invert x velocity\n    mov rax, [ball_velocity_x]\n    neg rax\n    mov [ball_velocity_x], rax\n\nball_update_end:\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Create all the entities for the game and insert them into a linked list.\n;\ncreate_entities:\n    push rbp\n    mov rbp, rsp\n\n    call linked_list_init\n    mov [entity_list], rax\n\n    ; collision code assumes ball is first in the entity list, then the paddle then the bricks\n    mov rdi, [entity_list]\n    lea rsi, [ball_x] ; store address of ball in list\n    call linked_list_push_back\n\n    mov rdi, [entity_list]\n    lea rsi, [paddle_x] ; store address of paddle data in list\n    call linked_list_push_back\n\n    mov rdi, 50\n    call create_brick_row\n    mov rdi, 80\n    call create_brick_row\n    mov rdi, 110\n    call create_brick_row\n    mov rdi, 140\n    call create_brick_row\n    mov rdi, 170\n    call create_brick_row\n    mov rdi, 200\n    call create_brick_row\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Adds a row of 10 bricks to the entity list\n;\n; @param rdi\n;   Y coord of row.\n;\ncreate_brick_row:\n    push rbp\n    mov rbp, rsp\n    sub rsp, 24\n\n    mov [rsp + 16], rdi\n\n    mov rax, 0\n    mov [rsp], rax ; store loop counter\n    mov rax, 20\n    mov [rsp + 8], rax ; store initial x coord\n\ncreate_row_start:\n\n    mov rax, [rsp]\n    cmp rax, 10\n    je create_row_end ; leave loop if we have added 10 bricks\n\n    mov rdi, 32\n    call memory_malloc\n\n    ; fill out entity struct\n    mov rbx, [rsp + 8]\n    mov [rax], rbx\n    mov rbx, [rsp + 16]\n    mov [rax + 8], rbx\n    mov rbx, 58\n    mov [rax + 16], rbx\n    mov rbx, 20\n    mov [rax + 24], rbx\n\n    mov rdi, [entity_list]\n    mov rsi, rax\n    call linked_list_push_back\n\n    ; advance x coord for next iteration\n    mov rax, [rsp + 8]\n    add rax, 78\n    mov [rsp + 8], rax\n\n    ; increment iteration count\n    mov rax, [rsp]\n    inc rax\n    mov [rsp], rax\n    jmp create_row_start\n\ncreate_row_end:\n\n    add rsp, 24\n    pop rbp\n    ret\n\nsection .data\n    entity_list: dq 0x0\n    paddle_x: dq 0x12c\n    paddle_y: dq 0x30c\n    paddle_width: dq 0xc8\n    paddle_height: dq 0x14\n    ball_x: dq 0x1a4\n    ball_y: dq 0x190\n    ball_width: dq 0xa\n    ball_height: dq 0xa\n    ball_velocity_y: dq 0xa\n    ball_velocity_x: dq 0x0\n    left_arrow_status: dq 0x0\n    right_arrow_status: dq 0x0\n    frame_time: dq 0x0\n\nsection .rodata\n    hello_world: db \"hello world\", 0xa, 0x0\n    goodbye: db \"goodbye\", 0xa, 0x0\n    sleep_for: db \"sleep_for: \", 0x0\n"
  },
  {
    "path": "Game/memory.asm",
    "content": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;         Distributed under the Boost Software License, Version 1.0.          ;;\n;;            (See accompanying file LICENSE or copy at                        ;;\n;;                 https://www.boost.org/LICENSE_1_0.txt)                      ;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\nglobal memory_mmap\nglobal memory_malloc\n\nextern assert_not_null\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; This file contains various utilities for dynamically allocating memory.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Map new pages into the process.\n;\n; @param rdi\n;   Number of bytes to map.\n;\n; @returns\n;   Address of allocated memory.\n;\nmemory_mmap:\n    push rbp\n    mov rbp, rsp\n\n    push rdi\n\n    mov rax, 0x9\n    mov rdi, 0x0 ; kernel chooses address\n    pop rsi ; number of bytes to map\n    mov rdx, 0x3 ; PROT_READ | PROT_WRITE\n    mov r10, 0x22 ; MAP_PRIVATE | MAP_ANONYMOUS\n    mov r8, 0x0 ; no backing file\n    mov r9, 0x0 ; no offset\n\n    syscall\n\n    push rax\n\n    mov rdi, rax\n    sub rdi, 0xffffffffffffffff ; check MAP_FAILED was not returned\n    lea rsi, [mmap_failed] \n    call assert_not_null\n    pop rax\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Simple implementation of malloc.\n;\n; Note that there is no equivalent of free, this just allocates memory from a large static buffer.\n;\n; @param rdi\n;   Number of bytes to allocate.\n;\n; @returns\n;   Address of allocated memory.\n;\nmemory_malloc:\n    push rbp\n    mov rbp, rsp\n\n    push rdi\n\n    ; if this is the first call then allocate a large fixed size buffer to \"malloc\" from\n    mov rax, [malloc_init]\n    cmp rax, 0x0\n    jne malloc_do_init_done\n\n    mov rdi, 4096000\n    call memory_mmap\n\n    mov [malloc_memory], rax\n    mov rax, 0x1\n    mov [malloc_init], rax\nmalloc_do_init_done:\n\n    pop rdi\n\n    mov rax, [malloc_memory] ; get address from head of buffer\n    mov rbx, rax\n    add rbx, rdi ; advance buffer by requested size\n    mov [malloc_memory], rbx\n\n    pop rbp\n    ret\n\nsection .data\n    malloc_init: dq 0x0\n    malloc_memory: dq 0x0\n\nsection .rodata\n    mmap_failed: db \"mmap failed\", 0xa, 0x0\n"
  },
  {
    "path": "Game/utils.asm",
    "content": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;;         Distributed under the Boost Software License, Version 1.0.          ;;\n;;            (See accompanying file LICENSE or copy at                        ;;\n;;                 https://www.boost.org/LICENSE_1_0.txt)                      ;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\nglobal assert_not_null\nglobal assert_null\nglobal exit\nglobal game_malloc\nglobal game_mmap\nglobal get_time\nglobal print\nglobal print_num\nglobal sleep_ms\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; This file contains various utilities.\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Print a string to STDOUT.\n;\n; @param rdi\n;   Address of null terminated string to print.\n;\n; @returns\n;   Number of bytes output.\n;\nprint:\n    push rbp\n    mov rbp, rsp\n\n    mov r10, rdi ; save off string address\n    mov r9, rdi ; iterator register for string\n    movzx rax, byte [r9] ; load first byte\n    mov rcx, 0x0 ; accumulator for string length\n\ncount_null_start:\n    cmp rax, 0x0 ; are we at the null byte?\n    je count_null_end\n\n    inc rcx ; increment accumulator\n    inc r9 ; move to next byte\n    movzx rax, byte [r9] ; load byte\n    jmp count_null_start \n\ncount_null_end:\n    ; syscall to write string to stdout\n    mov rax, 0x1\n    mov rdi, 0x1;\n    mov rsi, r10\n    mov rdx, rcx\n    syscall\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Print an integer to STDOUT (with a new line).\n;\n; @param rdi\n;   Unsigned number to print.\n;\nprint_num:\n    push rbp\n    mov rbp, rsp\n    sub rsp, 0x15 ; get stack space for two buffers, one to convert the number into a string (in reverse order)]\n                  ; and another to reverse the string into\n\n    mov r9, rdi ; r9 will be the mutable copy of the input number\n    mov rdx, rdi\n    mov rcx, 0x0 ; accumulator for string length\n\n    mov rdi, rsp ; set destination as start of first buffer\n\nwrite_loop_start:\n\n    mov rax, r9 ; load number to be divided\n    mov rdx, 0 ; zero out remainder\n    mov r10, 0xa ; divisor by 10\n    div r10 ; rdx = remainder, rax = quotient\n\n    mov r11, 0x30\n    add rdx, r11 ; add 0x30 to remainder to get ASCII code for number\n\n    mov [rdi], dl ; write ASCII byte to buffer\n    inc rcx ; increment how many characters have been written\n\n    cmp rax, 0x0 ; check if we have reached the end\n    je write_loop_end\n    \n    inc rdi\n    mov r9, rax ; load remainder into r9 so it can be divided again\n    jmp write_loop_start\n\nwrite_loop_end:\n\n    mov rsi, rdi ; move destination into source so we can reverse it\n    mov rdi, rsp\n    add rdi, 0xa ; set destination to start of second buffer\n\nreverse_loop_start:\n    cmp rcx, 0x0\n    je reverse_loop_end\n\n    movzx rax, byte[rsi]\n    mov [rdi], al ; write ascii character into second buffer\n    dec rsi\n    inc rdi\n\n    dec rcx; ; keep track of how many characters we've reversed\n    jmp reverse_loop_start\nreverse_loop_end:\n\n    mov rax, 0xa\n    mov [rdi], al ; write newline character into the end\n\n    mov rdi, rsp\n    add rdi, 0xa ; print second buffer\n    call print\n\n    leave\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Assert the input is not null.\n;\n; @param rdi\n;   Value to check is not null.\n;\n; @param rsi\n;   Pointer to error message string.\n;\nassert_not_null:\n    push rbp\n    mov rbp, rsp\n\n    cmp rdi, 0x0\n    jne assert_not_null_end\n\n    mov rdi, rsi\n    call print\n\n    mov rdi, 0x1\n    call exit\n\nassert_not_null_end:\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Assert the input is null.\n;\n; @param rdi\n;   Value to check is null.\n;\n; @param rsi\n;   Pointer to error message string.\n;\nassert_null:\n    push rbp\n    mov rbp, rsp\n\n    cmp rdi, 0x0\n    je assert_null_end\n\n    mov rdi, rsi\n    call print\n\n    mov rdi, 0x1\n    call exit\n\nassert_null_end:\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Exit the program.\n;\n; @param rdi\n;   Exit code.\n;\nexit:\n    mov rax, 0x3c\n    syscall\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Sleep the current process for the supplied number of milliseconds.\n;\n; @param rdi\n;   Number of milliseconds to sleep for.\n;\nsleep_ms:\n    push rbp\n    mov rbp, rsp\n\n    imul rdi, rdi, 1000000 ; convert supplied ms to ns\n    xor rax, rax \n    ; recreate struct timepec on the stack\n    push rdi ; tv_nsec\n    push rax ; tv_sec\n\n    ; nanosleep syscall\n    mov rax, 0x23\n    mov rdi, rsp\n    mov rsi, 0x0\n    syscall\n\n    add rsp, 16\n\n    pop rbp\n    ret\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; Get the time since epoch in milliseconds.\n;\n; @returns\n;   Milliseconds since epoch.\n;\nget_time:\n    push rbp\n    mov rbp, rsp\n\n    ; create empty timeval struct on the stack\n    push 0x0 ; tv_usec\n    push 0x0 ; tv_sec\n\n    ; gettimeofday syscall\n    mov rax, 0x60\n    mov rdi, rsp\n    mov rsi, 0x0\n    syscall\n\n    pop rax ; seconds\n    pop rbx ; microseconds\n\n    imul rax, rax, 1000000 ; convert seconds to microseconds\n    add rax, rbx ; add microseconds\n    mov rdx, 0x0\n    mov rbx, 1000\n    div rbx ; convert to milliseconds\n\n    pop rbp\n    ret\n"
  },
  {
    "path": "Game I/CMakeLists.txt",
    "content": "add_executable(c_game\n    c_list.c\n    c_rectangle.c\n    c_vector2.c\n    c_window.c\n    main.c\n)\n\ntarget_link_directories(c_game PRIVATE ${sdl_BINARY_DIR})\ntarget_include_directories(c_game PRIVATE ${sdl_SOURCE_DIR}/include)\n\ntarget_link_libraries(c_game SDL2::SDL2-static)\n"
  },
  {
    "path": "Game I/c_key_event.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n/**\n * Enumeration of possible key states.\n */\ntypedef enum C_KeyState\n{\n    C_KEYSTATE_DOWN,\n    C_KEYSTATE_UP\n} C_KeyState;\n\n/**\n * Enumeration of possible input keys (maybe incomplete).\n */\ntypedef enum C_Key\n{\n    C_KEY_ESCAPE,\n    C_KEY_LEFT,\n    C_KEY_RIGHT,\n} C_Key;\n\n/**\n * Struct encapsulating the data for a key press event.\n */\ntypedef struct C_KeyEvent\n{\n    C_KeyState key_state;\n    C_Key key;\n} C_KeyEvent;\n"
  },
  {
    "path": "Game I/c_list.c",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#include \"c_list.h\"\n\n#include <assert.h>\n#include <stdlib.h>\n\n#include \"c_result.h\"\n\n/**\n * Internal node struct. Stores value, next node and dtor function for value.\n */\ntypedef struct Node\n{\n    void *value;\n    struct Node *next;\n    void (*dtor)(void *);\n} Node;\n\n/**\n * Internal list struct. Stores a head sentinel node.\n */\ntypedef struct C_List\n{\n    Node *head;\n} C_List;\n\n/**\n * Internal iterator struct. Stores the node it is referencing.\n */\ntypedef struct C_ListIter\n{\n    Node *node;\n} C_ListIter;\n\nC_Result c_list_create(C_List **list)\n{\n    assert(list != NULL);\n\n    C_Result result = C_SUCCESS;\n\n    // allocate the list\n    C_List *new_list = (C_List *)calloc(sizeof(C_List), 1u);\n    if (new_list == NULL)\n    {\n        result = C_FAILED_TO_ALLOCATE_LIST;\n        goto fail;\n    }\n\n    // allocate the head node\n    new_list->head = (Node *)calloc(sizeof(Node), 1u);\n    if (new_list->head == NULL)\n    {\n        result = C_FAILED_TO_ALLOCATE_NODE;\n        goto fail;\n    }\n\n    // assign the list to the user supplied pointer\n    *list = new_list;\n\n    return result;\n\nfail:\n    // clean up and return error code\n    c_list_destroy(new_list);\n    return result;\n}\n\nvoid c_list_destroy(C_List *list)\n{\n    if (list == NULL)\n    {\n        return;\n    }\n\n    Node *cursor = list->head;\n\n    // walk through the linked list\n    do\n    {\n        Node *next = cursor->next;\n\n        // if we have a dtor the call it\n        if (cursor->dtor != NULL)\n        {\n            cursor->dtor(cursor->value);\n        }\n\n        // clean up the node and advance\n        free(cursor);\n        cursor = next;\n    } while (cursor != NULL);\n\n    free(list);\n}\n\nC_Result c_list_push_back(C_List *list, void *value)\n{\n    return c_list_push_back_dtor(list, value, NULL);\n}\n\nC_Result c_list_push_back_dtor(C_List *list, void *value, void (*dtor)(void *))\n{\n    assert(list != NULL);\n\n    C_Result result = C_SUCCESS;\n\n    // walk the list looking for rhe last node\n    Node *cursor = list->head;\n    while (cursor->next != NULL)\n    {\n        cursor = cursor->next;\n    }\n\n    // allocate a new node\n    Node *new_node = (Node *)calloc(sizeof(Node), 1u);\n    if (new_node == NULL)\n    {\n        result = C_FAILED_TO_ALLOCATE_NODE;\n        goto end;\n    }\n\n    // store the supplied data abd wire up the node to the end\n    new_node->value = value;\n    new_node->dtor = dtor;\n    cursor->next = new_node;\n\nend:\n    return result;\n}\n\nvoid c_list_remove(C_List *list, const C_ListIter *iter)\n{\n    assert(list != NULL);\n    assert(iter != NULL);\n\n    // walk the list looking for the node\n    Node *cursor = list->head;\n    while ((cursor->next != NULL) && (cursor->next != iter->node))\n    {\n        cursor = cursor->next;\n    }\n\n    // if we didn't reach the end of the list then we found the node\n    if (cursor->next != NULL)\n    {\n        Node *to_remove = cursor->next;\n        Node *next = to_remove->next;\n\n        // if we have a dtor the call it\n        if (to_remove->dtor != NULL)\n        {\n            to_remove->dtor(to_remove->value);\n        }\n\n        // free the node and remove it from the list\n        free(to_remove);\n        cursor->next = next;\n    }\n}\n\nC_Result c_list_iterator_create(const C_List *list, C_ListIter **iter)\n{\n    assert(list != NULL);\n    assert(iter != NULL);\n\n    C_Result result = C_SUCCESS;\n\n    // allocate the iterator\n    C_ListIter *new_iter = (C_ListIter *)calloc(sizeof(C_ListIter), 1u);\n    if (new_iter == NULL)\n    {\n        result = C_FAILED_TO_ALLOCATE_ITERATOR;\n        goto end;\n    }\n\n    c_list_iterator_reset(list, &new_iter);\n\n    // assign the iterator to the user supplied pointer\n    *iter = new_iter;\n\nend:\n    return result;\n}\n\nvoid c_list_iterator_destroy(C_ListIter *iter)\n{\n    free(iter);\n}\n\nvoid c_list_iterator_advance(C_ListIter **iter)\n{\n    assert(*iter != NULL);\n\n    (*iter)->node = (*iter)->node->next;\n}\n\nvoid c_list_iterator_reset(const C_List *list, C_ListIter **iter)\n{\n    assert(*iter != NULL);\n\n    (*iter)->node = list->head->next;\n}\n\nbool c_list_iterator_at_end(C_ListIter *iter)\n{\n    assert(iter != NULL);\n\n    return iter->node == NULL;\n}\n\nvoid *c_list_iterator_value(const C_ListIter *iter)\n{\n    assert(iter != NULL);\n\n    return iter->node->value;\n}\n"
  },
  {
    "path": "Game I/c_list.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n#include <stdbool.h>\n\n#include \"c_result.h\"\n\n/**\n * Simple linked list data structure which can store void*.\n */\n\n/**\n * Handle to internal list data.\n */\ntypedef struct C_List C_List;\n\n/**\n * Handle to internal list iterator data.\n */\ntypedef struct C_ListIter C_ListIter;\n\n/**\n * Create a new list.\n *\n * @param list\n *   Out parameter for created list.\n *\n * @returns\n *   C_SUCCESS on success\n *   Another Result type on error\n */\nC_Result c_list_create(C_List **list);\n\n/**\n * Destroy a list.\n *\n * Will call dtor function for each node (if supplied).\n *\n * @param list\n *   List to destroy.\n */\nvoid c_list_destroy(C_List *list);\n\n/**\n * Push a new value to the end of the list.\n *\n * @param list\n *   List to add to.\n *\n * @param value\n *   Value to add.\n *\n * @returns\n *   C_SUCCESS on success\n *   Another Result type on error\n */\nC_Result c_list_push_back(C_List *list, void *value);\n\n/**\n * Push a new value to the end of the list, with a dtor function which will get called when the node is removed or the\n * list is destroyed.\n *\n * @param list\n *   List to add to.\n *\n * @param value\n *   Value to add.\n *\n * @param dtor\n *   Function to call to cleanup value.\n *\n * @returns\n *   C_SUCCESS on success\n *   Another Result type on error\n */\nC_Result c_list_push_back_dtor(C_List *list, void *value, void (*dtor)(void *));\n\n/**\n * Remove the node referenced by an iterator from a list.\n *\n * @param list\n *   List to remove node from.\n *\n * @param iter\n *   Iterator to node to remove.\n */\nvoid c_list_remove(C_List *list, const C_ListIter *iter);\n\n/**\n * Create a new iterator to the first node.\n *\n * Note this will be NULL if the list is empty.\n *\n * @param list\n *   List to create iterator in.\n *\n * @param iter\n *  Out parameter for created iterator.\n *\n * @returns\n *   C_SUCCESS on success\n *   Another Result type on error\n */\nC_Result c_list_iterator_create(const C_List *list, C_ListIter **iter);\n\n/**\n * Destroy an iterator.\n *\n * @param iter\n *   Iterator to destroy.\n */\nvoid c_list_iterator_destroy(C_ListIter *iter);\n\n/**\n * Advance an iterator to the next node.\n *\n * @param iter\n *   Out parameter for advanced iterator.\n */\nvoid c_list_iterator_advance(C_ListIter **iter);\n\n/**\n * Reset an iterator back to the start of the list.\n *\n * @param list\n *   List to reset iterator in.\n *\n * @param iter\n *   Out paramater for reset iterator.\n */\nvoid c_list_iterator_reset(const C_List *list, C_ListIter **iter);\n\n/**\n * Check if an iterator is one past the end of the list.\n *\n * @param iter\n *   Iterator to check.\n *\n * @returns\n *   True if iterator is one past the end of the list, otherwise false.\n */\nbool c_list_iterator_at_end(C_ListIter *iter);\n\n/**\n * Get the value the iterator is referencing.\n *\n * @param iter\n *   Iterator to get value of.\n *\n * @returns\n *   Value at iterator.\n */\nvoid *c_list_iterator_value(const C_ListIter *iter);\n"
  },
  {
    "path": "Game I/c_rectangle.c",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#include \"c_rectangle.h\"\n\n#include <assert.h>\n#include <stdio.h>\n\n#include \"c_vector2.h\"\n\nC_Rectangle c_rectangle_create(const C_Vector2 *position, float width, float height)\n{\n    return c_rectangle_create_xy(position->x, position->y, width, height);\n}\n\nC_Rectangle c_rectangle_create_xy(float x, float y, float width, float height)\n{\n    C_Rectangle rect = {.position = {.x = x, .y = y}, .width = width, .height = height};\n    return rect;\n}\n\nvoid c_rectangle_translate(C_Rectangle *rectangle, const C_Vector2 *translation)\n{\n    c_vector2_add(&rectangle->position, translation);\n}\n\nvoid c_rectangle_translate_xy(C_Rectangle *rectangle, float x, float y)\n{\n    c_vector2_add_xy(&rectangle->position, x, y);\n}\n\nvoid c_rectangle_set_position(C_Rectangle *rectangle, const C_Vector2 *position)\n{\n    rectangle->position = *position;\n}\n\nvoid c_rectangle_set_position_xy(C_Rectangle *rectangle, float x, float y)\n{\n    rectangle->position.x = x;\n    rectangle->position.y = y;\n}\n\nvoid c_rectangle_print(const C_Rectangle *rectangle)\n{\n    printf(\n        \"{ x: %f, y: %f, w: %f, h: %f }\\n\",\n        rectangle->position.x,\n        rectangle->position.y,\n        rectangle->width,\n        rectangle->height);\n}\n"
  },
  {
    "path": "Game I/c_rectangle.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n#include \"c_vector2.h\"\n\n/**\n * A Rectangle represents an axis aligned box defined by the coordinates of its upper left corner as well as width and\n * height.\n */\n\n/**\n * Struct for rectangle data. Deliberately public.\n */\ntypedef struct C_Rectangle\n{\n    C_Vector2 position;\n    float width;\n    float height;\n} C_Rectangle;\n\n/**\n * Create a new Rectangle.\n *\n * @param position\n *   Position of rectangle (upper left corner).\n *\n * @param width\n *   Width of rectangle.\n *\n * @param height\n *   Height of rectangle.\n *\n * @returns\n *   Rectangle constructed with supplied values.\n */\nC_Rectangle c_rectangle_create(const C_Vector2 *position, float width, float height);\n\n/**\n * Create a new Rectangle.\n *\n * @param x\n *   X coordinate of position (upper left corner).\n *\n * @param y\n *   Y coordinate of position (upper left corner).\n *\n * @param width\n *   Width of rectangle.\n *\n * @param height\n *   Height of rectangle.\n *\n * @returns\n *   Rectangle constructed with supplied values.\n */\nC_Rectangle c_rectangle_create_xy(float x, float y, float width, float height);\n\n/**\n * Translate the position of a rectangle.\n *\n * @param rectangle\n *   Rectangle to translate.\n *\n * @param translation\n *   Translation amount.\n */\nvoid c_rectangle_translate(C_Rectangle *rectangle, const C_Vector2 *translation);\n\n/**\n * Translate the position of a rectangle.\n *\n * @param rectangle\n *   Rectangle to translate.\n *\n * @param x\n *   Amount to move along x axis.\n *\n * @param y\n *   Amount to move along y axis.\n */\nvoid c_rectangle_translate_xy(C_Rectangle *rectangle, float x, float y);\n\n/**\n * Set the position of a rectangle.\n *\n * @param rectangle\n *   Rectangle to set position of.\n *\n * @param position\n *   New rectangle position.\n */\nvoid c_rectangle_set_position(C_Rectangle *rectangle, const C_Vector2 *position);\n\n/**\n * Set the position of a rectangle.\n *\n * @param rectangle\n *   Rectangle to set position of.\n *\n * @param x\n *   X coordinate of new position.\n *\n * @param y\n *   Y coordinate of new position.\n */\nvoid c_rectangle_set_position_xy(C_Rectangle *rectangle, float x, float y);\n\n/**\n * Print rectangle to stdout.\n *\n * @param rectangle\n *   Rectangle to print.\n */\nvoid c_rectangle_print(const C_Rectangle *rectangle);\n"
  },
  {
    "path": "Game I/c_result.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n/**\n * Enumeration of all possible return codes.\n */\ntypedef enum C_Result\n{\n    C_SUCCESS,\n\n    C_NO_MORE_EVENTS,\n\n    C_SDL_INIT_FAILED,\n\n    C_FAILED_TO_ALLOCATE_WINDOW,\n    C_FAILED_TO_CREATE_WINDOW,\n    C_FAILED_TO_GET_SURFACE,\n    C_FAILED_TO_FILL_RECT,\n    C_FAILED_TO_UPDATE_SURFACE,\n    C_FAILED_TO_CREATE_RENDERER,\n\n    C_FAILED_TO_MAP_KEY,\n\n    C_FAILED_TO_CLEAR_RENDERER,\n    C_FAILED_TO_SET_RENDER_COLOUR,\n    C_FAILED_TO_DRAW_FILLED_RECT,\n\n    C_FAILED_TO_ALLOCATE_LIST,\n    C_FAILED_TO_ALLOCATE_NODE,\n    C_FAILED_TO_ALLOCATE_ITERATOR,\n} C_Result;\n"
  },
  {
    "path": "Game I/c_vector2.c",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#include \"c_vector2.h\"\n\n#include <assert.h>\n#include <stdio.h>\n\nC_Vector2 c_vector2_create()\n{\n    return c_vector2_create_xy(0.0f, 0.0f);\n}\n\nC_Vector2 c_vector2_create_xy(float x, float y)\n{\n    C_Vector2 vec = {.x = x, .y = y};\n    return vec;\n}\n\nvoid c_vector2_add(C_Vector2 *vec1, const C_Vector2 *vec2)\n{\n    assert(vec1 != NULL);\n    assert(vec2 != NULL);\n\n    vec1->x += vec2->x;\n    vec1->y += vec2->y;\n}\n\nvoid c_vector2_add_xy(C_Vector2 *vec, float x, float y)\n{\n    assert(vec != NULL);\n\n    vec->x += x;\n    vec->y += y;\n}\n\nvoid c_vector2_print(const C_Vector2 *vec)\n{\n    assert(vec != NULL);\n\n    printf(\"{ x: %f, y: %f }\\n\", vec->x, vec->y);\n}\n"
  },
  {
    "path": "Game I/c_vector2.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n/**\n * A Vector2 represents a two component (x and y) vector.\n */\n\n/**\n * Struct for vector data. Deliberately public.\n */\ntypedef struct C_Vector2\n{\n    float x;\n    float y;\n} C_Vector2;\n\n/**\n * Create a new Vector2 with both components 0.0.\n *\n * @returns\n *   Vector2 with x and y set to 0.0.\n */\nC_Vector2 c_vector2_create();\n\n/**\n * Create a new Vector2 with supplied component values.\n *\n * @param x\n *   X component.\n *\n * @param y\n *   Y component.\n *\n * @returns\n *   Vector2 with x and y set to supplied values.\n */\nC_Vector2 c_vector2_create_xy(float x, float y);\n\n/**\n * Add one vector to another.\n *\n * @param vec1\n *   The source vector, this will be modified.\n *\n * @param vec2\n *   The vector to add to vec1.\n */\nvoid c_vector2_add(C_Vector2 *vec1, const C_Vector2 *vec2);\n\n/**\n * Add values to a vector.\n *\n * @param vec\n *   The source vector, this will be modified.\n *\n * @param x\n *   Value to add to x component.\n *\n * @param y\n *   Value to add to y component.\n */\nvoid c_vector2_add_xy(C_Vector2 *vec, float x, float y);\n\n/**\n * Print vector to stdout.\n *\n * @param vec\n *   The vector to print.\n */\nvoid c_vector2_print(const C_Vector2 *vec);\n"
  },
  {
    "path": "Game I/c_window.c",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#include \"c_window.h\"\n\n#include <assert.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdlib.h>\n\n#include \"SDL.h\"\n\n#include \"c_key_event.h\"\n#include \"c_result.h\"\n\ntypedef struct C_Window\n{\n    SDL_Window *window;\n    SDL_Renderer *renderer;\n} C_Window;\n\nstatic C_Result map_sdl_key(C_Key *key, SDL_Keycode sdl_code)\n{\n    switch (sdl_code)\n    {\n        case SDLK_ESCAPE: *key = C_KEY_ESCAPE; return C_SUCCESS;\n        case SDLK_LEFT: *key = C_KEY_LEFT; return C_SUCCESS;\n        case SDLK_RIGHT: *key = C_KEY_RIGHT; return C_SUCCESS;\n        default: return C_NO_MORE_EVENTS;\n    }\n}\n\nC_Result c_window_create(C_Window **window)\n{\n    C_Result res = C_SUCCESS;\n\n    // perform the initial SDL initialisation\n    if (SDL_Init(SDL_INIT_VIDEO) != 0)\n    {\n        res = C_SDL_INIT_FAILED;\n        goto fail;\n    }\n\n    // allocate space for the window object\n    C_Window *new_window = (C_Window *)calloc(1u, sizeof(C_Window));\n    if (new_window == NULL)\n    {\n        res = C_FAILED_TO_ALLOCATE_WINDOW;\n        goto fail;\n    }\n\n    // create an SDL window\n    new_window->window =\n        SDL_CreateWindow(\"c_game\", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 800, SDL_WINDOW_SHOWN);\n    if (new_window->window == NULL)\n    {\n        res = C_FAILED_TO_CREATE_WINDOW;\n        goto fail;\n    }\n\n    // create an SDL renderer\n    new_window->renderer = SDL_CreateRenderer(new_window->window, -1, 0);\n    if (new_window->renderer == NULL)\n    {\n        res = C_FAILED_TO_CREATE_RENDERER;\n        goto fail;\n    }\n\n    // assign the window to the user supplied pointer\n    *window = new_window;\n    return res;\n\nfail:\n    // clean up and return error code\n    c_window_destroy(new_window);\n    return res;\n}\n\nvoid c_window_destroy(C_Window *window)\n{\n    if (window == NULL)\n    {\n        return;\n    }\n\n    if (window->window != NULL)\n    {\n        SDL_DestroyWindow(window->window);\n    }\n\n    free(window);\n\n    SDL_Quit();\n}\n\nC_Result c_window_get_event(const C_Window *window, C_KeyEvent *event)\n{\n    assert(window != NULL);\n    assert(event != NULL);\n\n    C_Result result = C_NO_MORE_EVENTS;\n\n    // try and get an SDL event\n    SDL_Event sdl_event;\n    if (SDL_PollEvent(&sdl_event) != 0u)\n    {\n        bool try_map_key = false;\n\n        if (sdl_event.type == SDL_KEYDOWN)\n        {\n            event->key_state = C_KEYSTATE_DOWN;\n            try_map_key = true;\n        }\n        else if (sdl_event.type == SDL_KEYUP)\n        {\n            event->key_state = C_KEYSTATE_UP;\n            try_map_key = true;\n        }\n\n        if (try_map_key)\n        {\n            // if we get here then we know we had a key event (either press or release), so convert the SDL key code\n            // to our internal representation\n            result = map_sdl_key(&event->key, sdl_event.key.keysym.sym);\n        }\n    }\n\n    return result;\n}\n\nC_Result c_window_pre_render(const C_Window *window)\n{\n    C_Result result = C_SUCCESS;\n\n    // clear the window to black\n\n    if (SDL_SetRenderDrawColor(window->renderer, 0x0, 0x0, 0x0, 0x0) != 0)\n    {\n        result = C_FAILED_TO_SET_RENDER_COLOUR;\n        goto end;\n    }\n\n    if (SDL_RenderClear(window->renderer) != 0)\n    {\n        result = C_FAILED_TO_CLEAR_RENDERER;\n        goto end;\n    }\n\nend:\n    return result;\n}\n\nvoid c_window_post_render(const C_Window *window)\n{\n    return SDL_RenderPresent(window->renderer);\n}\n\nC_Result c_window_draw_rectangle(const C_Window *window, const C_Rectangle *rectangle, uint8_t r, uint8_t g, uint8_t b)\n{\n    C_Result result = C_SUCCESS;\n\n    // convert our internal rect to an SDL rect\n    SDL_Rect sdl_rect = {\n        .x = rectangle->position.x, .y = rectangle->position.y, .w = rectangle->width, .h = rectangle->height};\n\n    // set the draw colour\n    if (SDL_SetRenderDrawColor(window->renderer, r, g, b, 0xff) != 0)\n    {\n        result = C_FAILED_TO_SET_RENDER_COLOUR;\n        goto end;\n    }\n\n    // draw!\n    if (SDL_RenderFillRect(window->renderer, &sdl_rect) != 0)\n    {\n        result = C_FAILED_TO_DRAW_FILLED_RECT;\n        goto end;\n    }\n\nend:\n    return result;\n}\n"
  },
  {
    "path": "Game I/c_window.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n#include <stdint.h>\n\n#include \"c_key_event.h\"\n#include \"c_rectangle.h\"\n#include \"c_result.h\"\n\n/**\n * Window is responsible fro creating and destroying a platform window as well as rendering to it and getting event.\n */\n\n/**\n * Handle to internal window data.\n */\ntypedef struct C_Window C_Window;\n\n/**\n * Create a new platform window.\n *\n * Note this library only supports creating one window, any calls to this function after the first successful call are\n * undefined.\n *\n * @param window\n *   Out paramater for created window object.\n *\n * @returns\n *   C_SUCCESS on success\n *   Another Result type on error\n */\nC_Result c_window_create(C_Window **window);\n\n/**\n * Destroy a window.\n *\n * @param window\n *   The window to destroy.\n */\nvoid c_window_destroy(C_Window *window);\n\n/**\n * Get an event if one is available.\n *\n * @param window\n *   Window to get events for.\n *\n * @param event\n *   Out paramater to write event data to.\n *\n * @returns\n *   C_SUCCESS on success\n *   C_NO_MORE_EVENTS if there was no event to get\n *   Another Result type on error\n */\nC_Result c_window_get_event(const C_Window *window, C_KeyEvent *event);\n\n/**\n * Perform an pre-render tasks.\n *\n * @param window\n *   Window to render to.\n *\n * @returns\n *   C_SUCCESS on success\n *   Another Result type on error\n */\nC_Result c_window_pre_render(const C_Window *window);\n\n/**\n * Perform an post-render tasks.\n *\n * @param window\n *   Window to render to.\n */\nvoid c_window_post_render(const C_Window *window);\n\n/**\n * Draw a rectangle to the screen.\n *\n * This *must* be called after c_window_pre_render and before c_window_post_render for any given frame.\n *\n * @param window\n *   The window to render to.\n *\n * @param rectangle\n *   The rectangle to draw.\n *\n * @param r\n *   The red component of the rectangle colour.\n *\n * @param g\n *   The green component of the rectangle colour.\n *\n * @param b\n *   The blue component of the rectangle colour.\n *\n * @returns\n *   C_SUCCESS on success\n *   Another Result type on error\n */\nC_Result c_window_draw_rectangle(const C_Window *window, const C_Rectangle *rectangle, uint8_t r, uint8_t g, uint8_t b);\n"
  },
  {
    "path": "Game I/main.c",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#include <assert.h>\n#include <stdbool.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n\n#include \"c_key_event.h\"\n#include \"c_list.h\"\n#include \"c_rectangle.h\"\n#include \"c_window.h\"\n\n/**\n * Struct encapsulating the data for a renderable entity.\n */\ntypedef struct Entity\n{\n    C_Rectangle rectangle;\n    uint8_t r;\n    uint8_t g;\n    uint8_t b;\n} Entity;\n\n/**\n * Helper macro for checking if a value is C_SUCCESS. If not it prints a supplied messaged and exits.\n */\n#define CHECK_SUCCESS(X, MSG)                                                                                          \\\n    do                                                                                                                 \\\n    {                                                                                                                  \\\n        C_Result r = X;                                                                                                \\\n        if (r != C_SUCCESS)                                                                                            \\\n        {                                                                                                              \\\n            printf(\"%s [error: %i]\\n\", MSG, r);                                                                        \\\n            exit(1);                                                                                                   \\\n        }                                                                                                              \\\n    } while (false)\n\n/**\n * Helper function to create a row of ten bricks.\n *\n * @param entities\n *   List to store entities in.\n *\n * @param y\n *   Y coordinate of row.\n *\n * @param r\n *   Red component of brick colour.\n *\n * @param g\n *   Green component of brick colour.\n *\n * @param b\n *  Blue component of brick colour.\n */\nstatic void create_brick_row(C_List *entities, float y, uint8_t r, uint8_t g, uint8_t b)\n{\n    float x = 20.0f;\n\n    for (int i = 0; i < 10; ++i)\n    {\n        Entity *e = (Entity *)calloc(sizeof(Entity), 1u);\n        e->rectangle.position.x = x;\n        e->rectangle.position.y = y;\n        e->rectangle.width = 58.0f;\n        e->rectangle.height = 20.0f;\n        e->r = r;\n        e->g = g;\n        e->b = b;\n\n        CHECK_SUCCESS(c_list_push_back_dtor(entities, e, &free), \"failed to add brick\");\n\n        x += 78.0f;\n    }\n}\n\n/**\n * Helper function to update the ball.\n *\n * @param ball\n *   Entity for ball.\n *\n * @param ball_velocity\n *   Velocity of ball.\n */\nstatic void update_ball(Entity *ball, C_Vector2 *ball_velocity)\n{\n    c_vector2_add(&ball->rectangle.position, ball_velocity);\n\n    // if ball does out of the screen then invert the y velocity\n    if ((ball->rectangle.position.y < 0.0f) || (ball->rectangle.position.y > 800.0f))\n    {\n        ball_velocity->y *= -1.0f;\n    }\n\n    if ((ball->rectangle.position.x < 0.0f) || (ball->rectangle.position.x > 800.0f))\n    {\n        ball_velocity->x *= -1.0f;\n    }\n}\n\n/**\n * Helper function to check if two entities are colliding.\n *\n * @param entity1\n *   First entity to check.\n *\n * @param entity2\n *   Second entity to check.\n *\n * @returns\n *   True if entities collide, false otherwise.\n */\nbool static check_collision(const Entity *entity1, const Entity *entity2)\n{\n    return (\n        (entity1->rectangle.position.x < entity2->rectangle.position.x + entity2->rectangle.width) &&\n        (entity1->rectangle.position.x + entity1->rectangle.width > entity2->rectangle.position.x) &&\n        (entity1->rectangle.position.y < entity2->rectangle.position.y + entity2->rectangle.height) &&\n        (entity1->rectangle.height + entity1->rectangle.position.y > entity2->rectangle.position.y));\n}\n\n/**\n * Helper function to handle collisions between the ball and other entities.\n *\n * @param entities\n *   List of all entities.\n *\n * @param ball\n *   Ball entity.\n *\n * @param ball_velocity\n *   The velocity of the ball.\n *\n * @param paddle\n *   Paddle entity.\n */\nstatic void handle_collisions(C_List *entities, Entity *ball, C_Vector2 *ball_velocity, const Entity *paddle)\n{\n    // keep iterator scoped so we can't use it after it's been destroyed\n    {\n        C_ListIter *iter;\n        CHECK_SUCCESS(c_list_iterator_create(entities, &iter), \"could not create iterator\");\n\n        // move past ball and paddle\n        c_list_iterator_advance(&iter);\n        c_list_iterator_advance(&iter);\n\n        // see if the ball intersects with any bricks\n        while (!c_list_iterator_at_end(iter))\n        {\n            Entity *block = (Entity *)c_list_iterator_value(iter);\n\n            if (check_collision(ball, block))\n            {\n                c_list_remove(entities, iter);\n                ball_velocity->y *= -1.0f;\n\n                // if we modify the list this will invalidate the iterator, so stop\n                break;\n            }\n\n            c_list_iterator_advance(&iter);\n        }\n\n        c_list_iterator_destroy(iter);\n    }\n\n    // handle ball - paddle collision\n    if (check_collision(ball, paddle))\n    {\n        if (ball->rectangle.position.x < paddle->rectangle.position.x + 6.0f)\n        {\n            ball_velocity->x = -0.7f;\n            ball_velocity->y = -0.7f;\n        }\n        else if (ball->rectangle.position.x < paddle->rectangle.position.x + 14.0f)\n        {\n            ball_velocity->x = 0.0f;\n            ball_velocity->y = -1.0f;\n        }\n        else\n        {\n            ball_velocity->x = 0.7f;\n            ball_velocity->y = -0.7f;\n        }\n    }\n}\n\nint main()\n{\n    printf(\"hello world\\n\");\n\n    Entity paddle = {\n        .rectangle = c_rectangle_create_xy(300.0f, 780.0f, 300.0f, 20.0f), .r = 0xff, .g = 0xff, .b = 0xff};\n    Entity ball = {.rectangle = c_rectangle_create_xy(420.0f, 400.0f, 10.0f, 10.0f), .r = 0xff, .g = 0xff, .b = 0xff};\n\n    C_Vector2 paddle_velocity = c_vector2_create();\n    C_Vector2 ball_velocity = c_vector2_create_xy(0.0f, 0.5f);\n\n    C_List *entities = NULL;\n    CHECK_SUCCESS(c_list_create(&entities), \"failed to create entity list\");\n\n    CHECK_SUCCESS(c_list_push_back(entities, &paddle), \"failed to add paddle to list\");\n    CHECK_SUCCESS(c_list_push_back(entities, &ball), \"failed to add ball to list\");\n\n    create_brick_row(entities, 50.0f, 0xff, 0x00, 0x00);\n    create_brick_row(entities, 80.0f, 0xff, 0x00, 0x00);\n    create_brick_row(entities, 110.0f, 0xff, 0xa5, 0x00);\n    create_brick_row(entities, 140.0f, 0xff, 0xa5, 0x00);\n    create_brick_row(entities, 170.0f, 0x00, 0xff, 0x00);\n    create_brick_row(entities, 200.0f, 0x00, 0xff, 0x00);\n\n    C_ListIter *iter = NULL;\n    CHECK_SUCCESS(c_list_iterator_create(entities, &iter), \"failed to get entity iterator\");\n\n    // create window\n    C_Window *window;\n    CHECK_SUCCESS(c_window_create(&window), \"failed to create window\");\n\n    C_KeyEvent event;\n    bool running = true;\n\n    const float paddle_speed = 1.0f;\n    bool left_press = false;\n    bool right_press = false;\n\n    while (running)\n    {\n        // process all events\n        for (;;)\n        {\n            C_Result event_result = c_window_get_event(window, &event);\n            if (event_result == C_SUCCESS)\n            {\n                if ((event.key_state == C_KEYSTATE_DOWN) && (event.key == C_KEY_ESCAPE))\n                {\n                    running = false;\n                }\n                else if (event.key == C_KEY_LEFT)\n                {\n                    left_press = (event.key_state == C_KEYSTATE_DOWN) ? true : false;\n                }\n                else if (event.key == C_KEY_RIGHT)\n                {\n                    right_press = (event.key_state == C_KEYSTATE_DOWN) ? true : false;\n                }\n            }\n            else if (event_result == C_NO_MORE_EVENTS)\n            {\n                break;\n            }\n            else\n            {\n                printf(\"error getting event\\n\");\n                exit(1);\n            }\n        }\n\n        if ((left_press && right_press) || (!left_press && !right_press))\n        {\n            paddle_velocity.x = 0.0f;\n        }\n        else if (left_press)\n        {\n            paddle_velocity.x = -paddle_speed;\n        }\n        else if (right_press)\n        {\n            paddle_velocity.x = paddle_speed;\n        }\n\n        c_vector2_add(&paddle.rectangle.position, &paddle_velocity);\n        update_ball(&ball, &ball_velocity);\n        handle_collisions(entities, &ball, &ball_velocity, &paddle);\n\n        // reset iterator as we may have modified the list and we will want to start from the beginning anyway\n        c_list_iterator_reset(entities, &iter);\n\n        // render our scene\n\n        CHECK_SUCCESS(c_window_pre_render(window), \"pre render failed\");\n\n        while (!c_list_iterator_at_end(iter))\n        {\n            Entity *entity = (Entity *)c_list_iterator_value(iter);\n            CHECK_SUCCESS(\n                c_window_draw_rectangle(window, &entity->rectangle, entity->r, entity->g, entity->b),\n                \"failed to render entity\");\n\n            c_list_iterator_advance(&iter);\n        }\n\n        c_window_post_render(window);\n    }\n\n    c_list_iterator_destroy(iter);\n    c_window_destroy(window);\n\n    printf(\"goodbye\\n\");\n\n    return 0;\n}\n"
  },
  {
    "path": "Game II/CMakeLists.txt",
    "content": "add_executable(cpp_game\n    colour.cpp\n    entity.cpp\n    main.cpp\n    rectangle.cpp\n    vector2.cpp\n    window.cpp\n)\n\ntarget_link_directories(cpp_game PRIVATE ${sdl_BINARY_DIR})\ntarget_include_directories(cpp_game PRIVATE ${sdl_SOURCE_DIR}/include)\ntarget_compile_features(cpp_game PRIVATE cxx_std_20)\n\ntarget_link_libraries(cpp_game SDL2::SDL2-static)\n"
  },
  {
    "path": "Game II/colour.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#include \"colour.h\"\n\n#include <cstdint>\n#include <iostream>\n\nnamespace cpp\n{\n\nColour::Colour()\n    : Colour(0xffffff)\n{\n}\n\nColour::Colour(std::uint8_t r, std::uint8_t g, std::uint8_t b)\n    : r(r)\n    , g(g)\n    , b(b)\n{\n}\n\nColour::Colour(std::uint32_t colour)\n    : Colour((colour >> 16) & 0xff, (colour >> 7) & 0xff, colour & 0xff)\n{\n}\n\nbool operator==(const Colour &c1, const Colour &c2)\n{\n    return (c1.r == c2.r) && (c1.g == c2.g) && (c1.b == c2.b);\n}\n\nbool operator!=(const Colour &c1, const Colour &c2)\n{\n    return !(c1 == c2);\n}\n\nstd::ostream &operator<<(std::ostream &os, const Colour &c)\n{\n    os << \"{ r: \" << c.r << \", g: \" << c.g << \", b: \" << c.b << \" }\";\n    return os;\n}\n\n}\n"
  },
  {
    "path": "Game II/colour.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n#include <cstdint>\n#include <iosfwd>\n\nnamespace cpp\n{\n\n/**\n * A Colour represents an RGB component (where each component is 8 bits).\n */\nclass Colour\n{\n  public:\n    /**\n     * Construct a new white colour.\n     */\n    Colour();\n\n    /**\n     * Construct a new colour from r, g and b components.\n     *\n     * @param r\n     *   Red component.\n     *\n     * @param g\n     *   Green component.\n     *\n     * @param b\n     *   Blue component.\n     */\n    Colour(std::uint8_t r, std::uint8_t g, std::uint8_t b);\n\n    /**\n     * Construct a new colour from a hex colour number. The expected format of the number is 0xRRGGBB.\n     *\n     * @param colour\n     *   Colour value (0xRRGGBB).\n     */\n    Colour(std::uint32_t colour);\n\n    /**\n     * Stream operator.\n     *\n     * @param os\n     *   Stream to write to.\n     *\n     * @param c\n     *   Colour to write to stream.\n     *\n     * @returns\n     *   Reference to supplied stream.\n     */\n    friend std::ostream &operator<<(std::ostream &os, const Colour &c);\n\n    /** Red component. */\n    std::uint8_t r;\n\n    /** Green component. */\n    std::uint8_t g;\n\n    /** Blue component. */\n    std::uint8_t b;\n};\n\n/**\n * Check if two colours are equal.\n *\n * @param c1\n *   First colour to check.\n *\n * @param c2\n *   Second colour to check.\n *\n * @returns\n *   True if both colours are equal, otherwise false.\n */\nbool operator==(const Colour &c1, const Colour &c2);\n\n/**\n * Check if two colours are not equal.\n *\n * @param c1\n *   First colour to check.\n *\n * @param c2\n *   Second colour to check.\n *\n * @returns\n *   True if both colours are not equal, otherwise false.\n */\nbool operator!=(const Colour &c1, const Colour &c2);\n\n// see docs on class definition\nstd::ostream &operator<<(std::ostream &os, const Colour &c);\n\n}\n"
  },
  {
    "path": "Game II/entity.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#include \"entity.h\"\n\n#include <iostream>\n\n#include \"colour.h\"\n#include \"rectangle.h\"\n#include \"vector2.h\"\n\nnamespace cpp\n{\n\nEntity::Entity(const Rectangle &rectangle, const Colour &colour)\n    : rectangle_(rectangle)\n    , colour_(colour)\n{\n}\n\nRectangle Entity::rectangle() const\n{\n    return rectangle_;\n}\n\nColour Entity::colour() const\n{\n    return colour_;\n}\n\nvoid Entity::translate(const Vector2 &translation)\n{\n    rectangle_.translate(translation);\n}\n\nbool Entity::intersects(const Entity &e) const\n{\n    return rectangle_.intersects(e.rectangle_);\n}\n\nbool operator==(const Entity &e1, const Entity &e2)\n{\n    return (e1.colour() == e2.colour()) && (e1.rectangle() == e2.rectangle());\n}\n\nbool operator!=(const Entity &e1, const Entity &e2)\n{\n    return !(e1 == e2);\n}\n\nstd::ostream &operator<<(std::ostream &os, const Entity &e)\n{\n    os << \"{ \" << e.colour() << \", \" << e.rectangle() << \" }\";\n    return os;\n}\n\n}\n"
  },
  {
    "path": "Game II/entity.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n#include \"colour.h\"\n#include \"rectangle.h\"\n#include \"vector2.h\"\n\nnamespace cpp\n{\n\n/**\n * An Entity represents a renderable rectangle.\n */\nclass Entity\n{\n  public:\n    /**\n     * Construct a new entity.\n     *\n     * @param rectangle\n     *   Rectangle representing the area to draw.\n     *\n     * @param colour\n     *   The colour to render the entity.\n     */\n    Entity(const Rectangle &rectangle, const Colour &colour);\n\n    /**\n     * Get the entities rectangle.\n     *\n     * @returns\n     *   Entity rectangle.\n     */\n    Rectangle rectangle() const;\n\n    /**\n     * Get the entities colour.\n     *\n     * @returns\n     *   Entity colour.\n     */\n    Colour colour() const;\n\n    /**\n     * Translate the entity.\n     *\n     * @param translation\n     *   Translation amount.\n     */\n    void translate(const Vector2 &translation);\n\n    /**\n     * Check if another entity intersects this.\n     *\n     * @param e\n     *   Entity to check for intersection.\n     *\n     * @returns\n     *   True if supplied entity intersects this, otherwise false.\n     */\n    bool intersects(const Entity &e) const;\n\n    /**\n     * Stream operator.\n     *\n     * @param os\n     *   Stream to write to.\n     *\n     * @param e\n     *   Entity to write to stream.\n     *\n     * @returns\n     *   Reference to supplied stream.\n     */\n    friend std::ostream &operator<<(std::ostream &os, const Entity &e);\n\n  private:\n    /** Drawable area. */\n    Rectangle rectangle_;\n\n    /** Draw colour. */\n    Colour colour_;\n};\n\n/**\n * Check if two entities are equal.\n *\n * @param e1\n *   First entity to check.\n *\n * @param e2\n *   Second entity to check.\n *\n * @returns\n *   True if both entities are equal, otherwise false.\n */\nbool operator==(const Entity &e1, const Entity &e2);\n\n/**\n * Check if two entities are equal.\n *\n * @param e1\n *   First entity to check.\n *\n * @param e2\n *   Second entity to check.\n *\n * @returns\n *   True if both entities are equal, otherwise false.\n */\nbool operator!=(const Entity &e1, const Entity &e2);\n\n// see docs on class definition\nstd::ostream &operator<<(std::ostream &os, const Entity &e);\n\n}\n"
  },
  {
    "path": "Game II/key_event.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\nnamespace cpp\n{\n\n/**\n * Enumeration of possible key states.\n */\nenum class KeyState\n{\n    DOWN,\n    UP\n};\n\n/**\n * Enumeration of possible input keys (maybe incomplete).\n */\nenum class Key\n{\n    ESCAPE,\n    LEFT,\n    RIGHT,\n};\n\n/**\n * Struct encapsulating the data for a key press event.\n */\nstruct KeyEvent\n{\n    KeyState key_state;\n    Key key;\n};\n\n}\n"
  },
  {
    "path": "Game II/main.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#include <iostream>\n#include <ranges>\n\n#include \"colour.h\"\n#include \"entity.h\"\n#include \"key_event.h\"\n#include \"rectangle.h\"\n#include \"vector2.h\"\n#include \"window.h\"\n\nnamespace\n{\n\n/**\n * Helper function to create a row of 10 bricks.\n *\n * @param entities\n *   Collection to add new entities to.\n *\n * @param y\n *   Y coordinate of row.\n *\n * @param colour\n *   Colour of bricks.\n */\nvoid create_brick_row(std::vector<cpp::Entity> &entities, float y, const cpp::Colour &colour)\n{\n    auto x = 20.0f;\n\n    for (auto i = 0u; i < 10u; ++i)\n    {\n        entities.push_back({{{x, y}, 58.0f, 20.0f}, colour});\n        x += 78.0f;\n    }\n}\n\n/**\n * Helper function to check for and resolve collisions between the ball and other entities.\n *\n * @param ball\n *   Ball to check for collisions.\n *\n * @param ball_velocity\n *   Velocity of ball, might get mutated during collision response.\n *\n * @param paddle\n *   Paddle to check for collisions with.\n *\n * @param entities\n *   Collection of all entities, brick entities will be removed if a collision is detected.\n */\nvoid check_collisions(\n    const cpp::Entity &ball,\n    cpp::Vector2 &ball_velocity,\n    const cpp::Entity &paddle,\n    std::vector<cpp::Entity> &entities)\n{\n    // check and handle ball and paddle collision\n    if (paddle.intersects(ball))\n    {\n        const auto ball_pos = ball.rectangle().position;\n        const auto paddle_pos = paddle.rectangle().position;\n\n        if (ball_pos.x < paddle_pos.x + 100.0f)\n        {\n            ball_velocity.x = -0.7f;\n            ball_velocity.y = -0.7f;\n        }\n        else if (ball_pos.x < paddle_pos.x + 200.0f)\n        {\n            ball_velocity.x = 0.0f;\n            ball_velocity.y = -1.0f;\n        }\n        else\n        {\n            ball_velocity.x = 0.7f;\n            ball_velocity.y = -0.7f;\n        }\n    }\n    else\n    {\n        // only check brick intersections if we didn't intersect the paddle, unlikely these will both happen in the same\n        // frame due to the layout of the game\n\n        // iterate over all entities, skipping the first two as these are the paddle and ball\n        auto bricks_view = entities | std::views::drop(2u);\n        auto hit_brick =\n            std::ranges::find_if(bricks_view, [&ball](const auto &brick) { return ball.intersects(brick); });\n\n        if (hit_brick != std::ranges::end(bricks_view))\n        {\n            // we hit a brick so update ball velocity and remove brick entity\n            ball_velocity.y *= -1.0f;\n            entities.erase(hit_brick);\n        }\n    }\n}\n\n/**\n * Helper function to update the ball. Will check if the ball leaves the window and adjust the velocity so it \"bounces\"\n * off walls.\n *\n * @param ball\n *   Ball entity to update.\n *\n * @param velocity\n *   Ball velocity, will be mutated if ball goes off screen.\n */\nvoid update_ball(cpp::Entity &ball, cpp::Vector2 &velocity)\n{\n    ball.translate(velocity);\n\n    const auto ball_pos = ball.rectangle().position;\n\n    if ((ball_pos.y > 800.0f) || (ball_pos.y < 0.0f))\n    {\n        velocity.y *= -1.0f;\n    }\n\n    if ((ball_pos.x > 800.0f) || (ball_pos.x < 0.0f))\n    {\n        velocity.x *= -1.0f;\n    }\n}\n\n/**\n * Helper function to update the paddle.\n *\n * @param paddle\n *   Paddle entity to update.\n *\n * @param velocity\n *   Paddle velocity.\n */\nvoid update_paddle(cpp::Entity &paddle, const cpp::Vector2 &velocity)\n{\n    paddle.translate(velocity);\n}\n\n}\n\nint main()\n{\n    std::cout << \"hello world\\n\";\n\n    const cpp::Window window{};\n    auto running = true;\n\n    std::vector<cpp::Entity> entities{\n        {{{300.0f, 780.0f}, 300.0f, 20.0f}, 0xFFFFFF}, {{{420.0f, 400.0f}, 10.0f, 10.0f}, 0xFFFFFF}};\n\n    create_brick_row(entities, 50.0f, 0xff0000);\n    create_brick_row(entities, 80.0f, 0xff0000);\n    create_brick_row(entities, 110.0f, 0xffa500);\n    create_brick_row(entities, 140.0f, 0xffa500);\n    create_brick_row(entities, 170.0f, 0x00ff00);\n    create_brick_row(entities, 200.0f, 0x00ff00);\n\n    cpp::Vector2 ball_velocity{0.0f, 1.0f};\n    cpp::Vector2 paddle_velocity{0.0f, 0.0f};\n    const float paddle_speed = 1.0f;\n    auto left_press = false;\n    auto right_press = false;\n\n    while (running)\n    {\n        for (;;)\n        {\n            if (const auto event = window.get_event(); event)\n            {\n                using enum cpp::Key;\n                using enum cpp::KeyState;\n\n                if ((event->key_state == DOWN) && (event->key == ESCAPE))\n                {\n                    running = false;\n                }\n                else if (event->key == LEFT)\n                {\n                    left_press = (event->key_state == DOWN) ? true : false;\n                }\n                else if (event->key == RIGHT)\n                {\n                    right_press = (event->key_state == DOWN) ? true : false;\n                }\n            }\n            else\n            {\n                break;\n            }\n        }\n\n        if ((left_press && right_press) || (!left_press && !right_press))\n        {\n            paddle_velocity.x = 0.0f;\n        }\n        else if (left_press)\n        {\n            paddle_velocity.x = -paddle_speed;\n        }\n        else if (right_press)\n        {\n            paddle_velocity.x = paddle_speed;\n        }\n\n        // scope the references to the paddle and ball, if check_collisions results in an entity being removed then\n        // that will invalidate our references, so prevent them from being accidentally used later\n        {\n            auto &paddle = entities[0];\n            auto &ball = entities[1];\n\n            update_paddle(paddle, paddle_velocity);\n            update_ball(ball, ball_velocity);\n            check_collisions(ball, ball_velocity, paddle, entities);\n        }\n\n        window.render(entities);\n    }\n\n    std::cout << \"goodbye\\n\";\n\n    return 0;\n}\n"
  },
  {
    "path": "Game II/rectangle.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#include \"rectangle.h\"\n\n#include <iostream>\n\n#include \"vector2.h\"\n\nnamespace cpp\n{\n\nRectangle::Rectangle(const Vector2 &position, float width, float height)\n    : position(position)\n    , width(width)\n    , height(height)\n{\n}\n\nvoid Rectangle::translate(const Vector2 &translation)\n{\n    position += translation;\n}\n\nbool Rectangle::intersects(const Rectangle &rect) const\n{\n    return (\n        (position.x < rect.position.x + rect.width) && (position.x + width > rect.position.x) &&\n        (position.y < rect.position.y + rect.height) && (height + position.y > rect.position.y));\n}\n\nbool operator==(const Rectangle &r1, const Rectangle &r2)\n{\n    return (r1.position == r2.position) && (r1.width == r2.width) && (r1.height == r2.height);\n}\n\nbool operator!=(const Rectangle &r1, const Rectangle &r2)\n{\n    return !(r1 == r2);\n}\n\nstd::ostream &operator<<(std::ostream &os, const Rectangle &rect)\n{\n    os << \"{ position: \" << rect.position << \", w: \" << rect.width << \", h: \" << rect.height << \" }\";\n    return os;\n}\n\n}\n"
  },
  {
    "path": "Game II/rectangle.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n#include <iosfwd>\n\n#include \"vector2.h\"\n\nnamespace cpp\n{\n\n/**\n * A Rectangle represents an axis aligned box defined by the coordinates of its upper left corner as well as width and\n * height.\n */\nclass Rectangle\n{\n  public:\n    /**\n     * Construct a new Rectangle.\n     *\n     * @param position\n     *   Position of rectangle (upper left corner).\n     *\n     * @param width\n     *   Width of rectangle.\n     *\n     * @param height\n     *   Height of rectangle.\n     */\n    Rectangle(const Vector2 &position, float width, float height);\n\n    /**\n     * Stream operator.\n     *\n     * @param os\n     *   Stream to write to.\n     *\n     * @param rect\n     *   Rectangle to write to stream.\n     *\n     * @returns\n     *   Reference to supplied stream.\n     */\n    friend std::ostream &operator<<(std::ostream &os, const Rectangle &rect);\n\n    /**\n     * Translate the position of a rectangle.\n     *\n     * @param translation\n     *   Translation amount.\n     */\n    void translate(const Vector2 &translation);\n\n    /**\n     * Check if another rectangle intersects this.\n     *\n     * @param rect\n     *   Rectangle to check for intersection.\n     *\n     * @returns\n     *   True if supplied rectangle intersects this, otherwise false.\n     */\n    bool intersects(const Rectangle &rect) const;\n\n    /** Position of upper left corner of rectangle. */\n    Vector2 position;\n\n    /** Rectangle width. */\n    float width;\n\n    /** Rectangle height. */\n    float height;\n};\n\n/**\n * Check if two rectangles are equal.\n *\n * @param r1\n *   First rectangle to check.\n *\n * @param r2\n *   Second rectangle to check.\n *\n * @returns\n *   True if both rectangles are equal, otherwise false.\n */\nbool operator==(const Rectangle &r1, const Rectangle &r2);\n\n/**\n * Check if two rectangles are not equal.\n *\n * @param r1\n *   First rectangle to check.\n *\n * @param r2\n *   Second rectangle to check.\n *\n * @returns\n *   True if both rectangles are not equal, otherwise false.\n */\nbool operator!=(const Rectangle &r1, const Rectangle &r2);\n\n// see docs on class definition\nstd::ostream &operator<<(std::ostream &os, const Rectangle &rect);\n\n}\n"
  },
  {
    "path": "Game II/vector2.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#include \"vector2.h\"\n\n#include <iostream>\n\nnamespace cpp\n{\n\nVector2::Vector2()\n    : Vector2(0.0f, 0.0f)\n{\n}\n\nVector2::Vector2(float x, float y)\n    : x(x)\n    , y(y)\n{\n}\n\nbool operator==(const Vector2 &v1, const Vector2 &v2)\n{\n    return (v1.x == v2.x) && (v1.y == v2.y);\n}\n\nbool operator!=(const Vector2 &v1, const Vector2 &v2)\n{\n    return !(v1 == v2);\n}\n\nVector2 operator+(const Vector2 &v1, const Vector2 &v2)\n{\n    Vector2 new_vec{v1};\n    new_vec += v2;\n    return new_vec;\n}\n\nVector2 &operator+=(Vector2 &v1, const Vector2 &v2)\n{\n    v1.x += v2.x;\n    v1.y += v2.y;\n    return v1;\n}\n\nstd::ostream &operator<<(std::ostream &os, const Vector2 &v)\n{\n    os << \"{ x: \" << v.x << \", y: \" << v.y << \"}\";\n    return os;\n}\n\n}\n"
  },
  {
    "path": "Game II/vector2.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n#include <iosfwd>\n\nnamespace cpp\n{\n\n/**\n * A Vector2 represents a two component (x and y) vector.\n */\nclass Vector2\n{\n  public:\n    /**\n     * Construct a new Vector2, with both components 0.0.\n     */\n    Vector2();\n\n    /**\n     * Construct a new Vector2, with supplied component values.\n     *\n     * @param x\n     *   X component.\n     *\n     * @param y\n     *   Y component.\n     */\n    Vector2(float x, float y);\n\n    /**\n     * Stream operator.\n     *\n     * @param os\n     *   Stream to write to.\n     *\n     * @param v\n     *   Vector to write to stream.\n     *\n     * @returns\n     *   Reference to supplied stream.\n     */\n    friend std::ostream &operator<<(std::ostream &os, const Vector2 &v);\n\n    /** X component. */\n    float x;\n\n    /** Y component. */\n    float y;\n};\n\n/**\n * Check if two vectors are equal.\n *\n * @param v1\n *   First vector to check.\n *\n * @param v2\n *   Second vector to check.\n *\n * @returns\n *   True if both vectors are equal, otherwise false.\n */\nbool operator==(const Vector2 &v1, const Vector2 &v2);\n\n/**\n * Check if two vectors are not equal.\n *\n * @param v1\n *   First vector to check.\n *\n * @param v2\n *   Second vector to check.\n *\n * @returns\n *   True if both vectors are not equal, otherwise false.\n */\nbool operator!=(const Vector2 &v1, const Vector2 &v2);\n\n/**\n * Construct a new vector by adding two supplied vectors.\n *\n * @param v1\n *   First vector to add.\n *\n * @param v2\n *   Second vector to add.\n *\n * @returns\n *   v1 + v2.\n */\nVector2 operator+(const Vector2 &v1, const Vector2 &v2);\n\n/**\n * Add assign one vector to another.\n *\n * @param v1\n *   Vector to add to, will be mutated.\n *\n * @param v2\n *   Second vector to add.\n *\n * @returns\n *   v1 += v2.\n */\nVector2 &operator+=(Vector2 &v1, const Vector2 &v2);\n\n// see docs on class definition\nstd::ostream &operator<<(std::ostream &os, const Vector2 &v);\n\n}\n"
  },
  {
    "path": "Game II/window.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#include \"window.h\"\n\n#include <memory>\n#include <optional>\n#include <stdexcept>\n#include <vector>\n\n#include \"SDL.h\"\n\n#include \"entity.h\"\n#include \"key_event.h\"\n\nnamespace\n{\n\n/**\n * Helper function to map an SDL key code to an internal type.\n *\n * @param sql_code\n *   SDL key code.\n *\n * @returns\n *   Internal representation of the supplied key code, or empty optional if no mapping exists.\n */\nstd::optional<cpp::Key> map_sdl_key(SDL_Keycode sdl_code)\n{\n    switch (sdl_code)\n    {\n        using enum cpp::Key;\n\n        case SDLK_ESCAPE: return ESCAPE;\n        case SDLK_LEFT: return LEFT;\n        case SDLK_RIGHT: return RIGHT;\n        default: return std::nullopt;\n    }\n}\n\n}\n\nnamespace cpp\n{\n\nWindow::Window()\n    : window_(nullptr, &SDL_DestroyWindow)\n    , renderer_(nullptr, &SDL_DestroyRenderer)\n{\n    if (::SDL_Init(SDL_INIT_VIDEO) != 0)\n    {\n        throw std::runtime_error(\"failed to init SDL\");\n    }\n\n    window_.reset(\n        ::SDL_CreateWindow(\"cpp_game\", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 800, SDL_WINDOW_SHOWN));\n    if (!window_)\n    {\n        throw std::runtime_error(\"failed to create window\");\n    }\n\n    renderer_.reset(::SDL_CreateRenderer(window_.get(), -1, 0u));\n    if (!renderer_)\n    {\n        throw std::runtime_error(\"failed to create renderer\");\n    }\n}\n\nstd::optional<KeyEvent> Window::get_event() const\n{\n    std::optional<KeyEvent> event{};\n\n    SDL_Event sdl_event = {0};\n    if (::SDL_PollEvent(&sdl_event) != 0u)\n    {\n        std::optional<KeyState> key_state;\n\n        if (sdl_event.type == SDL_KEYDOWN)\n        {\n            key_state = KeyState::DOWN;\n        }\n        else if (sdl_event.type == SDL_KEYUP)\n        {\n            key_state = KeyState::UP;\n        }\n\n        // if we got a key state then it's safe to inspect the key code\n        if (key_state)\n        {\n            if (const auto key = map_sdl_key(sdl_event.key.keysym.sym); key)\n            {\n                // got state and key - so create the KeyEvent\n                event = KeyEvent{.key_state = *key_state, .key = *key};\n            }\n        }\n    }\n\n    return event;\n}\n\nvoid Window::render(const std::vector<Entity> &entities) const\n{\n    if (::SDL_SetRenderDrawColor(renderer_.get(), 0x0, 0x0, 0x0, 0xff) != 0)\n    {\n        throw std::runtime_error(\"failed to set render draw colour\");\n    }\n\n    if (::SDL_RenderClear(renderer_.get()) != 0)\n    {\n        throw std::runtime_error(\"failed to clear renderer\");\n    }\n\n    for (const auto &entity : entities)\n    {\n        const auto entity_rect = entity.rectangle();\n        const auto entity_colour = entity.colour();\n\n        const SDL_Rect sdl_rect = {\n            .x = static_cast<int>(entity_rect.position.x),\n            .y = static_cast<int>(entity_rect.position.y),\n            .w = static_cast<int>(entity_rect.width),\n            .h = static_cast<int>(entity_rect.height),\n        };\n\n        if (::SDL_SetRenderDrawColor(renderer_.get(), entity_colour.r, entity_colour.g, entity_colour.b, 0xff) != 0)\n        {\n            throw std::runtime_error(\"failed to draw entity\");\n        }\n\n        if (::SDL_RenderFillRect(renderer_.get(), &sdl_rect) != 0)\n        {\n            throw std::runtime_error(\"failed to draw filled rect\");\n        }\n    }\n\n    ::SDL_RenderPresent(renderer_.get());\n}\n\n}\n"
  },
  {
    "path": "Game II/window.h",
    "content": "////////////////////////////////////////////////////////////////////////////////\n//         Distributed under the Boost Software License, Version 1.0.         //\n//            (See accompanying file LICENSE or copy at                       //\n//                 https://www.boost.org/LICENSE_1_0.txt)                     //\n////////////////////////////////////////////////////////////////////////////////\n\n#pragma once\n\n#include <memory>\n#include <optional>\n#include <vector>\n\n#include \"entity.h\"\n#include \"key_event.h\"\n\nstruct SDL_Window;\nstruct SDL_Renderer;\n\nusing SDLWindowDelete = void (*)(SDL_Window *);\nusing SDLRendererDelete = void (*)(SDL_Renderer *);\n\nnamespace cpp\n{\n\n/**\n * Window is responsible for creating and destroying a platform window as well as rendering to it and getting events.\n */\nclass Window\n{\n  public:\n    /**\n     * Construct a new Window.\n     */\n    Window();\n\n    Window(const Window &) = delete;\n    Window &operator=(const Window &) = delete;\n\n    Window(Window &&) = default;\n    Window &operator=(Window &&) = default;\n\n    /**\n     * Get an event if one is available.\n     *\n     * @returns\n     *   A KeyEvent if an event was available, otherwise an empty optional.\n     */\n    std::optional<KeyEvent> get_event() const;\n\n    /**\n     * Render a collection of entities.\n     *\n     * @param entities\n     *   Entities to render.\n     */\n    void render(const std::vector<Entity> &entities) const;\n\n  private:\n    /** SDL window object. */\n    std::unique_ptr<SDL_Window, SDLWindowDelete> window_;\n\n    /** SDL renderer object. */\n    std::unique_ptr<SDL_Renderer, SDLRendererDelete> renderer_;\n};\n\n}\n"
  },
  {
    "path": "GeTargs.c",
    "content": "\n/* New getargs implementation */\n\n#include \"Python.h\"\n#include \"pycore_tuple.h\"         // _PyTuple_ITEMS()\n#include \"pycore_pylifecycle.h\"   // _PyArg_Fini\n\n#include <ctype.h>\n#include <float.h>\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Export Stable ABIs (abi only) */\nPyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...);\nPyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, const char *, ...);\nPyAPI_FUNC(int) _PyArg_ParseTupleAndKeywords_SizeT(PyObject *, PyObject *,\n                                                  const char *, char **, ...);\nPyAPI_FUNC(int) _PyArg_VaParse_SizeT(PyObject *, const char *, va_list);\nPyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *,\n                                              const char *, char **, va_list);\n\n#define FLAG_COMPAT 1\n\ntypedef int (*destr_t)(PyObject *, void *);\n\n\n/* Keep track of \"objects\" that have been allocated or initialized and\n   which will need to be deallocated or cleaned up somehow if overall\n   parsing fails.\n*/\ntypedef struct {\n  void *item;\n  destr_t destructor;\n} freelistentry_t;\n\ntypedef struct {\n  freelistentry_t *entries;\n  int first_available;\n  int entries_malloced;\n} freelist_t;\n\n#define STATIC_FREELIST_ENTRIES 8\n\n/* Forward */\nstatic int vgetargs1_impl(PyObject *args, PyObject *const *stack, Py_ssize_t nargs,\n                          const char *format, va_list *p_va, int flags);\nstatic int vgetargs1(PyObject *, const char *, va_list *, int);\nstatic void seterror(Py_ssize_t, const char *, int *, const char *, const char *);\nstatic const char *convertitem(PyObject *, const char **, va_list *, int, int *,\n                               char *, size_t, freelist_t *);\nstatic const char *converttuple(PyObject *, const char **, va_list *, int,\n                                int *, char *, size_t, int, freelist_t *);\nstatic const char *convertsimple(PyObject *, const char **, va_list *, int,\n                                 char *, size_t, freelist_t *);\nstatic Py_ssize_t convertbuffer(PyObject *, const void **p, const char **);\nstatic int getbuffer(PyObject *, Py_buffer *, const char**);\n\nstatic int vgetargskeywords(PyObject *, PyObject *,\n                            const char *, char **, va_list *, int);\nstatic int vgetargskeywordsfast(PyObject *, PyObject *,\n                            struct _PyArg_Parser *, va_list *, int);\nstatic int vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,\n                          PyObject *keywords, PyObject *kwnames,\n                          struct _PyArg_Parser *parser,\n                          va_list *p_va, int flags);\nstatic const char *skipitem(const char **, va_list *, int);\n\nint\nPyArg_Parse(PyObject *args, const char *format, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, format);\n    retval = vgetargs1(args, format, &va, FLAG_COMPAT);\n    va_end(va);\n    return retval;\n}\n\nPyAPI_FUNC(int)\n_PyArg_Parse_SizeT(PyObject *args, const char *format, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, format);\n    retval = vgetargs1(args, format, &va, FLAG_COMPAT);\n    va_end(va);\n    return retval;\n}\n\n\nint\nPyArg_ParseTuple(PyObject *args, const char *format, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, format);\n    retval = vgetargs1(args, format, &va, 0);\n    va_end(va);\n    return retval;\n}\n\nint\n_PyArg_ParseTuple_SizeT(PyObject *args, const char *format, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, format);\n    retval = vgetargs1(args, format, &va, 0);\n    va_end(va);\n    return retval;\n}\n\n\nint\n_PyArg_ParseStack(PyObject *const *args, Py_ssize_t nargs, const char *format, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, format);\n    retval = vgetargs1_impl(NULL, args, nargs, format, &va, 0);\n    va_end(va);\n    return retval;\n}\n\nint\nPyArg_VaParse(PyObject *args, const char *format, va_list va)\n{\n    va_list lva;\n    int retval;\n\n    va_copy(lva, va);\n\n    retval = vgetargs1(args, format, &lva, 0);\n    va_end(lva);\n    return retval;\n}\n\nint\n_PyArg_VaParse_SizeT(PyObject *args, const char *format, va_list va)\n{\n    va_list lva;\n    int retval;\n\n    va_copy(lva, va);\n\n    retval = vgetargs1(args, format, &lva, 0);\n    va_end(lva);\n    return retval;\n}\n\n\n/* Handle cleanup of allocated memory in case of exception */\n\nstatic int\ncleanup_ptr(PyObject *self, void *ptr)\n{\n    void **pptr = (void **)ptr;\n    PyMem_Free(*pptr);\n    *pptr = NULL;\n    return 0;\n}\n\nstatic int\ncleanup_buffer(PyObject *self, void *ptr)\n{\n    Py_buffer *buf = (Py_buffer *)ptr;\n    if (buf) {\n        PyBuffer_Release(buf);\n    }\n    return 0;\n}\n\nstatic int\naddcleanup(void *ptr, freelist_t *freelist, destr_t destructor)\n{\n    int index;\n\n    index = freelist->first_available;\n    freelist->first_available += 1;\n\n    freelist->entries[index].item = ptr;\n    freelist->entries[index].destructor = destructor;\n\n    return 0;\n}\n\nstatic int\ncleanreturn(int retval, freelist_t *freelist)\n{\n    int index;\n\n    if (retval == 0) {\n      /* A failure occurred, therefore execute all of the cleanup\n         functions.\n      */\n      for (index = 0; index < freelist->first_available; ++index) {\n          freelist->entries[index].destructor(NULL,\n                                              freelist->entries[index].item);\n      }\n    }\n    if (freelist->entries_malloced)\n        PyMem_Free(freelist->entries);\n    return retval;\n}\n\n\nstatic int\nvgetargs1_impl(PyObject *compat_args, PyObject *const *stack, Py_ssize_t nargs, const char *format,\n               va_list *p_va, int flags)\n{\n    char msgbuf[256];\n    int levels[32];\n    const char *fname = NULL;\n    const char *message = NULL;\n    int min = -1;\n    int max = 0;\n    int level = 0;\n    int endfmt = 0;\n    const char *formatsave = format;\n    Py_ssize_t i;\n    const char *msg;\n    int compat = flags & FLAG_COMPAT;\n    freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];\n    freelist_t freelist;\n\n    assert(nargs == 0 || stack != NULL);\n\n    freelist.entries = static_entries;\n    freelist.first_available = 0;\n    freelist.entries_malloced = 0;\n\n    flags = flags & ~FLAG_COMPAT;\n\n    while (endfmt == 0) {\n        int c = *format++;\n        switch (c) {\n        case '(':\n            if (level == 0)\n                max++;\n            level++;\n            if (level >= 30)\n                Py_FatalError(\"too many tuple nesting levels \"\n                              \"in argument format string\");\n            break;\n        case ')':\n            if (level == 0)\n                Py_FatalError(\"excess ')' in getargs format\");\n            else\n                level--;\n            break;\n        case '\\0':\n            endfmt = 1;\n            break;\n        case ':':\n            fname = format;\n            endfmt = 1;\n            break;\n        case ';':\n            message = format;\n            endfmt = 1;\n            break;\n        case '|':\n            if (level == 0)\n                min = max;\n            break;\n        default:\n            if (level == 0) {\n                if (Py_ISALPHA(c))\n                    if (c != 'e') /* skip encoded */\n                        max++;\n            }\n            break;\n        }\n    }\n\n    if (level != 0)\n        Py_FatalError(/* '(' */ \"missing ')' in getargs format\");\n\n    if (min < 0)\n        min = max;\n\n    format = formatsave;\n\n    if (max > STATIC_FREELIST_ENTRIES) {\n        freelist.entries = PyMem_NEW(freelistentry_t, max);\n        if (freelist.entries == NULL) {\n            PyErr_NoMemory();\n            return 0;\n        }\n        freelist.entries_malloced = 1;\n    }\n\n    if (compat) {\n        if (max == 0) {\n            if (compat_args == NULL)\n                return 1;\n            PyErr_Format(PyExc_TypeError,\n                         \"%.200s%s takes no arguments\",\n                         fname==NULL ? \"function\" : fname,\n                         fname==NULL ? \"\" : \"()\");\n            return cleanreturn(0, &freelist);\n        }\n        else if (min == 1 && max == 1) {\n            if (compat_args == NULL) {\n                PyErr_Format(PyExc_TypeError,\n                             \"%.200s%s takes at least one argument\",\n                             fname==NULL ? \"function\" : fname,\n                             fname==NULL ? \"\" : \"()\");\n                return cleanreturn(0, &freelist);\n            }\n            msg = convertitem(compat_args, &format, p_va, flags, levels,\n                              msgbuf, sizeof(msgbuf), &freelist);\n            if (msg == NULL)\n                return cleanreturn(1, &freelist);\n            seterror(levels[0], msg, levels+1, fname, message);\n            return cleanreturn(0, &freelist);\n        }\n        else {\n            PyErr_SetString(PyExc_SystemError,\n                \"old style getargs format uses new features\");\n            return cleanreturn(0, &freelist);\n        }\n    }\n\n    if (nargs < min || max < nargs) {\n        if (message == NULL)\n            PyErr_Format(PyExc_TypeError,\n                         \"%.150s%s takes %s %d argument%s (%zd given)\",\n                         fname==NULL ? \"function\" : fname,\n                         fname==NULL ? \"\" : \"()\",\n                         min==max ? \"exactly\"\n                         : nargs < min ? \"at least\" : \"at most\",\n                         nargs < min ? min : max,\n                         (nargs < min ? min : max) == 1 ? \"\" : \"s\",\n                         nargs);\n        else\n            PyErr_SetString(PyExc_TypeError, message);\n        return cleanreturn(0, &freelist);\n    }\n\n    for (i = 0; i < nargs; i++) {\n        if (*format == '|')\n            format++;\n        msg = convertitem(stack[i], &format, p_va,\n                          flags, levels, msgbuf,\n                          sizeof(msgbuf), &freelist);\n        if (msg) {\n            seterror(i+1, msg, levels, fname, message);\n            return cleanreturn(0, &freelist);\n        }\n    }\n\n    if (*format != '\\0' && !Py_ISALPHA(*format) &&\n        *format != '(' &&\n        *format != '|' && *format != ':' && *format != ';') {\n        PyErr_Format(PyExc_SystemError,\n                     \"bad format string: %.200s\", formatsave);\n        return cleanreturn(0, &freelist);\n    }\n\n    return cleanreturn(1, &freelist);\n}\n\nstatic int\nvgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)\n{\n    PyObject **stack;\n    Py_ssize_t nargs;\n\n    if (!(flags & FLAG_COMPAT)) {\n        assert(args != NULL);\n\n        if (!PyTuple_Check(args)) {\n            PyErr_SetString(PyExc_SystemError,\n                \"new style getargs format but argument is not a tuple\");\n            return 0;\n        }\n\n        stack = _PyTuple_ITEMS(args);\n        nargs = PyTuple_GET_SIZE(args);\n    }\n    else {\n        stack = NULL;\n        nargs = 0;\n    }\n\n    return vgetargs1_impl(args, stack, nargs, format, p_va, flags);\n}\n\n\nstatic void\nseterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname,\n         const char *message)\n{\n    char buf[512];\n    int i;\n    char *p = buf;\n\n    if (PyErr_Occurred())\n        return;\n    else if (message == NULL) {\n        if (fname != NULL) {\n            PyOS_snprintf(p, sizeof(buf), \"%.200s() \", fname);\n            p += strlen(p);\n        }\n        if (iarg != 0) {\n            PyOS_snprintf(p, sizeof(buf) - (p - buf),\n                          \"argument %zd\", iarg);\n            i = 0;\n            p += strlen(p);\n            while (i < 32 && levels[i] > 0 && (int)(p-buf) < 220) {\n                PyOS_snprintf(p, sizeof(buf) - (p - buf),\n                              \", item %d\", levels[i]-1);\n                p += strlen(p);\n                i++;\n            }\n        }\n        else {\n            PyOS_snprintf(p, sizeof(buf) - (p - buf), \"argument\");\n            p += strlen(p);\n        }\n        PyOS_snprintf(p, sizeof(buf) - (p - buf), \" %.256s\", msg);\n        message = buf;\n    }\n    if (msg[0] == '(') {\n        PyErr_SetString(PyExc_SystemError, message);\n    }\n    else {\n        PyErr_SetString(PyExc_TypeError, message);\n    }\n}\n\n\n/* Convert a tuple argument.\n   On entry, *p_format points to the character _after_ the opening '('.\n   On successful exit, *p_format points to the closing ')'.\n   If successful:\n      *p_format and *p_va are updated,\n      *levels and *msgbuf are untouched,\n      and NULL is returned.\n   If the argument is invalid:\n      *p_format is unchanged,\n      *p_va is undefined,\n      *levels is a 0-terminated list of item numbers,\n      *msgbuf contains an error message, whose format is:\n     \"must be <typename1>, not <typename2>\", where:\n        <typename1> is the name of the expected type, and\n        <typename2> is the name of the actual type,\n      and msgbuf is returned.\n*/\n\nstatic const char *\nconverttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags,\n             int *levels, char *msgbuf, size_t bufsize, int toplevel,\n             freelist_t *freelist)\n{\n    int level = 0;\n    int n = 0;\n    const char *format = *p_format;\n    int i;\n    Py_ssize_t len;\n\n    for (;;) {\n        int c = *format++;\n        if (c == '(') {\n            if (level == 0)\n                n++;\n            level++;\n        }\n        else if (c == ')') {\n            if (level == 0)\n                break;\n            level--;\n        }\n        else if (c == ':' || c == ';' || c == '\\0')\n            break;\n        else if (level == 0 && Py_ISALPHA(c))\n            n++;\n    }\n\n    if (!PySequence_Check(arg) || PyBytes_Check(arg)) {\n        levels[0] = 0;\n        PyOS_snprintf(msgbuf, bufsize,\n                      toplevel ? \"expected %d arguments, not %.50s\" :\n                      \"must be %d-item sequence, not %.50s\",\n                  n,\n                  arg == Py_None ? \"None\" : Py_TYPE(arg)->tp_name);\n        return msgbuf;\n    }\n\n    len = PySequence_Size(arg);\n    if (len != n) {\n        levels[0] = 0;\n        if (toplevel) {\n            PyOS_snprintf(msgbuf, bufsize,\n                          \"expected %d argument%s, not %zd\",\n                          n,\n                          n == 1 ? \"\" : \"s\",\n                          len);\n        }\n        else {\n            PyOS_snprintf(msgbuf, bufsize,\n                          \"must be sequence of length %d, not %zd\",\n                          n, len);\n        }\n        return msgbuf;\n    }\n\n    format = *p_format;\n    for (i = 0; i < n; i++) {\n        const char *msg;\n        PyObject *item;\n        item = PySequence_GetItem(arg, i);\n        if (item == NULL) {\n            PyErr_Clear();\n            levels[0] = i+1;\n            levels[1] = 0;\n            strncpy(msgbuf, \"is not retrievable\", bufsize);\n            return msgbuf;\n        }\n        msg = convertitem(item, &format, p_va, flags, levels+1,\n                          msgbuf, bufsize, freelist);\n        /* PySequence_GetItem calls tp->sq_item, which INCREFs */\n        Py_XDECREF(item);\n        if (msg != NULL) {\n            levels[0] = i+1;\n            return msg;\n        }\n    }\n\n    *p_format = format;\n    return NULL;\n}\n\n\n/* Convert a single item. */\n\nstatic const char *\nconvertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags,\n            int *levels, char *msgbuf, size_t bufsize, freelist_t *freelist)\n{\n    const char *msg;\n    const char *format = *p_format;\n\n    if (*format == '(' /* ')' */) {\n        format++;\n        msg = converttuple(arg, &format, p_va, flags, levels, msgbuf,\n                           bufsize, 0, freelist);\n        if (msg == NULL)\n            format++;\n    }\n    else {\n        msg = convertsimple(arg, &format, p_va, flags,\n                            msgbuf, bufsize, freelist);\n        if (msg != NULL)\n            levels[0] = 0;\n    }\n    if (msg == NULL)\n        *p_format = format;\n    return msg;\n}\n\n\n\n/* Format an error message generated by convertsimple().\n   displayname must be UTF-8 encoded.\n*/\n\nvoid\n_PyArg_BadArgument(const char *fname, const char *displayname,\n                   const char *expected, PyObject *arg)\n{\n    PyErr_Format(PyExc_TypeError,\n                 \"%.200s() %.200s must be %.50s, not %.50s\",\n                 fname, displayname, expected,\n                 arg == Py_None ? \"None\" : Py_TYPE(arg)->tp_name);\n}\n\nstatic const char *\nconverterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize)\n{\n    assert(expected != NULL);\n    assert(arg != NULL);\n    if (expected[0] == '(') {\n        PyOS_snprintf(msgbuf, bufsize,\n                      \"%.100s\", expected);\n    }\n    else {\n        PyOS_snprintf(msgbuf, bufsize,\n                      \"must be %.50s, not %.50s\", expected,\n                      arg == Py_None ? \"None\" : Py_TYPE(arg)->tp_name);\n    }\n    return msgbuf;\n}\n\n#define CONV_UNICODE \"(unicode conversion error)\"\n\n/* Convert a non-tuple argument.  Return NULL if conversion went OK,\n   or a string with a message describing the failure.  The message is\n   formatted as \"must be <desired type>, not <actual type>\".\n   When failing, an exception may or may not have been raised.\n   Don't call if a tuple is expected.\n\n   When you add new format codes, please don't forget poor skipitem() below.\n*/\n\nstatic const char *\nconvertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,\n              char *msgbuf, size_t bufsize, freelist_t *freelist)\n{\n#define RETURN_ERR_OCCURRED return msgbuf\n\n    const char *format = *p_format;\n    char c = *format++;\n    const char *sarg;\n\n    switch (c) {\n\n    case 'b': { /* unsigned byte -- very short int */\n        char *p = va_arg(*p_va, char *);\n        long ival = PyLong_AsLong(arg);\n        if (ival == -1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else if (ival < 0) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"unsigned byte integer is less than minimum\");\n            RETURN_ERR_OCCURRED;\n        }\n        else if (ival > UCHAR_MAX) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"unsigned byte integer is greater than maximum\");\n            RETURN_ERR_OCCURRED;\n        }\n        else\n            *p = (unsigned char) ival;\n        break;\n    }\n\n    case 'B': {/* byte sized bitfield - both signed and unsigned\n                  values allowed */\n        char *p = va_arg(*p_va, char *);\n        unsigned long ival = PyLong_AsUnsignedLongMask(arg);\n        if (ival == (unsigned long)-1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = (unsigned char) ival;\n        break;\n    }\n\n    case 'h': {/* signed short int */\n        short *p = va_arg(*p_va, short *);\n        long ival = PyLong_AsLong(arg);\n        if (ival == -1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else if (ival < SHRT_MIN) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"signed short integer is less than minimum\");\n            RETURN_ERR_OCCURRED;\n        }\n        else if (ival > SHRT_MAX) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"signed short integer is greater than maximum\");\n            RETURN_ERR_OCCURRED;\n        }\n        else\n            *p = (short) ival;\n        break;\n    }\n\n    case 'H': { /* short int sized bitfield, both signed and\n                   unsigned allowed */\n        unsigned short *p = va_arg(*p_va, unsigned short *);\n        unsigned long ival = PyLong_AsUnsignedLongMask(arg);\n        if (ival == (unsigned long)-1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = (unsigned short) ival;\n        break;\n    }\n\n    case 'i': {/* signed int */\n        int *p = va_arg(*p_va, int *);\n        long ival = PyLong_AsLong(arg);\n        if (ival == -1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else if (ival > INT_MAX) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"signed integer is greater than maximum\");\n            RETURN_ERR_OCCURRED;\n        }\n        else if (ival < INT_MIN) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"signed integer is less than minimum\");\n            RETURN_ERR_OCCURRED;\n        }\n        else\n            *p = ival;\n        break;\n    }\n\n    case 'I': { /* int sized bitfield, both signed and\n                   unsigned allowed */\n        unsigned int *p = va_arg(*p_va, unsigned int *);\n        unsigned long ival = PyLong_AsUnsignedLongMask(arg);\n        if (ival == (unsigned long)-1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = (unsigned int) ival;\n        break;\n    }\n\n    case 'n': /* Py_ssize_t */\n    {\n        PyObject *iobj;\n        Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *);\n        Py_ssize_t ival = -1;\n        iobj = _PyNumber_Index(arg);\n        if (iobj != NULL) {\n            ival = PyLong_AsSsize_t(iobj);\n            Py_DECREF(iobj);\n        }\n        if (ival == -1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        *p = ival;\n        break;\n    }\n    case 'l': {/* long int */\n        long *p = va_arg(*p_va, long *);\n        long ival = PyLong_AsLong(arg);\n        if (ival == -1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = ival;\n        break;\n    }\n\n    case 'k': { /* long sized bitfield */\n        unsigned long *p = va_arg(*p_va, unsigned long *);\n        unsigned long ival;\n        if (PyLong_Check(arg))\n            ival = PyLong_AsUnsignedLongMask(arg);\n        else\n            return converterr(\"int\", arg, msgbuf, bufsize);\n        *p = ival;\n        break;\n    }\n\n    case 'L': {/* long long */\n        long long *p = va_arg( *p_va, long long * );\n        long long ival = PyLong_AsLongLong(arg);\n        if (ival == (long long)-1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = ival;\n        break;\n    }\n\n    case 'K': { /* long long sized bitfield */\n        unsigned long long *p = va_arg(*p_va, unsigned long long *);\n        unsigned long long ival;\n        if (PyLong_Check(arg))\n            ival = PyLong_AsUnsignedLongLongMask(arg);\n        else\n            return converterr(\"int\", arg, msgbuf, bufsize);\n        *p = ival;\n        break;\n    }\n\n    case 'f': {/* float */\n        float *p = va_arg(*p_va, float *);\n        double dval = PyFloat_AsDouble(arg);\n        if (dval == -1.0 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = (float) dval;\n        break;\n    }\n\n    case 'd': {/* double */\n        double *p = va_arg(*p_va, double *);\n        double dval = PyFloat_AsDouble(arg);\n        if (dval == -1.0 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = dval;\n        break;\n    }\n\n    case 'D': {/* complex double */\n        Py_complex *p = va_arg(*p_va, Py_complex *);\n        Py_complex cval;\n        cval = PyComplex_AsCComplex(arg);\n        if (PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = cval;\n        break;\n    }\n\n    case 'c': {/* char */\n        char *p = va_arg(*p_va, char *);\n        if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1)\n            *p = PyBytes_AS_STRING(arg)[0];\n        else if (PyByteArray_Check(arg) && PyByteArray_Size(arg) == 1)\n            *p = PyByteArray_AS_STRING(arg)[0];\n        else\n            return converterr(\"a byte string of length 1\", arg, msgbuf, bufsize);\n        break;\n    }\n\n    case 'C': {/* unicode char */\n        int *p = va_arg(*p_va, int *);\n        int kind;\n        const void *data;\n\n        if (!PyUnicode_Check(arg))\n            return converterr(\"a unicode character\", arg, msgbuf, bufsize);\n\n        if (PyUnicode_GET_LENGTH(arg) != 1)\n            return converterr(\"a unicode character\", arg, msgbuf, bufsize);\n\n        kind = PyUnicode_KIND(arg);\n        data = PyUnicode_DATA(arg);\n        *p = PyUnicode_READ(kind, data, 0);\n        break;\n    }\n\n    case 'p': {/* boolean *p*redicate */\n        int *p = va_arg(*p_va, int *);\n        int val = PyObject_IsTrue(arg);\n        if (val > 0)\n            *p = 1;\n        else if (val == 0)\n            *p = 0;\n        else\n            RETURN_ERR_OCCURRED;\n        break;\n    }\n\n    /* XXX WAAAAH!  's', 'y', 'z', 'u', 'Z', 'e', 'w' codes all\n       need to be cleaned up! */\n\n    case 'y': {/* any bytes-like object */\n        void **p = (void **)va_arg(*p_va, char **);\n        const char *buf;\n        Py_ssize_t count;\n        if (*format == '*') {\n            if (getbuffer(arg, (Py_buffer*)p, &buf) < 0)\n                return converterr(buf, arg, msgbuf, bufsize);\n            format++;\n            if (addcleanup(p, freelist, cleanup_buffer)) {\n                return converterr(\n                    \"(cleanup problem)\",\n                    arg, msgbuf, bufsize);\n            }\n            break;\n        }\n        count = convertbuffer(arg, (const void **)p, &buf);\n        if (count < 0)\n            return converterr(buf, arg, msgbuf, bufsize);\n        if (*format == '#') {\n            Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);\n            *psize = count;\n            format++;\n        } else {\n            if (strlen(*p) != (size_t)count) {\n                PyErr_SetString(PyExc_ValueError, \"embedded null byte\");\n                RETURN_ERR_OCCURRED;\n            }\n        }\n        break;\n    }\n\n    case 's': /* text string or bytes-like object */\n    case 'z': /* text string, bytes-like object or None */\n    {\n        if (*format == '*') {\n            /* \"s*\" or \"z*\" */\n            Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);\n\n            if (c == 'z' && arg == Py_None)\n                PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0);\n            else if (PyUnicode_Check(arg)) {\n                Py_ssize_t len;\n                sarg = PyUnicode_AsUTF8AndSize(arg, &len);\n                if (sarg == NULL)\n                    return converterr(CONV_UNICODE,\n                                      arg, msgbuf, bufsize);\n                PyBuffer_FillInfo(p, arg, (void *)sarg, len, 1, 0);\n            }\n            else { /* any bytes-like object */\n                const char *buf;\n                if (getbuffer(arg, p, &buf) < 0)\n                    return converterr(buf, arg, msgbuf, bufsize);\n            }\n            if (addcleanup(p, freelist, cleanup_buffer)) {\n                return converterr(\n                    \"(cleanup problem)\",\n                    arg, msgbuf, bufsize);\n            }\n            format++;\n        } else if (*format == '#') { /* a string or read-only bytes-like object */\n            /* \"s#\" or \"z#\" */\n            const void **p = (const void **)va_arg(*p_va, const char **);\n            Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);\n\n            if (c == 'z' && arg == Py_None) {\n                *p = NULL;\n                *psize = 0;\n            }\n            else if (PyUnicode_Check(arg)) {\n                Py_ssize_t len;\n                sarg = PyUnicode_AsUTF8AndSize(arg, &len);\n                if (sarg == NULL)\n                    return converterr(CONV_UNICODE,\n                                      arg, msgbuf, bufsize);\n                *p = sarg;\n                *psize = len;\n            }\n            else { /* read-only bytes-like object */\n                /* XXX Really? */\n                const char *buf;\n                Py_ssize_t count = convertbuffer(arg, p, &buf);\n                if (count < 0)\n                    return converterr(buf, arg, msgbuf, bufsize);\n                *psize = count;\n            }\n            format++;\n        } else {\n            /* \"s\" or \"z\" */\n            const char **p = va_arg(*p_va, const char **);\n            Py_ssize_t len;\n            sarg = NULL;\n\n            if (c == 'z' && arg == Py_None)\n                *p = NULL;\n            else if (PyUnicode_Check(arg)) {\n                sarg = PyUnicode_AsUTF8AndSize(arg, &len);\n                if (sarg == NULL)\n                    return converterr(CONV_UNICODE,\n                                      arg, msgbuf, bufsize);\n                if (strlen(sarg) != (size_t)len) {\n                    PyErr_SetString(PyExc_ValueError, \"embedded null character\");\n                    RETURN_ERR_OCCURRED;\n                }\n                *p = sarg;\n            }\n            else\n                return converterr(c == 'z' ? \"str or None\" : \"str\",\n                                  arg, msgbuf, bufsize);\n        }\n        break;\n    }\n\n    case 'e': {/* encoded string */\n        char **buffer;\n        const char *encoding;\n        PyObject *s;\n        int recode_strings;\n        Py_ssize_t size;\n        const char *ptr;\n\n        /* Get 'e' parameter: the encoding name */\n        encoding = (const char *)va_arg(*p_va, const char *);\n        if (encoding == NULL)\n            encoding = PyUnicode_GetDefaultEncoding();\n\n        /* Get output buffer parameter:\n           's' (recode all objects via Unicode) or\n           't' (only recode non-string objects)\n        */\n        if (*format == 's')\n            recode_strings = 1;\n        else if (*format == 't')\n            recode_strings = 0;\n        else\n            return converterr(\n                \"(unknown parser marker combination)\",\n                arg, msgbuf, bufsize);\n        buffer = (char **)va_arg(*p_va, char **);\n        format++;\n        if (buffer == NULL)\n            return converterr(\"(buffer is NULL)\",\n                              arg, msgbuf, bufsize);\n\n        /* Encode object */\n        if (!recode_strings &&\n            (PyBytes_Check(arg) || PyByteArray_Check(arg))) {\n            s = Py_NewRef(arg);\n            if (PyBytes_Check(arg)) {\n                size = PyBytes_GET_SIZE(s);\n                ptr = PyBytes_AS_STRING(s);\n            }\n            else {\n                size = PyByteArray_GET_SIZE(s);\n                ptr = PyByteArray_AS_STRING(s);\n            }\n        }\n        else if (PyUnicode_Check(arg)) {\n            /* Encode object; use default error handling */\n            s = PyUnicode_AsEncodedString(arg,\n                                          encoding,\n                                          NULL);\n            if (s == NULL)\n                return converterr(\"(encoding failed)\",\n                                  arg, msgbuf, bufsize);\n            assert(PyBytes_Check(s));\n            size = PyBytes_GET_SIZE(s);\n            ptr = PyBytes_AS_STRING(s);\n            if (ptr == NULL)\n                ptr = \"\";\n        }\n        else {\n            return converterr(\n                recode_strings ? \"str\" : \"str, bytes or bytearray\",\n                arg, msgbuf, bufsize);\n        }\n\n        /* Write output; output is guaranteed to be 0-terminated */\n        if (*format == '#') {\n            /* Using buffer length parameter '#':\n\n               - if *buffer is NULL, a new buffer of the\n               needed size is allocated and the data\n               copied into it; *buffer is updated to point\n               to the new buffer; the caller is\n               responsible for PyMem_Free()ing it after\n               usage\n\n               - if *buffer is not NULL, the data is\n               copied to *buffer; *buffer_len has to be\n               set to the size of the buffer on input;\n               buffer overflow is signalled with an error;\n               buffer has to provide enough room for the\n               encoded string plus the trailing 0-byte\n\n               - in both cases, *buffer_len is updated to\n               the size of the buffer /excluding/ the\n               trailing 0-byte\n\n            */\n            Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);\n\n            format++;\n            if (psize == NULL) {\n                Py_DECREF(s);\n                return converterr(\n                    \"(buffer_len is NULL)\",\n                    arg, msgbuf, bufsize);\n            }\n            if (*buffer == NULL) {\n                *buffer = PyMem_NEW(char, size + 1);\n                if (*buffer == NULL) {\n                    Py_DECREF(s);\n                    PyErr_NoMemory();\n                    RETURN_ERR_OCCURRED;\n                }\n                if (addcleanup(buffer, freelist, cleanup_ptr)) {\n                    Py_DECREF(s);\n                    return converterr(\n                        \"(cleanup problem)\",\n                        arg, msgbuf, bufsize);\n                }\n            } else {\n                if (size + 1 > *psize) {\n                    Py_DECREF(s);\n                    PyErr_Format(PyExc_ValueError,\n                                 \"encoded string too long \"\n                                 \"(%zd, maximum length %zd)\",\n                                 (Py_ssize_t)size, (Py_ssize_t)(*psize - 1));\n                    RETURN_ERR_OCCURRED;\n                }\n            }\n            memcpy(*buffer, ptr, size+1);\n\n            *psize = size;\n        }\n        else {\n            /* Using a 0-terminated buffer:\n\n               - the encoded string has to be 0-terminated\n               for this variant to work; if it is not, an\n               error raised\n\n               - a new buffer of the needed size is\n               allocated and the data copied into it;\n               *buffer is updated to point to the new\n               buffer; the caller is responsible for\n               PyMem_Free()ing it after usage\n\n            */\n            if ((Py_ssize_t)strlen(ptr) != size) {\n                Py_DECREF(s);\n                return converterr(\n                    \"encoded string without null bytes\",\n                    arg, msgbuf, bufsize);\n            }\n            *buffer = PyMem_NEW(char, size + 1);\n            if (*buffer == NULL) {\n                Py_DECREF(s);\n                PyErr_NoMemory();\n                RETURN_ERR_OCCURRED;\n            }\n            if (addcleanup(buffer, freelist, cleanup_ptr)) {\n                Py_DECREF(s);\n                return converterr(\"(cleanup problem)\",\n                                arg, msgbuf, bufsize);\n            }\n            memcpy(*buffer, ptr, size+1);\n        }\n        Py_DECREF(s);\n        break;\n    }\n\n    case 'S': { /* PyBytes object */\n        PyObject **p = va_arg(*p_va, PyObject **);\n        if (PyBytes_Check(arg))\n            *p = arg;\n        else\n            return converterr(\"bytes\", arg, msgbuf, bufsize);\n        break;\n    }\n\n    case 'Y': { /* PyByteArray object */\n        PyObject **p = va_arg(*p_va, PyObject **);\n        if (PyByteArray_Check(arg))\n            *p = arg;\n        else\n            return converterr(\"bytearray\", arg, msgbuf, bufsize);\n        break;\n    }\n\n    case 'U': { /* PyUnicode object */\n        PyObject **p = va_arg(*p_va, PyObject **);\n        if (PyUnicode_Check(arg)) {\n            *p = arg;\n        }\n        else\n            return converterr(\"str\", arg, msgbuf, bufsize);\n        break;\n    }\n\n    case 'O': { /* object */\n        PyTypeObject *type;\n        PyObject **p;\n        if (*format == '!') {\n            type = va_arg(*p_va, PyTypeObject*);\n            p = va_arg(*p_va, PyObject **);\n            format++;\n            if (PyType_IsSubtype(Py_TYPE(arg), type))\n                *p = arg;\n            else\n                return converterr(type->tp_name, arg, msgbuf, bufsize);\n\n        }\n        else if (*format == '&') {\n            typedef int (*converter)(PyObject *, void *);\n            converter convert = va_arg(*p_va, converter);\n            void *addr = va_arg(*p_va, void *);\n            int res;\n            format++;\n            if (! (res = (*convert)(arg, addr)))\n                return converterr(\"(unspecified)\",\n                                  arg, msgbuf, bufsize);\n            if (res == Py_CLEANUP_SUPPORTED &&\n                addcleanup(addr, freelist, convert) == -1)\n                return converterr(\"(cleanup problem)\",\n                                arg, msgbuf, bufsize);\n        }\n        else {\n            p = va_arg(*p_va, PyObject **);\n            *p = arg;\n        }\n        break;\n    }\n\n\n    case 'w': { /* \"w*\": memory buffer, read-write access */\n        void **p = va_arg(*p_va, void **);\n\n        if (*format != '*')\n            return converterr(\n                \"(invalid use of 'w' format character)\",\n                arg, msgbuf, bufsize);\n        format++;\n\n        /* Caller is interested in Py_buffer, and the object\n           supports it directly. */\n        if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) {\n            PyErr_Clear();\n            return converterr(\"read-write bytes-like object\",\n                              arg, msgbuf, bufsize);\n        }\n        if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) {\n            PyBuffer_Release((Py_buffer*)p);\n            return converterr(\"contiguous buffer\", arg, msgbuf, bufsize);\n        }\n        if (addcleanup(p, freelist, cleanup_buffer)) {\n            return converterr(\n                \"(cleanup problem)\",\n                arg, msgbuf, bufsize);\n        }\n        break;\n    }\n\n    default:\n        return converterr(\"(impossible<bad format char>)\", arg, msgbuf, bufsize);\n\n    }\n\n    *p_format = format;\n    return NULL;\n\n#undef RETURN_ERR_OCCURRED\n}\n\nstatic Py_ssize_t\nconvertbuffer(PyObject *arg, const void **p, const char **errmsg)\n{\n    PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer;\n    Py_ssize_t count;\n    Py_buffer view;\n\n    *errmsg = NULL;\n    *p = NULL;\n    if (pb != NULL && pb->bf_releasebuffer != NULL) {\n        *errmsg = \"read-only bytes-like object\";\n        return -1;\n    }\n\n    if (getbuffer(arg, &view, errmsg) < 0)\n        return -1;\n    count = view.len;\n    *p = view.buf;\n    PyBuffer_Release(&view);\n    return count;\n}\n\nstatic int\ngetbuffer(PyObject *arg, Py_buffer *view, const char **errmsg)\n{\n    if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) {\n        *errmsg = \"bytes-like object\";\n        return -1;\n    }\n    if (!PyBuffer_IsContiguous(view, 'C')) {\n        PyBuffer_Release(view);\n        *errmsg = \"contiguous buffer\";\n        return -1;\n    }\n    return 0;\n}\n\n/* Support for keyword arguments donated by\n   Geoff Philbrick <philbric@delphi.hks.com> */\n\n/* Return false (0) for error, else true. */\nint\nPyArg_ParseTupleAndKeywords(PyObject *args,\n                            PyObject *keywords,\n                            const char *format,\n                            char **kwlist, ...)\n{\n    int retval;\n    va_list va;\n\n    if ((args == NULL || !PyTuple_Check(args)) ||\n        (keywords != NULL && !PyDict_Check(keywords)) ||\n        format == NULL ||\n        kwlist == NULL)\n    {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    va_start(va, kwlist);\n    retval = vgetargskeywords(args, keywords, format, kwlist, &va, 0);\n    va_end(va);\n    return retval;\n}\n\nint\n_PyArg_ParseTupleAndKeywords_SizeT(PyObject *args,\n                                  PyObject *keywords,\n                                  const char *format,\n                                  char **kwlist, ...)\n{\n    int retval;\n    va_list va;\n\n    if ((args == NULL || !PyTuple_Check(args)) ||\n        (keywords != NULL && !PyDict_Check(keywords)) ||\n        format == NULL ||\n        kwlist == NULL)\n    {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    va_start(va, kwlist);\n    retval = vgetargskeywords(args, keywords, format,\n                              kwlist, &va, 0);\n    va_end(va);\n    return retval;\n}\n\n\nint\nPyArg_VaParseTupleAndKeywords(PyObject *args,\n                              PyObject *keywords,\n                              const char *format,\n                              char **kwlist, va_list va)\n{\n    int retval;\n    va_list lva;\n\n    if ((args == NULL || !PyTuple_Check(args)) ||\n        (keywords != NULL && !PyDict_Check(keywords)) ||\n        format == NULL ||\n        kwlist == NULL)\n    {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    va_copy(lva, va);\n\n    retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0);\n    va_end(lva);\n    return retval;\n}\n\nint\n_PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args,\n                                    PyObject *keywords,\n                                    const char *format,\n                                    char **kwlist, va_list va)\n{\n    int retval;\n    va_list lva;\n\n    if ((args == NULL || !PyTuple_Check(args)) ||\n        (keywords != NULL && !PyDict_Check(keywords)) ||\n        format == NULL ||\n        kwlist == NULL)\n    {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    va_copy(lva, va);\n\n    retval = vgetargskeywords(args, keywords, format,\n                              kwlist, &lva, 0);\n    va_end(lva);\n    return retval;\n}\n\nPyAPI_FUNC(int)\n_PyArg_ParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords,\n                            struct _PyArg_Parser *parser, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, parser);\n    retval = vgetargskeywordsfast(args, keywords, parser, &va, 0);\n    va_end(va);\n    return retval;\n}\n\nint\n_PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,\n                            struct _PyArg_Parser *parser, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, parser);\n    retval = vgetargskeywordsfast(args, keywords, parser, &va, 0);\n    va_end(va);\n    return retval;\n}\n\nint\n_PyArg_ParseStackAndKeywords(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames,\n                  struct _PyArg_Parser *parser, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, parser);\n    retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, 0);\n    va_end(va);\n    return retval;\n}\n\nint\n_PyArg_ParseStackAndKeywords_SizeT(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames,\n                        struct _PyArg_Parser *parser, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, parser);\n    retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, 0);\n    va_end(va);\n    return retval;\n}\n\n\nPyAPI_FUNC(int)\n_PyArg_VaParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords,\n                            struct _PyArg_Parser *parser, va_list va)\n{\n    int retval;\n    va_list lva;\n\n    va_copy(lva, va);\n\n    retval = vgetargskeywordsfast(args, keywords, parser, &lva, 0);\n    va_end(lva);\n    return retval;\n}\n\nstatic void\nerror_unexpected_keyword_arg(PyObject *kwargs, PyObject *kwnames, PyObject *kwtuple, const char *fname)\n{\n    /* make sure there are no extraneous keyword arguments */\n    Py_ssize_t j = 0;\n    while (1) {\n        PyObject *keyword;\n        if (kwargs != NULL) {\n            if (!PyDict_Next(kwargs, &j, &keyword, NULL))\n                break;\n        }\n        else {\n            if (j >= PyTuple_GET_SIZE(kwnames))\n                break;\n            keyword = PyTuple_GET_ITEM(kwnames, j);\n            j++;\n        }\n        if (!PyUnicode_Check(keyword)) {\n            PyErr_SetString(PyExc_TypeError,\n                            \"keywords must be strings\");\n            return;\n        }\n\n        int match = PySequence_Contains(kwtuple, keyword);\n        if (match <= 0) {\n            if (!match) {\n                PyErr_Format(PyExc_TypeError,\n                             \"'%S' is an invalid keyword \"\n                             \"argument for %.200s%s\",\n                             keyword,\n                             (fname == NULL) ? \"this function\" : fname,\n                             (fname == NULL) ? \"\" : \"()\");\n            }\n            return;\n        }\n    }\n    /* Something wrong happened. There are extraneous keyword arguments,\n     * but we don't know what. And we don't bother. */\n    PyErr_Format(PyExc_TypeError,\n                 \"invalid keyword argument for %.200s%s\",\n                 (fname == NULL) ? \"this function\" : fname,\n                 (fname == NULL) ? \"\" : \"()\");\n}\n\nint\nPyArg_ValidateKeywordArguments(PyObject *kwargs)\n{\n    if (!PyDict_Check(kwargs)) {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n    if (!_PyDict_HasOnlyStringKeys(kwargs)) {\n        PyErr_SetString(PyExc_TypeError,\n                        \"keywords must be strings\");\n        return 0;\n    }\n    return 1;\n}\n\n#define IS_END_OF_FORMAT(c) (c == '\\0' || c == ';' || c == ':')\n\nstatic int\nvgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,\n                 char **kwlist, va_list *p_va, int flags)\n{\n    char msgbuf[512];\n    int levels[32];\n    const char *fname, *msg, *custom_msg;\n    int min = INT_MAX;\n    int max = INT_MAX;\n    int i, pos, len;\n    int skip = 0;\n    Py_ssize_t nargs, nkwargs;\n    PyObject *current_arg;\n    freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];\n    freelist_t freelist;\n\n    freelist.entries = static_entries;\n    freelist.first_available = 0;\n    freelist.entries_malloced = 0;\n\n    assert(args != NULL && PyTuple_Check(args));\n    assert(kwargs == NULL || PyDict_Check(kwargs));\n    assert(format != NULL);\n    assert(kwlist != NULL);\n    assert(p_va != NULL);\n\n    /* grab the function name or custom error msg first (mutually exclusive) */\n    fname = strchr(format, ':');\n    if (fname) {\n        fname++;\n        custom_msg = NULL;\n    }\n    else {\n        custom_msg = strchr(format,';');\n        if (custom_msg)\n            custom_msg++;\n    }\n\n    /* scan kwlist and count the number of positional-only parameters */\n    for (pos = 0; kwlist[pos] && !*kwlist[pos]; pos++) {\n    }\n    /* scan kwlist and get greatest possible nbr of args */\n    for (len = pos; kwlist[len]; len++) {\n        if (!*kwlist[len]) {\n            PyErr_SetString(PyExc_SystemError,\n                            \"Empty keyword parameter name\");\n            return cleanreturn(0, &freelist);\n        }\n    }\n\n    if (len > STATIC_FREELIST_ENTRIES) {\n        freelist.entries = PyMem_NEW(freelistentry_t, len);\n        if (freelist.entries == NULL) {\n            PyErr_NoMemory();\n            return 0;\n        }\n        freelist.entries_malloced = 1;\n    }\n\n    nargs = PyTuple_GET_SIZE(args);\n    nkwargs = (kwargs == NULL) ? 0 : PyDict_GET_SIZE(kwargs);\n    if (nargs + nkwargs > len) {\n        /* Adding \"keyword\" (when nargs == 0) prevents producing wrong error\n           messages in some special cases (see bpo-31229). */\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s%s takes at most %d %sargument%s (%zd given)\",\n                     (fname == NULL) ? \"function\" : fname,\n                     (fname == NULL) ? \"\" : \"()\",\n                     len,\n                     (nargs == 0) ? \"keyword \" : \"\",\n                     (len == 1) ? \"\" : \"s\",\n                     nargs + nkwargs);\n        return cleanreturn(0, &freelist);\n    }\n\n    /* convert tuple args and keyword args in same loop, using kwlist to drive process */\n    for (i = 0; i < len; i++) {\n        if (*format == '|') {\n            if (min != INT_MAX) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Invalid format string (| specified twice)\");\n                return cleanreturn(0, &freelist);\n            }\n\n            min = i;\n            format++;\n\n            if (max != INT_MAX) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Invalid format string ($ before |)\");\n                return cleanreturn(0, &freelist);\n            }\n        }\n        if (*format == '$') {\n            if (max != INT_MAX) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Invalid format string ($ specified twice)\");\n                return cleanreturn(0, &freelist);\n            }\n\n            max = i;\n            format++;\n\n            if (max < pos) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Empty parameter name after $\");\n                return cleanreturn(0, &freelist);\n            }\n            if (skip) {\n                /* Now we know the minimal and the maximal numbers of\n                 * positional arguments and can raise an exception with\n                 * informative message (see below). */\n                break;\n            }\n            if (max < nargs) {\n                if (max == 0) {\n                    PyErr_Format(PyExc_TypeError,\n                                 \"%.200s%s takes no positional arguments\",\n                                 (fname == NULL) ? \"function\" : fname,\n                                 (fname == NULL) ? \"\" : \"()\");\n                }\n                else {\n                    PyErr_Format(PyExc_TypeError,\n                                 \"%.200s%s takes %s %d positional argument%s\"\n                                 \" (%zd given)\",\n                                 (fname == NULL) ? \"function\" : fname,\n                                 (fname == NULL) ? \"\" : \"()\",\n                                 (min != INT_MAX) ? \"at most\" : \"exactly\",\n                                 max,\n                                 max == 1 ? \"\" : \"s\",\n                                 nargs);\n                }\n                return cleanreturn(0, &freelist);\n            }\n        }\n        if (IS_END_OF_FORMAT(*format)) {\n            PyErr_Format(PyExc_SystemError,\n                         \"More keyword list entries (%d) than \"\n                         \"format specifiers (%d)\", len, i);\n            return cleanreturn(0, &freelist);\n        }\n        if (!skip) {\n            if (i < nargs) {\n                current_arg = PyTuple_GET_ITEM(args, i);\n            }\n            else if (nkwargs && i >= pos) {\n                current_arg = _PyDict_GetItemStringWithError(kwargs, kwlist[i]);\n                if (current_arg) {\n                    --nkwargs;\n                }\n                else if (PyErr_Occurred()) {\n                    return cleanreturn(0, &freelist);\n                }\n            }\n            else {\n                current_arg = NULL;\n            }\n\n            if (current_arg) {\n                msg = convertitem(current_arg, &format, p_va, flags,\n                    levels, msgbuf, sizeof(msgbuf), &freelist);\n                if (msg) {\n                    seterror(i+1, msg, levels, fname, custom_msg);\n                    return cleanreturn(0, &freelist);\n                }\n                continue;\n            }\n\n            if (i < min) {\n                if (i < pos) {\n                    assert (min == INT_MAX);\n                    assert (max == INT_MAX);\n                    skip = 1;\n                    /* At that moment we still don't know the minimal and\n                     * the maximal numbers of positional arguments.  Raising\n                     * an exception is deferred until we encounter | and $\n                     * or the end of the format. */\n                }\n                else {\n                    PyErr_Format(PyExc_TypeError,  \"%.200s%s missing required \"\n                                 \"argument '%s' (pos %d)\",\n                                 (fname == NULL) ? \"function\" : fname,\n                                 (fname == NULL) ? \"\" : \"()\",\n                                 kwlist[i], i+1);\n                    return cleanreturn(0, &freelist);\n                }\n            }\n            /* current code reports success when all required args\n             * fulfilled and no keyword args left, with no further\n             * validation. XXX Maybe skip this in debug build ?\n             */\n            if (!nkwargs && !skip) {\n                return cleanreturn(1, &freelist);\n            }\n        }\n\n        /* We are into optional args, skip through to any remaining\n         * keyword args */\n        msg = skipitem(&format, p_va, flags);\n        if (msg) {\n            PyErr_Format(PyExc_SystemError, \"%s: '%s'\", msg,\n                         format);\n            return cleanreturn(0, &freelist);\n        }\n    }\n\n    if (skip) {\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s%s takes %s %d positional argument%s\"\n                     \" (%zd given)\",\n                     (fname == NULL) ? \"function\" : fname,\n                     (fname == NULL) ? \"\" : \"()\",\n                     (Py_MIN(pos, min) < i) ? \"at least\" : \"exactly\",\n                     Py_MIN(pos, min),\n                     Py_MIN(pos, min) == 1 ? \"\" : \"s\",\n                     nargs);\n        return cleanreturn(0, &freelist);\n    }\n\n    if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) {\n        PyErr_Format(PyExc_SystemError,\n            \"more argument specifiers than keyword list entries \"\n            \"(remaining format:'%s')\", format);\n        return cleanreturn(0, &freelist);\n    }\n\n    if (nkwargs > 0) {\n        PyObject *key;\n        Py_ssize_t j;\n        /* make sure there are no arguments given by name and position */\n        for (i = pos; i < nargs; i++) {\n            current_arg = _PyDict_GetItemStringWithError(kwargs, kwlist[i]);\n            if (current_arg) {\n                /* arg present in tuple and in dict */\n                PyErr_Format(PyExc_TypeError,\n                             \"argument for %.200s%s given by name ('%s') \"\n                             \"and position (%d)\",\n                             (fname == NULL) ? \"function\" : fname,\n                             (fname == NULL) ? \"\" : \"()\",\n                             kwlist[i], i+1);\n                return cleanreturn(0, &freelist);\n            }\n            else if (PyErr_Occurred()) {\n                return cleanreturn(0, &freelist);\n            }\n        }\n        /* make sure there are no extraneous keyword arguments */\n        j = 0;\n        while (PyDict_Next(kwargs, &j, &key, NULL)) {\n            int match = 0;\n            if (!PyUnicode_Check(key)) {\n                PyErr_SetString(PyExc_TypeError,\n                                \"keywords must be strings\");\n                return cleanreturn(0, &freelist);\n            }\n            for (i = pos; i < len; i++) {\n                if (_PyUnicode_EqualToASCIIString(key, kwlist[i])) {\n                    match = 1;\n                    break;\n                }\n            }\n            if (!match) {\n                PyErr_Format(PyExc_TypeError,\n                             \"'%U' is an invalid keyword \"\n                             \"argument for %.200s%s\",\n                             key,\n                             (fname == NULL) ? \"this function\" : fname,\n                             (fname == NULL) ? \"\" : \"()\");\n                return cleanreturn(0, &freelist);\n            }\n        }\n        /* Something wrong happened. There are extraneous keyword arguments,\n         * but we don't know what. And we don't bother. */\n        PyErr_Format(PyExc_TypeError,\n                     \"invalid keyword argument for %.200s%s\",\n                     (fname == NULL) ? \"this function\" : fname,\n                     (fname == NULL) ? \"\" : \"()\");\n        return cleanreturn(0, &freelist);\n    }\n\n    return cleanreturn(1, &freelist);\n}\n\n\nstatic int\nscan_keywords(const char * const *keywords, int *ptotal, int *pposonly)\n{\n    /* scan keywords and count the number of positional-only parameters */\n    int i;\n    for (i = 0; keywords[i] && !*keywords[i]; i++) {\n    }\n    *pposonly = i;\n\n    /* scan keywords and get greatest possible nbr of args */\n    for (; keywords[i]; i++) {\n        if (!*keywords[i]) {\n            PyErr_SetString(PyExc_SystemError,\n                            \"Empty keyword parameter name\");\n            return -1;\n        }\n    }\n    *ptotal = i;\n    return 0;\n}\n\nstatic int\nparse_format(const char *format, int total, int npos,\n             const char **pfname, const char **pcustommsg,\n             int *pmin, int *pmax)\n{\n    /* grab the function name or custom error msg first (mutually exclusive) */\n    const char *custommsg;\n    const char *fname = strchr(format, ':');\n    if (fname) {\n        fname++;\n        custommsg = NULL;\n    }\n    else {\n        custommsg = strchr(format,';');\n        if (custommsg) {\n            custommsg++;\n        }\n    }\n\n    int min = INT_MAX;\n    int max = INT_MAX;\n    for (int i = 0; i < total; i++) {\n        if (*format == '|') {\n            if (min != INT_MAX) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Invalid format string (| specified twice)\");\n                return -1;\n            }\n            if (max != INT_MAX) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Invalid format string ($ before |)\");\n                return -1;\n            }\n            min = i;\n            format++;\n        }\n        if (*format == '$') {\n            if (max != INT_MAX) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Invalid format string ($ specified twice)\");\n                return -1;\n            }\n            if (i < npos) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Empty parameter name after $\");\n                return -1;\n            }\n            max = i;\n            format++;\n        }\n        if (IS_END_OF_FORMAT(*format)) {\n            PyErr_Format(PyExc_SystemError,\n                        \"More keyword list entries (%d) than \"\n                        \"format specifiers (%d)\", total, i);\n            return -1;\n        }\n\n        const char *msg = skipitem(&format, NULL, 0);\n        if (msg) {\n            PyErr_Format(PyExc_SystemError, \"%s: '%s'\", msg,\n                        format);\n            return -1;\n        }\n    }\n    min = Py_MIN(min, total);\n    max = Py_MIN(max, total);\n\n    if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) {\n        PyErr_Format(PyExc_SystemError,\n            \"more argument specifiers than keyword list entries \"\n            \"(remaining format:'%s')\", format);\n        return -1;\n    }\n\n    *pfname = fname;\n    *pcustommsg = custommsg;\n    *pmin = min;\n    *pmax = max;\n    return 0;\n}\n\nstatic PyObject *\nnew_kwtuple(const char * const *keywords, int total, int pos)\n{\n    int nkw = total - pos;\n    PyObject *kwtuple = PyTuple_New(nkw);\n    if (kwtuple == NULL) {\n        return NULL;\n    }\n    keywords += pos;\n    for (int i = 0; i < nkw; i++) {\n        PyObject *str = PyUnicode_FromString(keywords[i]);\n        if (str == NULL) {\n            Py_DECREF(kwtuple);\n            return NULL;\n        }\n        PyUnicode_InternInPlace(&str);\n        PyTuple_SET_ITEM(kwtuple, i, str);\n    }\n    return kwtuple;\n}\n\nstatic int\n_parser_init(struct _PyArg_Parser *parser)\n{\n    const char * const *keywords = parser->keywords;\n    assert(keywords != NULL);\n    assert(parser->pos == 0 &&\n           (parser->format == NULL || parser->fname == NULL) &&\n           parser->custom_msg == NULL &&\n           parser->min == 0 &&\n           parser->max == 0);\n\n    int len, pos;\n    if (scan_keywords(keywords, &len, &pos) < 0) {\n        return 0;\n    }\n\n    const char *fname, *custommsg = NULL;\n    int min = 0, max = 0;\n    if (parser->format) {\n        assert(parser->fname == NULL);\n        if (parse_format(parser->format, len, pos,\n                         &fname, &custommsg, &min, &max) < 0) {\n            return 0;\n        }\n    }\n    else {\n        assert(parser->fname != NULL);\n        fname = parser->fname;\n    }\n\n    int owned;\n    PyObject *kwtuple = parser->kwtuple;\n    if (kwtuple == NULL) {\n        kwtuple = new_kwtuple(keywords, len, pos);\n        if (kwtuple == NULL) {\n            return 0;\n        }\n        owned = 1;\n    }\n    else {\n        owned = 0;\n    }\n\n    parser->pos = pos;\n    parser->fname = fname;\n    parser->custom_msg = custommsg;\n    parser->min = min;\n    parser->max = max;\n    parser->kwtuple = kwtuple;\n    parser->initialized = owned ? 1 : -1;\n\n    assert(parser->next == NULL);\n    parser->next = _PyRuntime.getargs.static_parsers;\n    _PyRuntime.getargs.static_parsers = parser;\n    return 1;\n}\n\nstatic int\nparser_init(struct _PyArg_Parser *parser)\n{\n    // volatile as it can be modified by other threads\n    // and should not be optimized or reordered by compiler\n    if (*((volatile int *)&parser->initialized)) {\n        assert(parser->kwtuple != NULL);\n        return 1;\n    }\n    PyThread_acquire_lock(_PyRuntime.getargs.mutex, WAIT_LOCK);\n    // Check again if another thread initialized the parser\n    // while we were waiting for the lock.\n    if (*((volatile int *)&parser->initialized)) {\n        assert(parser->kwtuple != NULL);\n        PyThread_release_lock(_PyRuntime.getargs.mutex);\n        return 1;\n    }\n    int ret = _parser_init(parser);\n    PyThread_release_lock(_PyRuntime.getargs.mutex);\n    return ret;\n}\n\nstatic void\nparser_clear(struct _PyArg_Parser *parser)\n{\n    if (parser->initialized == 1) {\n        Py_CLEAR(parser->kwtuple);\n    }\n}\n\nstatic PyObject*\nfind_keyword(PyObject *kwnames, PyObject *const *kwstack, PyObject *key)\n{\n    Py_ssize_t i, nkwargs;\n\n    nkwargs = PyTuple_GET_SIZE(kwnames);\n    for (i = 0; i < nkwargs; i++) {\n        PyObject *kwname = PyTuple_GET_ITEM(kwnames, i);\n\n        /* kwname == key will normally find a match in since keyword keys\n           should be interned strings; if not retry below in a new loop. */\n        if (kwname == key) {\n            return kwstack[i];\n        }\n    }\n\n    for (i = 0; i < nkwargs; i++) {\n        PyObject *kwname = PyTuple_GET_ITEM(kwnames, i);\n        assert(PyUnicode_Check(kwname));\n        if (_PyUnicode_EQ(kwname, key)) {\n            return kwstack[i];\n        }\n    }\n    return NULL;\n}\n\nstatic int\nvgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,\n                          PyObject *kwargs, PyObject *kwnames,\n                          struct _PyArg_Parser *parser,\n                          va_list *p_va, int flags)\n{\n    PyObject *kwtuple;\n    char msgbuf[512];\n    int levels[32];\n    const char *format;\n    const char *msg;\n    PyObject *keyword;\n    int i, pos, len;\n    Py_ssize_t nkwargs;\n    PyObject *current_arg;\n    freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];\n    freelist_t freelist;\n    PyObject *const *kwstack = NULL;\n\n    freelist.entries = static_entries;\n    freelist.first_available = 0;\n    freelist.entries_malloced = 0;\n\n    assert(kwargs == NULL || PyDict_Check(kwargs));\n    assert(kwargs == NULL || kwnames == NULL);\n    assert(p_va != NULL);\n\n    if (parser == NULL) {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    if (kwnames != NULL && !PyTuple_Check(kwnames)) {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    if (!parser_init(parser)) {\n        return 0;\n    }\n\n    kwtuple = parser->kwtuple;\n    pos = parser->pos;\n    len = pos + (int)PyTuple_GET_SIZE(kwtuple);\n\n    if (len > STATIC_FREELIST_ENTRIES) {\n        freelist.entries = PyMem_NEW(freelistentry_t, len);\n        if (freelist.entries == NULL) {\n            PyErr_NoMemory();\n            return 0;\n        }\n        freelist.entries_malloced = 1;\n    }\n\n    if (kwargs != NULL) {\n        nkwargs = PyDict_GET_SIZE(kwargs);\n    }\n    else if (kwnames != NULL) {\n        nkwargs = PyTuple_GET_SIZE(kwnames);\n        kwstack = args + nargs;\n    }\n    else {\n        nkwargs = 0;\n    }\n    if (nargs + nkwargs > len) {\n        /* Adding \"keyword\" (when nargs == 0) prevents producing wrong error\n           messages in some special cases (see bpo-31229). */\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s%s takes at most %d %sargument%s (%zd given)\",\n                     (parser->fname == NULL) ? \"function\" : parser->fname,\n                     (parser->fname == NULL) ? \"\" : \"()\",\n                     len,\n                     (nargs == 0) ? \"keyword \" : \"\",\n                     (len == 1) ? \"\" : \"s\",\n                     nargs + nkwargs);\n        return cleanreturn(0, &freelist);\n    }\n    if (parser->max < nargs) {\n        if (parser->max == 0) {\n            PyErr_Format(PyExc_TypeError,\n                         \"%.200s%s takes no positional arguments\",\n                         (parser->fname == NULL) ? \"function\" : parser->fname,\n                         (parser->fname == NULL) ? \"\" : \"()\");\n        }\n        else {\n            PyErr_Format(PyExc_TypeError,\n                         \"%.200s%s takes %s %d positional argument%s (%zd given)\",\n                         (parser->fname == NULL) ? \"function\" : parser->fname,\n                         (parser->fname == NULL) ? \"\" : \"()\",\n                         (parser->min < parser->max) ? \"at most\" : \"exactly\",\n                         parser->max,\n                         parser->max == 1 ? \"\" : \"s\",\n                         nargs);\n        }\n        return cleanreturn(0, &freelist);\n    }\n\n    format = parser->format;\n    assert(format != NULL || len == 0);\n    /* convert tuple args and keyword args in same loop, using kwtuple to drive process */\n    for (i = 0; i < len; i++) {\n        if (*format == '|') {\n            format++;\n        }\n        if (*format == '$') {\n            format++;\n        }\n        assert(!IS_END_OF_FORMAT(*format));\n\n        if (i < nargs) {\n            current_arg = args[i];\n        }\n        else if (nkwargs && i >= pos) {\n            keyword = PyTuple_GET_ITEM(kwtuple, i - pos);\n            if (kwargs != NULL) {\n                current_arg = PyDict_GetItemWithError(kwargs, keyword);\n                if (!current_arg && PyErr_Occurred()) {\n                    return cleanreturn(0, &freelist);\n                }\n            }\n            else {\n                current_arg = find_keyword(kwnames, kwstack, keyword);\n            }\n            if (current_arg) {\n                --nkwargs;\n            }\n        }\n        else {\n            current_arg = NULL;\n        }\n\n        if (current_arg) {\n            msg = convertitem(current_arg, &format, p_va, flags,\n                levels, msgbuf, sizeof(msgbuf), &freelist);\n            if (msg) {\n                seterror(i+1, msg, levels, parser->fname, parser->custom_msg);\n                return cleanreturn(0, &freelist);\n            }\n            continue;\n        }\n\n        if (i < parser->min) {\n            /* Less arguments than required */\n            if (i < pos) {\n                Py_ssize_t min = Py_MIN(pos, parser->min);\n                PyErr_Format(PyExc_TypeError,\n                             \"%.200s%s takes %s %d positional argument%s\"\n                             \" (%zd given)\",\n                             (parser->fname == NULL) ? \"function\" : parser->fname,\n                             (parser->fname == NULL) ? \"\" : \"()\",\n                             min < parser->max ? \"at least\" : \"exactly\",\n                             min,\n                             min == 1 ? \"\" : \"s\",\n                             nargs);\n            }\n            else {\n                keyword = PyTuple_GET_ITEM(kwtuple, i - pos);\n                PyErr_Format(PyExc_TypeError,  \"%.200s%s missing required \"\n                             \"argument '%U' (pos %d)\",\n                             (parser->fname == NULL) ? \"function\" : parser->fname,\n                             (parser->fname == NULL) ? \"\" : \"()\",\n                             keyword, i+1);\n            }\n            return cleanreturn(0, &freelist);\n        }\n        /* current code reports success when all required args\n         * fulfilled and no keyword args left, with no further\n         * validation. XXX Maybe skip this in debug build ?\n         */\n        if (!nkwargs) {\n            return cleanreturn(1, &freelist);\n        }\n\n        /* We are into optional args, skip through to any remaining\n         * keyword args */\n        msg = skipitem(&format, p_va, flags);\n        assert(msg == NULL);\n    }\n\n    assert(IS_END_OF_FORMAT(*format) || (*format == '|') || (*format == '$'));\n\n    if (nkwargs > 0) {\n        /* make sure there are no arguments given by name and position */\n        for (i = pos; i < nargs; i++) {\n            keyword = PyTuple_GET_ITEM(kwtuple, i - pos);\n            if (kwargs != NULL) {\n                current_arg = PyDict_GetItemWithError(kwargs, keyword);\n                if (!current_arg && PyErr_Occurred()) {\n                    return cleanreturn(0, &freelist);\n                }\n            }\n            else {\n                current_arg = find_keyword(kwnames, kwstack, keyword);\n            }\n            if (current_arg) {\n                /* arg present in tuple and in dict */\n                PyErr_Format(PyExc_TypeError,\n                             \"argument for %.200s%s given by name ('%U') \"\n                             \"and position (%d)\",\n                             (parser->fname == NULL) ? \"function\" : parser->fname,\n                             (parser->fname == NULL) ? \"\" : \"()\",\n                             keyword, i+1);\n                return cleanreturn(0, &freelist);\n            }\n        }\n\n        error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname);\n        return cleanreturn(0, &freelist);\n    }\n\n    return cleanreturn(1, &freelist);\n}\n\nstatic int\nvgetargskeywordsfast(PyObject *args, PyObject *keywords,\n                     struct _PyArg_Parser *parser, va_list *p_va, int flags)\n{\n    PyObject **stack;\n    Py_ssize_t nargs;\n\n    if (args == NULL\n        || !PyTuple_Check(args)\n        || (keywords != NULL && !PyDict_Check(keywords)))\n    {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    stack = _PyTuple_ITEMS(args);\n    nargs = PyTuple_GET_SIZE(args);\n    return vgetargskeywordsfast_impl(stack, nargs, keywords, NULL,\n                                     parser, p_va, flags);\n}\n\n\n#undef _PyArg_UnpackKeywords\n\nPyObject * const *\n_PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,\n                      PyObject *kwargs, PyObject *kwnames,\n                      struct _PyArg_Parser *parser,\n                      int minpos, int maxpos, int minkw,\n                      PyObject **buf)\n{\n    PyObject *kwtuple;\n    PyObject *keyword;\n    int i, posonly, minposonly, maxargs;\n    int reqlimit = minkw ? maxpos + minkw : minpos;\n    Py_ssize_t nkwargs;\n    PyObject *current_arg;\n    PyObject * const *kwstack = NULL;\n\n    assert(kwargs == NULL || PyDict_Check(kwargs));\n    assert(kwargs == NULL || kwnames == NULL);\n\n    if (parser == NULL) {\n        PyErr_BadInternalCall();\n        return NULL;\n    }\n\n    if (kwnames != NULL && !PyTuple_Check(kwnames)) {\n        PyErr_BadInternalCall();\n        return NULL;\n    }\n\n    if (args == NULL && nargs == 0) {\n        args = buf;\n    }\n\n    if (!parser_init(parser)) {\n        return NULL;\n    }\n\n    kwtuple = parser->kwtuple;\n    posonly = parser->pos;\n    minposonly = Py_MIN(posonly, minpos);\n    maxargs = posonly + (int)PyTuple_GET_SIZE(kwtuple);\n\n    if (kwargs != NULL) {\n        nkwargs = PyDict_GET_SIZE(kwargs);\n    }\n    else if (kwnames != NULL) {\n        nkwargs = PyTuple_GET_SIZE(kwnames);\n        kwstack = args + nargs;\n    }\n    else {\n        nkwargs = 0;\n    }\n    if (nkwargs == 0 && minkw == 0 && minpos <= nargs && nargs <= maxpos) {\n        /* Fast path. */\n        return args;\n    }\n    if (nargs + nkwargs > maxargs) {\n        /* Adding \"keyword\" (when nargs == 0) prevents producing wrong error\n           messages in some special cases (see bpo-31229). */\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s%s takes at most %d %sargument%s (%zd given)\",\n                     (parser->fname == NULL) ? \"function\" : parser->fname,\n                     (parser->fname == NULL) ? \"\" : \"()\",\n                     maxargs,\n                     (nargs == 0) ? \"keyword \" : \"\",\n                     (maxargs == 1) ? \"\" : \"s\",\n                     nargs + nkwargs);\n        return NULL;\n    }\n    if (nargs > maxpos) {\n        if (maxpos == 0) {\n            PyErr_Format(PyExc_TypeError,\n                         \"%.200s%s takes no positional arguments\",\n                         (parser->fname == NULL) ? \"function\" : parser->fname,\n                         (parser->fname == NULL) ? \"\" : \"()\");\n        }\n        else {\n            PyErr_Format(PyExc_TypeError,\n                         \"%.200s%s takes %s %d positional argument%s (%zd given)\",\n                         (parser->fname == NULL) ? \"function\" : parser->fname,\n                         (parser->fname == NULL) ? \"\" : \"()\",\n                         (minpos < maxpos) ? \"at most\" : \"exactly\",\n                         maxpos,\n                         (maxpos == 1) ? \"\" : \"s\",\n                         nargs);\n        }\n        return NULL;\n    }\n    if (nargs < minposonly) {\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s%s takes %s %d positional argument%s\"\n                     \" (%zd given)\",\n                     (parser->fname == NULL) ? \"function\" : parser->fname,\n                     (parser->fname == NULL) ? \"\" : \"()\",\n                     minposonly < maxpos ? \"at least\" : \"exactly\",\n                     minposonly,\n                     minposonly == 1 ? \"\" : \"s\",\n                     nargs);\n        return NULL;\n    }\n\n    /* copy tuple args */\n    for (i = 0; i < nargs; i++) {\n        buf[i] = args[i];\n    }\n\n    /* copy keyword args using kwtuple to drive process */\n    for (i = Py_MAX((int)nargs, posonly); i < maxargs; i++) {\n        if (nkwargs) {\n            keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);\n            if (kwargs != NULL) {\n                current_arg = PyDict_GetItemWithError(kwargs, keyword);\n                if (!current_arg && PyErr_Occurred()) {\n                    return NULL;\n                }\n            }\n            else {\n                current_arg = find_keyword(kwnames, kwstack, keyword);\n            }\n        }\n        else if (i >= reqlimit) {\n            break;\n        }\n        else {\n            current_arg = NULL;\n        }\n\n        buf[i] = current_arg;\n\n        if (current_arg) {\n            --nkwargs;\n        }\n        else if (i < minpos || (maxpos <= i && i < reqlimit)) {\n            /* Less arguments than required */\n            keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);\n            PyErr_Format(PyExc_TypeError,  \"%.200s%s missing required \"\n                         \"argument '%U' (pos %d)\",\n                         (parser->fname == NULL) ? \"function\" : parser->fname,\n                         (parser->fname == NULL) ? \"\" : \"()\",\n                         keyword, i+1);\n            return NULL;\n        }\n    }\n\n    if (nkwargs > 0) {\n        /* make sure there are no arguments given by name and position */\n        for (i = posonly; i < nargs; i++) {\n            keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);\n            if (kwargs != NULL) {\n                current_arg = PyDict_GetItemWithError(kwargs, keyword);\n                if (!current_arg && PyErr_Occurred()) {\n                    return NULL;\n                }\n            }\n            else {\n                current_arg = find_keyword(kwnames, kwstack, keyword);\n            }\n            if (current_arg) {\n                /* arg present in tuple and in dict */\n                PyErr_Format(PyExc_TypeError,\n                             \"argument for %.200s%s given by name ('%U') \"\n                             \"and position (%d)\",\n                             (parser->fname == NULL) ? \"function\" : parser->fname,\n                             (parser->fname == NULL) ? \"\" : \"()\",\n                             keyword, i+1);\n                return NULL;\n            }\n        }\n\n        error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname);\n        return NULL;\n    }\n\n    return buf;\n}\n\nPyObject * const *\n_PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs,\n                                PyObject *kwargs, PyObject *kwnames,\n                                struct _PyArg_Parser *parser,\n                                int minpos, int maxpos, int minkw,\n                                int vararg, PyObject **buf)\n{\n    PyObject *kwtuple;\n    PyObject *keyword;\n    Py_ssize_t varargssize = 0;\n    int i, posonly, minposonly, maxargs;\n    int reqlimit = minkw ? maxpos + minkw : minpos;\n    Py_ssize_t nkwargs;\n    PyObject *current_arg;\n    PyObject * const *kwstack = NULL;\n\n    assert(kwargs == NULL || PyDict_Check(kwargs));\n    assert(kwargs == NULL || kwnames == NULL);\n\n    if (parser == NULL) {\n        PyErr_BadInternalCall();\n        return NULL;\n    }\n\n    if (kwnames != NULL && !PyTuple_Check(kwnames)) {\n        PyErr_BadInternalCall();\n        return NULL;\n    }\n\n    if (args == NULL && nargs == 0) {\n        args = buf;\n    }\n\n    if (!parser_init(parser)) {\n        return NULL;\n    }\n\n    kwtuple = parser->kwtuple;\n    posonly = parser->pos;\n    minposonly = Py_MIN(posonly, minpos);\n    maxargs = posonly + (int)PyTuple_GET_SIZE(kwtuple);\n    if (kwargs != NULL) {\n        nkwargs = PyDict_GET_SIZE(kwargs);\n    }\n    else if (kwnames != NULL) {\n        nkwargs = PyTuple_GET_SIZE(kwnames);\n        kwstack = args + nargs;\n    }\n    else {\n        nkwargs = 0;\n    }\n    if (nargs < minposonly) {\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s%s takes %s %d positional argument%s\"\n                     \" (%zd given)\",\n                     (parser->fname == NULL) ? \"function\" : parser->fname,\n                     (parser->fname == NULL) ? \"\" : \"()\",\n                     minposonly < maxpos ? \"at least\" : \"exactly\",\n                     minposonly,\n                     minposonly == 1 ? \"\" : \"s\",\n                     nargs);\n        return NULL;\n    }\n\n    /* create varargs tuple */\n    varargssize = nargs - maxpos;\n    if (varargssize < 0) {\n        varargssize = 0;\n    }\n    buf[vararg] = PyTuple_New(varargssize);\n    if (!buf[vararg]) {\n        return NULL;\n    }\n\n    /* copy tuple args */\n    for (i = 0; i < nargs; i++) {\n        if (i >= vararg) {\n            PyTuple_SET_ITEM(buf[vararg], i - vararg, Py_NewRef(args[i]));\n            continue;\n        }\n        else {\n            buf[i] = args[i];\n        }\n    }\n\n    /* copy keyword args using kwtuple to drive process */\n    for (i = Py_MAX((int)nargs, posonly) -\n         Py_SAFE_DOWNCAST(varargssize, Py_ssize_t, int); i < maxargs; i++) {\n        if (nkwargs) {\n            keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);\n            if (kwargs != NULL) {\n                current_arg = PyDict_GetItemWithError(kwargs, keyword);\n                if (!current_arg && PyErr_Occurred()) {\n                    goto exit;\n                }\n            }\n            else {\n                current_arg = find_keyword(kwnames, kwstack, keyword);\n            }\n        }\n        else {\n            current_arg = NULL;\n        }\n\n        /* If an arguments is passed in as a keyword argument,\n         * it should be placed before `buf[vararg]`.\n         *\n         * For example:\n         * def f(a, /, b, *args):\n         *     pass\n         * f(1, b=2)\n         *\n         * This `buf` array should be: [1, 2, NULL].\n         * In this case, nargs < vararg.\n         *\n         * Otherwise, we leave a place at `buf[vararg]` for vararg tuple\n         * so the index is `i + 1`. */\n        if (nargs < vararg) {\n            buf[i] = current_arg;\n        }\n        else {\n            buf[i + 1] = current_arg;\n        }\n\n        if (current_arg) {\n            --nkwargs;\n        }\n        else if (i < minpos || (maxpos <= i && i < reqlimit)) {\n            /* Less arguments than required */\n            keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);\n            PyErr_Format(PyExc_TypeError,  \"%.200s%s missing required \"\n                         \"argument '%U' (pos %d)\",\n                         (parser->fname == NULL) ? \"function\" : parser->fname,\n                         (parser->fname == NULL) ? \"\" : \"()\",\n                         keyword, i+1);\n            goto exit;\n        }\n    }\n\n    if (nkwargs > 0) {\n        error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname);\n        goto exit;\n    }\n\n    return buf;\n\nexit:\n    Py_XDECREF(buf[vararg]);\n    return NULL;\n}\n\n\nstatic const char *\nskipitem(const char **p_format, va_list *p_va, int flags)\n{\n    const char *format = *p_format;\n    char c = *format++;\n\n    switch (c) {\n\n    /*\n     * codes that take a single data pointer as an argument\n     * (the type of the pointer is irrelevant)\n     */\n\n    case 'b': /* byte -- very short int */\n    case 'B': /* byte as bitfield */\n    case 'h': /* short int */\n    case 'H': /* short int as bitfield */\n    case 'i': /* int */\n    case 'I': /* int sized bitfield */\n    case 'l': /* long int */\n    case 'k': /* long int sized bitfield */\n    case 'L': /* long long */\n    case 'K': /* long long sized bitfield */\n    case 'n': /* Py_ssize_t */\n    case 'f': /* float */\n    case 'd': /* double */\n    case 'D': /* complex double */\n    case 'c': /* char */\n    case 'C': /* unicode char */\n    case 'p': /* boolean predicate */\n    case 'S': /* string object */\n    case 'Y': /* string object */\n    case 'U': /* unicode string object */\n        {\n            if (p_va != NULL) {\n                (void) va_arg(*p_va, void *);\n            }\n            break;\n        }\n\n    /* string codes */\n\n    case 'e': /* string with encoding */\n        {\n            if (p_va != NULL) {\n                (void) va_arg(*p_va, const char *);\n            }\n            if (!(*format == 's' || *format == 't'))\n                /* after 'e', only 's' and 't' is allowed */\n                goto err;\n            format++;\n        }\n        /* fall through */\n\n    case 's': /* string */\n    case 'z': /* string or None */\n    case 'y': /* bytes */\n    case 'w': /* buffer, read-write */\n        {\n            if (p_va != NULL) {\n                (void) va_arg(*p_va, char **);\n            }\n            if (*format == '#') {\n                if (p_va != NULL) {\n                    (void) va_arg(*p_va, Py_ssize_t *);\n                }\n                format++;\n            } else if ((c == 's' || c == 'z' || c == 'y' || c == 'w')\n                       && *format == '*')\n            {\n                format++;\n            }\n            break;\n        }\n\n    case 'O': /* object */\n        {\n            if (*format == '!') {\n                format++;\n                if (p_va != NULL) {\n                    (void) va_arg(*p_va, PyTypeObject*);\n                    (void) va_arg(*p_va, PyObject **);\n                }\n            }\n            else if (*format == '&') {\n                typedef int (*converter)(PyObject *, void *);\n                if (p_va != NULL) {\n                    (void) va_arg(*p_va, converter);\n                    (void) va_arg(*p_va, void *);\n                }\n                format++;\n            }\n            else {\n                if (p_va != NULL) {\n                    (void) va_arg(*p_va, PyObject **);\n                }\n            }\n            break;\n        }\n\n    case '(':           /* bypass tuple, not handled at all previously */\n        {\n            const char *msg;\n            for (;;) {\n                if (*format==')')\n                    break;\n                if (IS_END_OF_FORMAT(*format))\n                    return \"Unmatched left paren in format \"\n                           \"string\";\n                msg = skipitem(&format, p_va, flags);\n                if (msg)\n                    return msg;\n            }\n            format++;\n            break;\n        }\n\n    case ')':\n        return \"Unmatched right paren in format string\";\n\n    default:\nerr:\n        return \"impossible<bad format char>\";\n\n    }\n\n    *p_format = format;\n    return NULL;\n}\n\n\n#undef _PyArg_CheckPositional\n\nint\n_PyArg_CheckPositional(const char *name, Py_ssize_t nargs,\n                       Py_ssize_t min, Py_ssize_t max)\n{\n    assert(min >= 0);\n    assert(min <= max);\n\n    if (nargs < min) {\n        if (name != NULL)\n            PyErr_Format(\n                PyExc_TypeError,\n                \"%.200s expected %s%zd argument%s, got %zd\",\n                name, (min == max ? \"\" : \"at least \"), min, min == 1 ? \"\" : \"s\", nargs);\n        else\n            PyErr_Format(\n                PyExc_TypeError,\n                \"unpacked tuple should have %s%zd element%s,\"\n                \" but has %zd\",\n                (min == max ? \"\" : \"at least \"), min, min == 1 ? \"\" : \"s\", nargs);\n        return 0;\n    }\n\n    if (nargs == 0) {\n        return 1;\n    }\n\n    if (nargs > max) {\n        if (name != NULL)\n            PyErr_Format(\n                PyExc_TypeError,\n                \"%.200s expected %s%zd argument%s, got %zd\",\n                name, (min == max ? \"\" : \"at most \"), max, max == 1 ? \"\" : \"s\", nargs);\n        else\n            PyErr_Format(\n                PyExc_TypeError,\n                \"unpacked tuple should have %s%zd element%s,\"\n                \" but has %zd\",\n                (min == max ? \"\" : \"at most \"), max, max == 1 ? \"\" : \"s\", nargs);\n        return 0;\n    }\n\n    return 1;\n}\n\nstatic int\nunpack_stack(PyObject *const *args, Py_ssize_t nargs, const char *name,\n             Py_ssize_t min, Py_ssize_t max, va_list vargs)\n{\n    Py_ssize_t i;\n    PyObject **o;\n\n    if (!_PyArg_CheckPositional(name, nargs, min, max)) {\n        return 0;\n    }\n\n    for (i = 0; i < nargs; i++) {\n        o = va_arg(vargs, PyObject **);\n        *o = args[i];\n    }\n    return 1;\n}\n\nint\nPyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...)\n{\n    PyObject **stack;\n    Py_ssize_t nargs;\n    int retval;\n    va_list vargs;\n\n    if (!PyTuple_Check(args)) {\n        PyErr_SetString(PyExc_SystemError,\n            \"PyArg_UnpackTuple() argument list is not a tuple\");\n        return 0;\n    }\n    stack = _PyTuple_ITEMS(args);\n    nargs = PyTuple_GET_SIZE(args);\n\n    va_start(vargs, max);\n    retval = unpack_stack(stack, nargs, name, min, max, vargs);\n    va_end(vargs);\n    return retval;\n}\n\nint\n_PyArg_UnpackStack(PyObject *const *args, Py_ssize_t nargs, const char *name,\n                   Py_ssize_t min, Py_ssize_t max, ...)\n{\n    int retval;\n    va_list vargs;\n\n    va_start(vargs, max);\n    retval = unpack_stack(args, nargs, name, min, max, vargs);\n    va_end(vargs);\n    return retval;\n}\n\n\n#undef _PyArg_NoKeywords\n#undef _PyArg_NoKwnames\n#undef _PyArg_NoPositional\n\n/* For type constructors that don't take keyword args\n *\n * Sets a TypeError and returns 0 if the args/kwargs is\n * not empty, returns 1 otherwise\n */\nint\n_PyArg_NoKeywords(const char *funcname, PyObject *kwargs)\n{\n    if (kwargs == NULL) {\n        return 1;\n    }\n    if (!PyDict_CheckExact(kwargs)) {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n    if (PyDict_GET_SIZE(kwargs) == 0) {\n        return 1;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"%.200s() takes no keyword arguments\",\n                    funcname);\n    return 0;\n}\n\nint\n_PyArg_NoPositional(const char *funcname, PyObject *args)\n{\n    if (args == NULL)\n        return 1;\n    if (!PyTuple_CheckExact(args)) {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n    if (PyTuple_GET_SIZE(args) == 0)\n        return 1;\n\n    PyErr_Format(PyExc_TypeError, \"%.200s() takes no positional arguments\",\n                    funcname);\n    return 0;\n}\n\nint\n_PyArg_NoKwnames(const char *funcname, PyObject *kwnames)\n{\n    if (kwnames == NULL) {\n        return 1;\n    }\n\n    assert(PyTuple_CheckExact(kwnames));\n\n    if (PyTuple_GET_SIZE(kwnames) == 0) {\n        return 1;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"%s() takes no keyword arguments\", funcname);\n    return 0;\n}\n\nvoid\n_PyArg_Fini(void)\n{\n    struct _PyArg_Parser *tmp, *s = _PyRuntime.getargs.static_parsers;\n    while (s) {\n        tmp = s->next;\n        s->next = NULL;\n        parser_clear(s);\n        s = tmp;\n    }\n    _PyRuntime.getargs.static_parsers = NULL;\n}\n\n#ifdef __cplusplus\n};\n#endif\n"
  },
  {
    "path": "Generated_Cases.c.h",
    "content": "// This file is generated by Tools/cases_generator/generate_cases.py\n// from:\n//   Python/bytecodes.c\n// Do not edit!\n\n        TARGET(NOP) {\n            DISPATCH();\n        }\n\n        TARGET(RESUME) {\n            #line 138 \"Python/bytecodes.c\"\n            assert(tstate->cframe == &cframe);\n            assert(frame == cframe.current_frame);\n            /* Possibly combine this with eval breaker */\n            if (frame->f_code->_co_instrumentation_version != tstate->interp->monitoring_version) {\n                int err = _Py_Instrument(frame->f_code, tstate->interp);\n                if (err) goto error;\n                next_instr--;\n            }\n            else if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker) && oparg < 2) {\n                goto handle_eval_breaker;\n            }\n            #line 24 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_RESUME) {\n            #line 152 \"Python/bytecodes.c\"\n            /* Possible performance enhancement:\n             *   We need to check the eval breaker anyway, can we\n             * combine the instrument verison check and the eval breaker test?\n             */\n            if (frame->f_code->_co_instrumentation_version != tstate->interp->monitoring_version) {\n                if (_Py_Instrument(frame->f_code, tstate->interp)) {\n                    goto error;\n                }\n                next_instr--;\n            }\n            else {\n                _PyFrame_SetStackPointer(frame, stack_pointer);\n                int err = _Py_call_instrumentation(\n                        tstate, oparg > 0, frame, next_instr-1);\n                stack_pointer = _PyFrame_GetStackPointer(frame);\n                if (err) goto error;\n                if (frame->prev_instr != next_instr-1) {\n                    /* Instrumentation has jumped */\n                    next_instr = frame->prev_instr;\n                    DISPATCH();\n                }\n                if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker) && oparg < 2) {\n                    goto handle_eval_breaker;\n                }\n            }\n            #line 55 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(LOAD_CLOSURE) {\n            PyObject *value;\n            #line 180 \"Python/bytecodes.c\"\n            /* We keep LOAD_CLOSURE so that the bytecode stays more readable. */\n            value = GETLOCAL(oparg);\n            if (value == NULL) goto unbound_local_error;\n            Py_INCREF(value);\n            #line 66 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = value;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_FAST_CHECK) {\n            PyObject *value;\n            #line 187 \"Python/bytecodes.c\"\n            value = GETLOCAL(oparg);\n            if (value == NULL) goto unbound_local_error;\n            Py_INCREF(value);\n            #line 78 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = value;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_FAST) {\n            PyObject *value;\n            #line 193 \"Python/bytecodes.c\"\n            value = GETLOCAL(oparg);\n            assert(value != NULL);\n            Py_INCREF(value);\n            #line 90 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = value;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_FAST_AND_CLEAR) {\n            PyObject *value;\n            #line 199 \"Python/bytecodes.c\"\n            value = GETLOCAL(oparg);\n            // do not use SETLOCAL here, it decrefs the old value\n            GETLOCAL(oparg) = NULL;\n            #line 102 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = value;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_FAST_LOAD_FAST) {\n            PyObject *value1;\n            PyObject *value2;\n            #line 205 \"Python/bytecodes.c\"\n            uint32_t oparg1 = oparg >> 4;\n            uint32_t oparg2 = oparg & 15;\n            value1 = GETLOCAL(oparg1);\n            value2 = GETLOCAL(oparg2);\n            Py_INCREF(value1);\n            Py_INCREF(value2);\n            #line 118 \"Python/generated_cases.c.h\"\n            STACK_GROW(2);\n            stack_pointer[-1] = value2;\n            stack_pointer[-2] = value1;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_CONST) {\n            PyObject *value;\n            #line 214 \"Python/bytecodes.c\"\n            value = GETITEM(frame->f_code->co_consts, oparg);\n            Py_INCREF(value);\n            #line 130 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = value;\n            DISPATCH();\n        }\n\n        TARGET(STORE_FAST) {\n            PyObject *value = stack_pointer[-1];\n            #line 219 \"Python/bytecodes.c\"\n            SETLOCAL(oparg, value);\n            #line 140 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(STORE_FAST_LOAD_FAST) {\n            PyObject *value1 = stack_pointer[-1];\n            PyObject *value2;\n            #line 227 \"Python/bytecodes.c\"\n            uint32_t oparg1 = oparg >> 4;\n            uint32_t oparg2 = oparg & 15;\n            SETLOCAL(oparg1, value1);\n            value2 = GETLOCAL(oparg2);\n            Py_INCREF(value2);\n            #line 154 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = value2;\n            DISPATCH();\n        }\n\n        TARGET(STORE_FAST_STORE_FAST) {\n            PyObject *value1 = stack_pointer[-1];\n            PyObject *value2 = stack_pointer[-2];\n            #line 235 \"Python/bytecodes.c\"\n            uint32_t oparg1 = oparg >> 4;\n            uint32_t oparg2 = oparg & 15;\n            SETLOCAL(oparg1, value1);\n            SETLOCAL(oparg2, value2);\n            #line 167 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(2);\n            DISPATCH();\n        }\n\n        TARGET(POP_TOP) {\n            PyObject *value = stack_pointer[-1];\n            #line 242 \"Python/bytecodes.c\"\n            #line 175 \"Python/generated_cases.c.h\"\n            Py_DECREF(value);\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(PUSH_NULL) {\n            PyObject *res;\n            #line 246 \"Python/bytecodes.c\"\n            res = NULL;\n            #line 185 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = res;\n            DISPATCH();\n        }\n\n        TARGET(END_FOR) {\n            PyObject *_tmp_1 = stack_pointer[-1];\n            PyObject *_tmp_2 = stack_pointer[-2];\n            {\n                PyObject *value = _tmp_1;\n                #line 242 \"Python/bytecodes.c\"\n                #line 197 \"Python/generated_cases.c.h\"\n                Py_DECREF(value);\n            }\n            {\n                PyObject *value = _tmp_2;\n                #line 242 \"Python/bytecodes.c\"\n                #line 203 \"Python/generated_cases.c.h\"\n                Py_DECREF(value);\n            }\n            STACK_SHRINK(2);\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_END_FOR) {\n            PyObject *value = stack_pointer[-1];\n            PyObject *receiver = stack_pointer[-2];\n            #line 252 \"Python/bytecodes.c\"\n            /* Need to create a fake StopIteration error here,\n             * to conform to PEP 380 */\n            if (PyGen_Check(receiver)) {\n                PyErr_SetObject(PyExc_StopIteration, value);\n                if (monitor_stop_iteration(tstate, frame, next_instr-1)) {\n                    goto error;\n                }\n                PyErr_SetRaisedException(NULL);\n            }\n            #line 223 \"Python/generated_cases.c.h\"\n            Py_DECREF(receiver);\n            Py_DECREF(value);\n            STACK_SHRINK(2);\n            DISPATCH();\n        }\n\n        TARGET(END_SEND) {\n            PyObject *value = stack_pointer[-1];\n            PyObject *receiver = stack_pointer[-2];\n            #line 265 \"Python/bytecodes.c\"\n            Py_DECREF(receiver);\n            #line 235 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = value;\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_END_SEND) {\n            PyObject *value = stack_pointer[-1];\n            PyObject *receiver = stack_pointer[-2];\n            #line 269 \"Python/bytecodes.c\"\n            if (PyGen_Check(receiver) || PyCoro_CheckExact(receiver)) {\n                PyErr_SetObject(PyExc_StopIteration, value);\n                if (monitor_stop_iteration(tstate, frame, next_instr-1)) {\n                    goto error;\n                }\n                PyErr_SetRaisedException(NULL);\n            }\n            Py_DECREF(receiver);\n            #line 253 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = value;\n            DISPATCH();\n        }\n\n        TARGET(UNARY_NEGATIVE) {\n            PyObject *value = stack_pointer[-1];\n            PyObject *res;\n            #line 280 \"Python/bytecodes.c\"\n            res = PyNumber_Negative(value);\n            #line 264 \"Python/generated_cases.c.h\"\n            Py_DECREF(value);\n            #line 282 \"Python/bytecodes.c\"\n            if (res == NULL) goto pop_1_error;\n            #line 268 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = res;\n            DISPATCH();\n        }\n\n        TARGET(UNARY_NOT) {\n            PyObject *value = stack_pointer[-1];\n            PyObject *res;\n            #line 286 \"Python/bytecodes.c\"\n            int err = PyObject_IsTrue(value);\n            #line 278 \"Python/generated_cases.c.h\"\n            Py_DECREF(value);\n            #line 288 \"Python/bytecodes.c\"\n            if (err < 0) goto pop_1_error;\n            if (err == 0) {\n                res = Py_True;\n            }\n            else {\n                res = Py_False;\n            }\n            #line 288 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = res;\n            DISPATCH();\n        }\n\n        TARGET(UNARY_INVERT) {\n            PyObject *value = stack_pointer[-1];\n            PyObject *res;\n            #line 298 \"Python/bytecodes.c\"\n            res = PyNumber_Invert(value);\n            #line 298 \"Python/generated_cases.c.h\"\n            Py_DECREF(value);\n            #line 300 \"Python/bytecodes.c\"\n            if (res == NULL) goto pop_1_error;\n            #line 302 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = res;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_OP_MULTIPLY_INT) {\n            PyObject *_tmp_1 = stack_pointer[-1];\n            PyObject *_tmp_2 = stack_pointer[-2];\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                #line 316 \"Python/bytecodes.c\"\n                DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);\n                DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);\n                #line 316 \"Python/generated_cases.c.h\"\n                _tmp_2 = left;\n                _tmp_1 = right;\n            }\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                PyObject *res;\n                #line 321 \"Python/bytecodes.c\"\n                STAT_INC(BINARY_OP, hit);\n                res = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right);\n                _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);\n                _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);\n                if (res == NULL) goto pop_2_error;\n                #line 330 \"Python/generated_cases.c.h\"\n                _tmp_2 = res;\n            }\n            next_instr += 1;\n            STACK_SHRINK(1);\n            stack_pointer[-1] = _tmp_2;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_OP_ADD_INT) {\n            PyObject *_tmp_1 = stack_pointer[-1];\n            PyObject *_tmp_2 = stack_pointer[-2];\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                #line 316 \"Python/bytecodes.c\"\n                DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);\n                DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);\n                #line 348 \"Python/generated_cases.c.h\"\n                _tmp_2 = left;\n                _tmp_1 = right;\n            }\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                PyObject *res;\n                #line 329 \"Python/bytecodes.c\"\n                STAT_INC(BINARY_OP, hit);\n                res = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right);\n                _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);\n                _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);\n                if (res == NULL) goto pop_2_error;\n                #line 362 \"Python/generated_cases.c.h\"\n                _tmp_2 = res;\n            }\n            next_instr += 1;\n            STACK_SHRINK(1);\n            stack_pointer[-1] = _tmp_2;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_OP_SUBTRACT_INT) {\n            PyObject *_tmp_1 = stack_pointer[-1];\n            PyObject *_tmp_2 = stack_pointer[-2];\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                #line 316 \"Python/bytecodes.c\"\n                DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);\n                DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);\n                #line 380 \"Python/generated_cases.c.h\"\n                _tmp_2 = left;\n                _tmp_1 = right;\n            }\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                PyObject *res;\n                #line 337 \"Python/bytecodes.c\"\n                STAT_INC(BINARY_OP, hit);\n                res = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);\n                _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);\n                _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);\n                if (res == NULL) goto pop_2_error;\n                #line 394 \"Python/generated_cases.c.h\"\n                _tmp_2 = res;\n            }\n            next_instr += 1;\n            STACK_SHRINK(1);\n            stack_pointer[-1] = _tmp_2;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_OP_MULTIPLY_FLOAT) {\n            PyObject *_tmp_1 = stack_pointer[-1];\n            PyObject *_tmp_2 = stack_pointer[-2];\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                #line 352 \"Python/bytecodes.c\"\n                DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);\n                DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);\n                #line 412 \"Python/generated_cases.c.h\"\n                _tmp_2 = left;\n                _tmp_1 = right;\n            }\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                PyObject *res;\n                #line 357 \"Python/bytecodes.c\"\n                STAT_INC(BINARY_OP, hit);\n                double dres =\n                    ((PyFloatObject *)left)->ob_fval *\n                    ((PyFloatObject *)right)->ob_fval;\n                DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);\n                #line 426 \"Python/generated_cases.c.h\"\n                _tmp_2 = res;\n            }\n            next_instr += 1;\n            STACK_SHRINK(1);\n            stack_pointer[-1] = _tmp_2;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_OP_ADD_FLOAT) {\n            PyObject *_tmp_1 = stack_pointer[-1];\n            PyObject *_tmp_2 = stack_pointer[-2];\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                #line 352 \"Python/bytecodes.c\"\n                DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);\n                DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);\n                #line 444 \"Python/generated_cases.c.h\"\n                _tmp_2 = left;\n                _tmp_1 = right;\n            }\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                PyObject *res;\n                #line 365 \"Python/bytecodes.c\"\n                STAT_INC(BINARY_OP, hit);\n                double dres =\n                    ((PyFloatObject *)left)->ob_fval +\n                    ((PyFloatObject *)right)->ob_fval;\n                DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);\n                #line 458 \"Python/generated_cases.c.h\"\n                _tmp_2 = res;\n            }\n            next_instr += 1;\n            STACK_SHRINK(1);\n            stack_pointer[-1] = _tmp_2;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_OP_SUBTRACT_FLOAT) {\n            PyObject *_tmp_1 = stack_pointer[-1];\n            PyObject *_tmp_2 = stack_pointer[-2];\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                #line 352 \"Python/bytecodes.c\"\n                DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);\n                DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);\n                #line 476 \"Python/generated_cases.c.h\"\n                _tmp_2 = left;\n                _tmp_1 = right;\n            }\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                PyObject *res;\n                #line 373 \"Python/bytecodes.c\"\n                STAT_INC(BINARY_OP, hit);\n                double dres =\n                    ((PyFloatObject *)left)->ob_fval -\n                    ((PyFloatObject *)right)->ob_fval;\n                DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);\n                #line 490 \"Python/generated_cases.c.h\"\n                _tmp_2 = res;\n            }\n            next_instr += 1;\n            STACK_SHRINK(1);\n            stack_pointer[-1] = _tmp_2;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_OP_ADD_UNICODE) {\n            PyObject *_tmp_1 = stack_pointer[-1];\n            PyObject *_tmp_2 = stack_pointer[-2];\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                #line 388 \"Python/bytecodes.c\"\n                DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);\n                DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP);\n                #line 508 \"Python/generated_cases.c.h\"\n                _tmp_2 = left;\n                _tmp_1 = right;\n            }\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                PyObject *res;\n                #line 393 \"Python/bytecodes.c\"\n                STAT_INC(BINARY_OP, hit);\n                res = PyUnicode_Concat(left, right);\n                _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);\n                _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);\n                if (res == NULL) goto pop_2_error;\n                #line 522 \"Python/generated_cases.c.h\"\n                _tmp_2 = res;\n            }\n            next_instr += 1;\n            STACK_SHRINK(1);\n            stack_pointer[-1] = _tmp_2;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_OP_INPLACE_ADD_UNICODE) {\n            PyObject *_tmp_1 = stack_pointer[-1];\n            PyObject *_tmp_2 = stack_pointer[-2];\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                #line 388 \"Python/bytecodes.c\"\n                DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);\n                DEOPT_IF(!PyUnicode_CheckExact(right), BINARY_OP);\n                #line 540 \"Python/generated_cases.c.h\"\n                _tmp_2 = left;\n                _tmp_1 = right;\n            }\n            {\n                PyObject *right = _tmp_1;\n                PyObject *left = _tmp_2;\n                #line 410 \"Python/bytecodes.c\"\n                _Py_CODEUNIT true_next = next_instr[INLINE_CACHE_ENTRIES_BINARY_OP];\n                assert(true_next.op.code == STORE_FAST);\n                PyObject **target_local = &GETLOCAL(true_next.op.arg);\n                DEOPT_IF(*target_local != left, BINARY_OP);\n                STAT_INC(BINARY_OP, hit);\n                /* Handle `left = left + right` or `left += right` for str.\n                 *\n                 * When possible, extend `left` in place rather than\n                 * allocating a new PyUnicodeObject. This attempts to avoid\n                 * quadratic behavior when one neglects to use str.join().\n                 *\n                 * If `left` has only two references remaining (one from\n                 * the stack, one in the locals), DECREFing `left` leaves\n                 * only the locals reference, so PyUnicode_Append knows\n                 * that the string is safe to mutate.\n                 */\n                assert(Py_REFCNT(left) >= 2);\n                _Py_DECREF_NO_DEALLOC(left);\n                PyUnicode_Append(target_local, right);\n                _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);\n                if (*target_local == NULL) goto pop_2_error;\n                // The STORE_FAST is already done.\n                JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP + 1);\n                #line 571 \"Python/generated_cases.c.h\"\n            }\n            STACK_SHRINK(2);\n            DISPATCH();\n        }\n\n        TARGET(BINARY_SUBSCR) {\n            PREDICTED(BINARY_SUBSCR);\n            static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, \"incorrect cache size\");\n            PyObject *sub = stack_pointer[-1];\n            PyObject *container = stack_pointer[-2];\n            PyObject *res;\n            #line 447 \"Python/bytecodes.c\"\n            #if ENABLE_SPECIALIZATION\n            _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_BinarySubscr(container, sub, next_instr);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(BINARY_SUBSCR, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            res = PyObject_GetItem(container, sub);\n            #line 595 \"Python/generated_cases.c.h\"\n            Py_DECREF(container);\n            Py_DECREF(sub);\n            #line 459 \"Python/bytecodes.c\"\n            if (res == NULL) goto pop_2_error;\n            #line 600 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_SLICE) {\n            PyObject *stop = stack_pointer[-1];\n            PyObject *start = stack_pointer[-2];\n            PyObject *container = stack_pointer[-3];\n            PyObject *res;\n            #line 463 \"Python/bytecodes.c\"\n            PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop);\n            // Can't use ERROR_IF() here, because we haven't\n            // DECREF'ed container yet, and we still own slice.\n            if (slice == NULL) {\n                res = NULL;\n            }\n            else {\n                res = PyObject_GetItem(container, slice);\n                Py_DECREF(slice);\n            }\n            Py_DECREF(container);\n            if (res == NULL) goto pop_3_error;\n            #line 625 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(2);\n            stack_pointer[-1] = res;\n            DISPATCH();\n        }\n\n        TARGET(STORE_SLICE) {\n            PyObject *stop = stack_pointer[-1];\n            PyObject *start = stack_pointer[-2];\n            PyObject *container = stack_pointer[-3];\n            PyObject *v = stack_pointer[-4];\n            #line 478 \"Python/bytecodes.c\"\n            PyObject *slice = _PyBuildSlice_ConsumeRefs(start, stop);\n            int err;\n            if (slice == NULL) {\n                err = 1;\n            }\n            else {\n                err = PyObject_SetItem(container, slice, v);\n                Py_DECREF(slice);\n            }\n            Py_DECREF(v);\n            Py_DECREF(container);\n            if (err) goto pop_4_error;\n            #line 649 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(4);\n            DISPATCH();\n        }\n\n        TARGET(BINARY_SUBSCR_LIST_INT) {\n            PyObject *sub = stack_pointer[-1];\n            PyObject *list = stack_pointer[-2];\n            PyObject *res;\n            #line 493 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);\n            DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR);\n\n            // Deopt unless 0 <= sub < PyList_Size(list)\n            DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR);\n            Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];\n            DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR);\n            STAT_INC(BINARY_SUBSCR, hit);\n            res = PyList_GET_ITEM(list, index);\n            assert(res != NULL);\n            Py_INCREF(res);\n            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);\n            Py_DECREF(list);\n            #line 672 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_SUBSCR_TUPLE_INT) {\n            PyObject *sub = stack_pointer[-1];\n            PyObject *tuple = stack_pointer[-2];\n            PyObject *res;\n            #line 509 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);\n            DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR);\n\n            // Deopt unless 0 <= sub < PyTuple_Size(list)\n            DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR);\n            Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];\n            DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR);\n            STAT_INC(BINARY_SUBSCR, hit);\n            res = PyTuple_GET_ITEM(tuple, index);\n            assert(res != NULL);\n            Py_INCREF(res);\n            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);\n            Py_DECREF(tuple);\n            #line 697 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_SUBSCR_DICT) {\n            PyObject *sub = stack_pointer[-1];\n            PyObject *dict = stack_pointer[-2];\n            PyObject *res;\n            #line 525 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR);\n            STAT_INC(BINARY_SUBSCR, hit);\n            res = PyDict_GetItemWithError(dict, sub);\n            if (res == NULL) {\n                if (!_PyErr_Occurred(tstate)) {\n                    _PyErr_SetKeyError(sub);\n                }\n            #line 716 \"Python/generated_cases.c.h\"\n                Py_DECREF(dict);\n                Py_DECREF(sub);\n            #line 533 \"Python/bytecodes.c\"\n                if (true) goto pop_2_error;\n            }\n            Py_INCREF(res);  // Do this before DECREF'ing dict, sub\n            #line 723 \"Python/generated_cases.c.h\"\n            Py_DECREF(dict);\n            Py_DECREF(sub);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_SUBSCR_GETITEM) {\n            PyObject *sub = stack_pointer[-1];\n            PyObject *container = stack_pointer[-2];\n            #line 540 \"Python/bytecodes.c\"\n            DEOPT_IF(tstate->interp->eval_frame, BINARY_SUBSCR);\n            PyTypeObject *tp = Py_TYPE(container);\n            DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE), BINARY_SUBSCR);\n            PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;\n            PyObject *cached = ht->_spec_cache.getitem;\n            DEOPT_IF(cached == NULL, BINARY_SUBSCR);\n            assert(PyFunction_Check(cached));\n            PyFunctionObject *getitem = (PyFunctionObject *)cached;\n            uint32_t cached_version = ht->_spec_cache.getitem_version;\n            DEOPT_IF(getitem->func_version != cached_version, BINARY_SUBSCR);\n            PyCodeObject *code = (PyCodeObject *)getitem->func_code;\n            assert(code->co_argcount == 2);\n            DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), BINARY_SUBSCR);\n            STAT_INC(BINARY_SUBSCR, hit);\n            Py_INCREF(getitem);\n            _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2);\n            STACK_SHRINK(2);\n            new_frame->localsplus[0] = container;\n            new_frame->localsplus[1] = sub;\n            JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);\n            frame->return_offset = 0;\n            DISPATCH_INLINED(new_frame);\n            #line 758 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(LIST_APPEND) {\n            PyObject *v = stack_pointer[-1];\n            PyObject *list = stack_pointer[-(2 + (oparg-1))];\n            #line 565 \"Python/bytecodes.c\"\n            if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto pop_1_error;\n            #line 766 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(SET_ADD) {\n            PyObject *v = stack_pointer[-1];\n            PyObject *set = stack_pointer[-(2 + (oparg-1))];\n            #line 569 \"Python/bytecodes.c\"\n            int err = PySet_Add(set, v);\n            #line 776 \"Python/generated_cases.c.h\"\n            Py_DECREF(v);\n            #line 571 \"Python/bytecodes.c\"\n            if (err) goto pop_1_error;\n            #line 780 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(STORE_SUBSCR) {\n            PREDICTED(STORE_SUBSCR);\n            static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, \"incorrect cache size\");\n            PyObject *sub = stack_pointer[-1];\n            PyObject *container = stack_pointer[-2];\n            PyObject *v = stack_pointer[-3];\n            uint16_t counter = read_u16(&next_instr[0].cache);\n            #line 581 \"Python/bytecodes.c\"\n            #if ENABLE_SPECIALIZATION\n            if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {\n                next_instr--;\n                _Py_Specialize_StoreSubscr(container, sub, next_instr);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(STORE_SUBSCR, deferred);\n            _PyStoreSubscrCache *cache = (_PyStoreSubscrCache *)next_instr;\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #else\n            (void)counter;  // Unused.\n            #endif  /* ENABLE_SPECIALIZATION */\n            /* container[sub] = v */\n            int err = PyObject_SetItem(container, sub, v);\n            #line 807 \"Python/generated_cases.c.h\"\n            Py_DECREF(v);\n            Py_DECREF(container);\n            Py_DECREF(sub);\n            #line 596 \"Python/bytecodes.c\"\n            if (err) goto pop_3_error;\n            #line 813 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(3);\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(STORE_SUBSCR_LIST_INT) {\n            PyObject *sub = stack_pointer[-1];\n            PyObject *list = stack_pointer[-2];\n            PyObject *value = stack_pointer[-3];\n            #line 600 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR);\n            DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR);\n\n            // Ensure nonnegative, zero-or-one-digit ints.\n            DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), STORE_SUBSCR);\n            Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];\n            // Ensure index < len(list)\n            DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR);\n            STAT_INC(STORE_SUBSCR, hit);\n\n            PyObject *old_value = PyList_GET_ITEM(list, index);\n            PyList_SET_ITEM(list, index, value);\n            assert(old_value != NULL);\n            Py_DECREF(old_value);\n            _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);\n            Py_DECREF(list);\n            #line 840 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(3);\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(STORE_SUBSCR_DICT) {\n            PyObject *sub = stack_pointer[-1];\n            PyObject *dict = stack_pointer[-2];\n            PyObject *value = stack_pointer[-3];\n            #line 619 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR);\n            STAT_INC(STORE_SUBSCR, hit);\n            int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value);\n            Py_DECREF(dict);\n            if (err) goto pop_3_error;\n            #line 856 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(3);\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(DELETE_SUBSCR) {\n            PyObject *sub = stack_pointer[-1];\n            PyObject *container = stack_pointer[-2];\n            #line 627 \"Python/bytecodes.c\"\n            /* del container[sub] */\n            int err = PyObject_DelItem(container, sub);\n            #line 868 \"Python/generated_cases.c.h\"\n            Py_DECREF(container);\n            Py_DECREF(sub);\n            #line 630 \"Python/bytecodes.c\"\n            if (err) goto pop_2_error;\n            #line 873 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(2);\n            DISPATCH();\n        }\n\n        TARGET(CALL_INTRINSIC_1) {\n            PyObject *value = stack_pointer[-1];\n            PyObject *res;\n            #line 634 \"Python/bytecodes.c\"\n            assert(oparg <= MAX_INTRINSIC_1);\n            res = _PyIntrinsics_UnaryFunctions[oparg](tstate, value);\n            #line 884 \"Python/generated_cases.c.h\"\n            Py_DECREF(value);\n            #line 637 \"Python/bytecodes.c\"\n            if (res == NULL) goto pop_1_error;\n            #line 888 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = res;\n            DISPATCH();\n        }\n\n        TARGET(CALL_INTRINSIC_2) {\n            PyObject *value1 = stack_pointer[-1];\n            PyObject *value2 = stack_pointer[-2];\n            PyObject *res;\n            #line 641 \"Python/bytecodes.c\"\n            assert(oparg <= MAX_INTRINSIC_2);\n            res = _PyIntrinsics_BinaryFunctions[oparg](tstate, value2, value1);\n            #line 900 \"Python/generated_cases.c.h\"\n            Py_DECREF(value2);\n            Py_DECREF(value1);\n            #line 644 \"Python/bytecodes.c\"\n            if (res == NULL) goto pop_2_error;\n            #line 905 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            DISPATCH();\n        }\n\n        TARGET(RAISE_VARARGS) {\n            PyObject **args = (stack_pointer - oparg);\n            #line 648 \"Python/bytecodes.c\"\n            PyObject *cause = NULL, *exc = NULL;\n            switch (oparg) {\n            case 2:\n                cause = args[1];\n                /* fall through */\n            case 1:\n                exc = args[0];\n                /* fall through */\n            case 0:\n                if (do_raise(tstate, exc, cause)) { STACK_SHRINK(oparg); goto exception_unwind; }\n                break;\n            default:\n                _PyErr_SetString(tstate, PyExc_SystemError,\n                                 \"bad RAISE_VARARGS oparg\");\n                break;\n            }\n            if (true) { STACK_SHRINK(oparg); goto error; }\n            #line 931 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(INTERPRETER_EXIT) {\n            PyObject *retval = stack_pointer[-1];\n            #line 668 \"Python/bytecodes.c\"\n            assert(frame == &entry_frame);\n            assert(_PyFrame_IsIncomplete(frame));\n            STACK_SHRINK(1);  // Since we're not going to DISPATCH()\n            assert(EMPTY());\n            /* Restore previous cframe and return. */\n            tstate->cframe = cframe.previous;\n            assert(tstate->cframe->current_frame == frame->previous);\n            assert(!_PyErr_Occurred(tstate));\n            _Py_LeaveRecursiveCallTstate(tstate);\n            return retval;\n            #line 947 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(RETURN_VALUE) {\n            PyObject *retval = stack_pointer[-1];\n            #line 681 \"Python/bytecodes.c\"\n            STACK_SHRINK(1);\n            assert(EMPTY());\n            _PyFrame_SetStackPointer(frame, stack_pointer);\n            _Py_LeaveRecursiveCallPy(tstate);\n            assert(frame != &entry_frame);\n            // GH-99729: We need to unlink the frame *before* clearing it:\n            _PyInterpreterFrame *dying = frame;\n            frame = cframe.current_frame = dying->previous;\n            _PyEvalFrameClearAndPop(tstate, dying);\n            frame->prev_instr += frame->return_offset;\n            _PyFrame_StackPush(frame, retval);\n            goto resume_frame;\n            #line 965 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(INSTRUMENTED_RETURN_VALUE) {\n            PyObject *retval = stack_pointer[-1];\n            #line 696 \"Python/bytecodes.c\"\n            int err = _Py_call_instrumentation_arg(\n                    tstate, PY_MONITORING_EVENT_PY_RETURN,\n                    frame, next_instr-1, retval);\n            if (err) goto error;\n            STACK_SHRINK(1);\n            assert(EMPTY());\n            _PyFrame_SetStackPointer(frame, stack_pointer);\n            _Py_LeaveRecursiveCallPy(tstate);\n            assert(frame != &entry_frame);\n            // GH-99729: We need to unlink the frame *before* clearing it:\n            _PyInterpreterFrame *dying = frame;\n            frame = cframe.current_frame = dying->previous;\n            _PyEvalFrameClearAndPop(tstate, dying);\n            frame->prev_instr += frame->return_offset;\n            _PyFrame_StackPush(frame, retval);\n            goto resume_frame;\n            #line 987 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(RETURN_CONST) {\n            #line 715 \"Python/bytecodes.c\"\n            PyObject *retval = GETITEM(frame->f_code->co_consts, oparg);\n            Py_INCREF(retval);\n            assert(EMPTY());\n            _PyFrame_SetStackPointer(frame, stack_pointer);\n            _Py_LeaveRecursiveCallPy(tstate);\n            assert(frame != &entry_frame);\n            // GH-99729: We need to unlink the frame *before* clearing it:\n            _PyInterpreterFrame *dying = frame;\n            frame = cframe.current_frame = dying->previous;\n            _PyEvalFrameClearAndPop(tstate, dying);\n            frame->prev_instr += frame->return_offset;\n            _PyFrame_StackPush(frame, retval);\n            goto resume_frame;\n            #line 1005 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(INSTRUMENTED_RETURN_CONST) {\n            #line 731 \"Python/bytecodes.c\"\n            PyObject *retval = GETITEM(frame->f_code->co_consts, oparg);\n            int err = _Py_call_instrumentation_arg(\n                    tstate, PY_MONITORING_EVENT_PY_RETURN,\n                    frame, next_instr-1, retval);\n            if (err) goto error;\n            Py_INCREF(retval);\n            assert(EMPTY());\n            _PyFrame_SetStackPointer(frame, stack_pointer);\n            _Py_LeaveRecursiveCallPy(tstate);\n            assert(frame != &entry_frame);\n            // GH-99729: We need to unlink the frame *before* clearing it:\n            _PyInterpreterFrame *dying = frame;\n            frame = cframe.current_frame = dying->previous;\n            _PyEvalFrameClearAndPop(tstate, dying);\n            frame->prev_instr += frame->return_offset;\n            _PyFrame_StackPush(frame, retval);\n            goto resume_frame;\n            #line 1027 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(GET_AITER) {\n            PyObject *obj = stack_pointer[-1];\n            PyObject *iter;\n            #line 751 \"Python/bytecodes.c\"\n            unaryfunc getter = NULL;\n            PyTypeObject *type = Py_TYPE(obj);\n\n            if (type->tp_as_async != NULL) {\n                getter = type->tp_as_async->am_aiter;\n            }\n\n            if (getter == NULL) {\n                _PyErr_Format(tstate, PyExc_TypeError,\n                              \"'async for' requires an object with \"\n                              \"__aiter__ method, got %.100s\",\n                              type->tp_name);\n            #line 1046 \"Python/generated_cases.c.h\"\n                Py_DECREF(obj);\n            #line 764 \"Python/bytecodes.c\"\n                if (true) goto pop_1_error;\n            }\n\n            iter = (*getter)(obj);\n            #line 1053 \"Python/generated_cases.c.h\"\n            Py_DECREF(obj);\n            #line 769 \"Python/bytecodes.c\"\n            if (iter == NULL) goto pop_1_error;\n\n            if (Py_TYPE(iter)->tp_as_async == NULL ||\n                    Py_TYPE(iter)->tp_as_async->am_anext == NULL) {\n\n                _PyErr_Format(tstate, PyExc_TypeError,\n                              \"'async for' received an object from __aiter__ \"\n                              \"that does not implement __anext__: %.100s\",\n                              Py_TYPE(iter)->tp_name);\n                Py_DECREF(iter);\n                if (true) goto pop_1_error;\n            }\n            #line 1068 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = iter;\n            DISPATCH();\n        }\n\n        TARGET(GET_ANEXT) {\n            PyObject *aiter = stack_pointer[-1];\n            PyObject *awaitable;\n            #line 784 \"Python/bytecodes.c\"\n            unaryfunc getter = NULL;\n            PyObject *next_iter = NULL;\n            PyTypeObject *type = Py_TYPE(aiter);\n\n            if (PyAsyncGen_CheckExact(aiter)) {\n                awaitable = type->tp_as_async->am_anext(aiter);\n                if (awaitable == NULL) {\n                    goto error;\n                }\n            } else {\n                if (type->tp_as_async != NULL){\n                    getter = type->tp_as_async->am_anext;\n                }\n\n                if (getter != NULL) {\n                    next_iter = (*getter)(aiter);\n                    if (next_iter == NULL) {\n                        goto error;\n                    }\n                }\n                else {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                  \"'async for' requires an iterator with \"\n                                  \"__anext__ method, got %.100s\",\n                                  type->tp_name);\n                    goto error;\n                }\n\n                awaitable = _PyCoro_GetAwaitableIter(next_iter);\n                if (awaitable == NULL) {\n                    _PyErr_FormatFromCause(\n                        PyExc_TypeError,\n                        \"'async for' received an invalid object \"\n                        \"from __anext__: %.100s\",\n                        Py_TYPE(next_iter)->tp_name);\n\n                    Py_DECREF(next_iter);\n                    goto error;\n                } else {\n                    Py_DECREF(next_iter);\n                }\n            }\n            #line 1119 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = awaitable;\n            DISPATCH();\n        }\n\n        TARGET(GET_AWAITABLE) {\n            PyObject *iterable = stack_pointer[-1];\n            PyObject *iter;\n            #line 829 \"Python/bytecodes.c\"\n            iter = _PyCoro_GetAwaitableIter(iterable);\n\n            if (iter == NULL) {\n                format_awaitable_error(tstate, Py_TYPE(iterable), oparg);\n            }\n\n            #line 1135 \"Python/generated_cases.c.h\"\n            Py_DECREF(iterable);\n            #line 836 \"Python/bytecodes.c\"\n\n            if (iter != NULL && PyCoro_CheckExact(iter)) {\n                PyObject *yf = _PyGen_yf((PyGenObject*)iter);\n                if (yf != NULL) {\n                    /* `iter` is a coroutine object that is being\n                       awaited, `yf` is a pointer to the current awaitable\n                       being awaited on. */\n                    Py_DECREF(yf);\n                    Py_CLEAR(iter);\n                    _PyErr_SetString(tstate, PyExc_RuntimeError,\n                                     \"coroutine is being awaited already\");\n                    /* The code below jumps to `error` if `iter` is NULL. */\n                }\n            }\n\n            if (iter == NULL) goto pop_1_error;\n            #line 1154 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = iter;\n            DISPATCH();\n        }\n\n        TARGET(SEND) {\n            PREDICTED(SEND);\n            static_assert(INLINE_CACHE_ENTRIES_SEND == 1, \"incorrect cache size\");\n            PyObject *v = stack_pointer[-1];\n            PyObject *receiver = stack_pointer[-2];\n            PyObject *retval;\n            #line 860 \"Python/bytecodes.c\"\n            #if ENABLE_SPECIALIZATION\n            _PySendCache *cache = (_PySendCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_Send(receiver, next_instr);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(SEND, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            assert(frame != &entry_frame);\n            if ((tstate->interp->eval_frame == NULL) &&\n                (Py_TYPE(receiver) == &PyGen_Type || Py_TYPE(receiver) == &PyCoro_Type) &&\n                ((PyGenObject *)receiver)->gi_frame_state < FRAME_EXECUTING)\n            {\n                PyGenObject *gen = (PyGenObject *)receiver;\n                _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;\n                frame->return_offset = oparg;\n                STACK_SHRINK(1);\n                _PyFrame_StackPush(gen_frame, v);\n                gen->gi_frame_state = FRAME_EXECUTING;\n                gen->gi_exc_state.previous_item = tstate->exc_info;\n                tstate->exc_info = &gen->gi_exc_state;\n                JUMPBY(INLINE_CACHE_ENTRIES_SEND);\n                DISPATCH_INLINED(gen_frame);\n            }\n            if (Py_IsNone(v) && PyIter_Check(receiver)) {\n                retval = Py_TYPE(receiver)->tp_iternext(receiver);\n            }\n            else {\n                retval = PyObject_CallMethodOneArg(receiver, &_Py_ID(send), v);\n            }\n            if (retval == NULL) {\n                if (_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)\n                ) {\n                    monitor_raise(tstate, frame, next_instr-1);\n                }\n                if (_PyGen_FetchStopIterationValue(&retval) == 0) {\n                    assert(retval != NULL);\n                    JUMPBY(oparg);\n                }\n                else {\n                    goto error;\n                }\n            }\n            Py_DECREF(v);\n            #line 1212 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = retval;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(SEND_GEN) {\n            PyObject *v = stack_pointer[-1];\n            PyObject *receiver = stack_pointer[-2];\n            #line 909 \"Python/bytecodes.c\"\n            DEOPT_IF(tstate->interp->eval_frame, SEND);\n            PyGenObject *gen = (PyGenObject *)receiver;\n            DEOPT_IF(Py_TYPE(gen) != &PyGen_Type &&\n                     Py_TYPE(gen) != &PyCoro_Type, SEND);\n            DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, SEND);\n            STAT_INC(SEND, hit);\n            _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;\n            frame->return_offset = oparg;\n            STACK_SHRINK(1);\n            _PyFrame_StackPush(gen_frame, v);\n            gen->gi_frame_state = FRAME_EXECUTING;\n            gen->gi_exc_state.previous_item = tstate->exc_info;\n            tstate->exc_info = &gen->gi_exc_state;\n            JUMPBY(INLINE_CACHE_ENTRIES_SEND);\n            DISPATCH_INLINED(gen_frame);\n            #line 1237 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(INSTRUMENTED_YIELD_VALUE) {\n            PyObject *retval = stack_pointer[-1];\n            #line 927 \"Python/bytecodes.c\"\n            assert(frame != &entry_frame);\n            PyGenObject *gen = _PyFrame_GetGenerator(frame);\n            gen->gi_frame_state = FRAME_SUSPENDED;\n            _PyFrame_SetStackPointer(frame, stack_pointer - 1);\n            int err = _Py_call_instrumentation_arg(\n                    tstate, PY_MONITORING_EVENT_PY_YIELD,\n                    frame, next_instr-1, retval);\n            if (err) goto error;\n            tstate->exc_info = gen->gi_exc_state.previous_item;\n            gen->gi_exc_state.previous_item = NULL;\n            _Py_LeaveRecursiveCallPy(tstate);\n            _PyInterpreterFrame *gen_frame = frame;\n            frame = cframe.current_frame = frame->previous;\n            gen_frame->previous = NULL;\n            _PyFrame_StackPush(frame, retval);\n            goto resume_frame;\n            #line 1259 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(YIELD_VALUE) {\n            PyObject *retval = stack_pointer[-1];\n            #line 946 \"Python/bytecodes.c\"\n            // NOTE: It's important that YIELD_VALUE never raises an exception!\n            // The compiler treats any exception raised here as a failed close()\n            // or throw() call.\n            assert(frame != &entry_frame);\n            PyGenObject *gen = _PyFrame_GetGenerator(frame);\n            gen->gi_frame_state = FRAME_SUSPENDED;\n            _PyFrame_SetStackPointer(frame, stack_pointer - 1);\n            tstate->exc_info = gen->gi_exc_state.previous_item;\n            gen->gi_exc_state.previous_item = NULL;\n            _Py_LeaveRecursiveCallPy(tstate);\n            _PyInterpreterFrame *gen_frame = frame;\n            frame = cframe.current_frame = frame->previous;\n            gen_frame->previous = NULL;\n            _PyFrame_StackPush(frame, retval);\n            goto resume_frame;\n            #line 1280 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(POP_EXCEPT) {\n            PyObject *exc_value = stack_pointer[-1];\n            #line 964 \"Python/bytecodes.c\"\n            _PyErr_StackItem *exc_info = tstate->exc_info;\n            Py_XSETREF(exc_info->exc_value, exc_value);\n            #line 1288 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(RERAISE) {\n            PyObject *exc = stack_pointer[-1];\n            PyObject **values = (stack_pointer - (1 + oparg));\n            #line 969 \"Python/bytecodes.c\"\n            assert(oparg >= 0 && oparg <= 2);\n            if (oparg) {\n                PyObject *lasti = values[0];\n                if (PyLong_Check(lasti)) {\n                    frame->prev_instr = _PyCode_CODE(frame->f_code) + PyLong_AsLong(lasti);\n                    assert(!_PyErr_Occurred(tstate));\n                }\n                else {\n                    assert(PyLong_Check(lasti));\n                    _PyErr_SetString(tstate, PyExc_SystemError, \"lasti is not an int\");\n                    goto error;\n                }\n            }\n            assert(exc && PyExceptionInstance_Check(exc));\n            Py_INCREF(exc);\n            _PyErr_SetRaisedException(tstate, exc);\n            goto exception_unwind;\n            #line 1314 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(END_ASYNC_FOR) {\n            PyObject *exc = stack_pointer[-1];\n            PyObject *awaitable = stack_pointer[-2];\n            #line 989 \"Python/bytecodes.c\"\n            assert(exc && PyExceptionInstance_Check(exc));\n            if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) {\n            #line 1323 \"Python/generated_cases.c.h\"\n                Py_DECREF(awaitable);\n                Py_DECREF(exc);\n            #line 992 \"Python/bytecodes.c\"\n            }\n            else {\n                Py_INCREF(exc);\n                _PyErr_SetRaisedException(tstate, exc);\n                goto exception_unwind;\n            }\n            #line 1333 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(2);\n            DISPATCH();\n        }\n\n        TARGET(CLEANUP_THROW) {\n            PyObject *exc_value = stack_pointer[-1];\n            PyObject *last_sent_val = stack_pointer[-2];\n            PyObject *sub_iter = stack_pointer[-3];\n            PyObject *none;\n            PyObject *value;\n            #line 1001 \"Python/bytecodes.c\"\n            assert(throwflag);\n            assert(exc_value && PyExceptionInstance_Check(exc_value));\n            if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) {\n                value = Py_NewRef(((PyStopIterationObject *)exc_value)->value);\n            #line 1349 \"Python/generated_cases.c.h\"\n                Py_DECREF(sub_iter);\n                Py_DECREF(last_sent_val);\n                Py_DECREF(exc_value);\n            #line 1006 \"Python/bytecodes.c\"\n                none = Py_None;\n            }\n            else {\n                _PyErr_SetRaisedException(tstate, Py_NewRef(exc_value));\n                goto exception_unwind;\n            }\n            #line 1360 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = value;\n            stack_pointer[-2] = none;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_ASSERTION_ERROR) {\n            PyObject *value;\n            #line 1015 \"Python/bytecodes.c\"\n            value = Py_NewRef(PyExc_AssertionError);\n            #line 1371 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = value;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_BUILD_CLASS) {\n            PyObject *bc;\n            #line 1019 \"Python/bytecodes.c\"\n            if (PyDict_CheckExact(BUILTINS())) {\n                bc = _PyDict_GetItemWithError(BUILTINS(),\n                                              &_Py_ID(__build_class__));\n                if (bc == NULL) {\n                    if (!_PyErr_Occurred(tstate)) {\n                        _PyErr_SetString(tstate, PyExc_NameError,\n                                         \"__build_class__ not found\");\n                    }\n                    if (true) goto error;\n                }\n                Py_INCREF(bc);\n            }\n            else {\n                bc = PyObject_GetItem(BUILTINS(), &_Py_ID(__build_class__));\n                if (bc == NULL) {\n                    if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError))\n                        _PyErr_SetString(tstate, PyExc_NameError,\n                                         \"__build_class__ not found\");\n                    if (true) goto error;\n                }\n            }\n            #line 1401 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = bc;\n            DISPATCH();\n        }\n\n        TARGET(STORE_NAME) {\n            PyObject *v = stack_pointer[-1];\n            #line 1044 \"Python/bytecodes.c\"\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            PyObject *ns = LOCALS();\n            int err;\n            if (ns == NULL) {\n                _PyErr_Format(tstate, PyExc_SystemError,\n                              \"no locals found when storing %R\", name);\n            #line 1416 \"Python/generated_cases.c.h\"\n                Py_DECREF(v);\n            #line 1051 \"Python/bytecodes.c\"\n                if (true) goto pop_1_error;\n            }\n            if (PyDict_CheckExact(ns))\n                err = PyDict_SetItem(ns, name, v);\n            else\n                err = PyObject_SetItem(ns, name, v);\n            #line 1425 \"Python/generated_cases.c.h\"\n            Py_DECREF(v);\n            #line 1058 \"Python/bytecodes.c\"\n            if (err) goto pop_1_error;\n            #line 1429 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(DELETE_NAME) {\n            #line 1062 \"Python/bytecodes.c\"\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            PyObject *ns = LOCALS();\n            int err;\n            if (ns == NULL) {\n                _PyErr_Format(tstate, PyExc_SystemError,\n                              \"no locals when deleting %R\", name);\n                goto error;\n            }\n            err = PyObject_DelItem(ns, name);\n            // Can't use ERROR_IF here.\n            if (err != 0) {\n                format_exc_check_arg(tstate, PyExc_NameError,\n                                     NAME_ERROR_MSG,\n                                     name);\n                goto error;\n            }\n            #line 1452 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(UNPACK_SEQUENCE) {\n            PREDICTED(UNPACK_SEQUENCE);\n            static_assert(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE == 1, \"incorrect cache size\");\n            PyObject *seq = stack_pointer[-1];\n            #line 1088 \"Python/bytecodes.c\"\n            #if ENABLE_SPECIALIZATION\n            _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_UnpackSequence(seq, next_instr, oparg);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(UNPACK_SEQUENCE, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            PyObject **top = stack_pointer + oparg - 1;\n            int res = unpack_iterable(tstate, seq, oparg, -1, top);\n            #line 1473 \"Python/generated_cases.c.h\"\n            Py_DECREF(seq);\n            #line 1101 \"Python/bytecodes.c\"\n            if (res == 0) goto pop_1_error;\n            #line 1477 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            STACK_GROW(oparg);\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(UNPACK_SEQUENCE_TWO_TUPLE) {\n            PyObject *seq = stack_pointer[-1];\n            PyObject **values = stack_pointer - (1);\n            #line 1105 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE);\n            DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE);\n            assert(oparg == 2);\n            STAT_INC(UNPACK_SEQUENCE, hit);\n            values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1));\n            values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0));\n            #line 1494 \"Python/generated_cases.c.h\"\n            Py_DECREF(seq);\n            STACK_SHRINK(1);\n            STACK_GROW(oparg);\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(UNPACK_SEQUENCE_TUPLE) {\n            PyObject *seq = stack_pointer[-1];\n            PyObject **values = stack_pointer - (1);\n            #line 1115 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE);\n            DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE);\n            STAT_INC(UNPACK_SEQUENCE, hit);\n            PyObject **items = _PyTuple_ITEMS(seq);\n            for (int i = oparg; --i >= 0; ) {\n                *values++ = Py_NewRef(items[i]);\n            }\n            #line 1513 \"Python/generated_cases.c.h\"\n            Py_DECREF(seq);\n            STACK_SHRINK(1);\n            STACK_GROW(oparg);\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(UNPACK_SEQUENCE_LIST) {\n            PyObject *seq = stack_pointer[-1];\n            PyObject **values = stack_pointer - (1);\n            #line 1126 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE);\n            DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE);\n            STAT_INC(UNPACK_SEQUENCE, hit);\n            PyObject **items = _PyList_ITEMS(seq);\n            for (int i = oparg; --i >= 0; ) {\n                *values++ = Py_NewRef(items[i]);\n            }\n            #line 1532 \"Python/generated_cases.c.h\"\n            Py_DECREF(seq);\n            STACK_SHRINK(1);\n            STACK_GROW(oparg);\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(UNPACK_EX) {\n            PyObject *seq = stack_pointer[-1];\n            #line 1137 \"Python/bytecodes.c\"\n            int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8);\n            PyObject **top = stack_pointer + totalargs - 1;\n            int res = unpack_iterable(tstate, seq, oparg & 0xFF, oparg >> 8, top);\n            #line 1546 \"Python/generated_cases.c.h\"\n            Py_DECREF(seq);\n            #line 1141 \"Python/bytecodes.c\"\n            if (res == 0) goto pop_1_error;\n            #line 1550 \"Python/generated_cases.c.h\"\n            STACK_GROW((oparg & 0xFF) + (oparg >> 8));\n            DISPATCH();\n        }\n\n        TARGET(STORE_ATTR) {\n            PREDICTED(STORE_ATTR);\n            static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, \"incorrect cache size\");\n            PyObject *owner = stack_pointer[-1];\n            PyObject *v = stack_pointer[-2];\n            uint16_t counter = read_u16(&next_instr[0].cache);\n            #line 1152 \"Python/bytecodes.c\"\n            #if ENABLE_SPECIALIZATION\n            if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {\n                PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n                next_instr--;\n                _Py_Specialize_StoreAttr(owner, next_instr, name);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(STORE_ATTR, deferred);\n            _PyAttrCache *cache = (_PyAttrCache *)next_instr;\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #else\n            (void)counter;  // Unused.\n            #endif  /* ENABLE_SPECIALIZATION */\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            int err = PyObject_SetAttr(owner, name, v);\n            #line 1577 \"Python/generated_cases.c.h\"\n            Py_DECREF(v);\n            Py_DECREF(owner);\n            #line 1168 \"Python/bytecodes.c\"\n            if (err) goto pop_2_error;\n            #line 1582 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(2);\n            next_instr += 4;\n            DISPATCH();\n        }\n\n        TARGET(DELETE_ATTR) {\n            PyObject *owner = stack_pointer[-1];\n            #line 1172 \"Python/bytecodes.c\"\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            int err = PyObject_SetAttr(owner, name, (PyObject *)NULL);\n            #line 1593 \"Python/generated_cases.c.h\"\n            Py_DECREF(owner);\n            #line 1175 \"Python/bytecodes.c\"\n            if (err) goto pop_1_error;\n            #line 1597 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(STORE_GLOBAL) {\n            PyObject *v = stack_pointer[-1];\n            #line 1179 \"Python/bytecodes.c\"\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            int err = PyDict_SetItem(GLOBALS(), name, v);\n            #line 1607 \"Python/generated_cases.c.h\"\n            Py_DECREF(v);\n            #line 1182 \"Python/bytecodes.c\"\n            if (err) goto pop_1_error;\n            #line 1611 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(DELETE_GLOBAL) {\n            #line 1186 \"Python/bytecodes.c\"\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            int err;\n            err = PyDict_DelItem(GLOBALS(), name);\n            // Can't use ERROR_IF here.\n            if (err != 0) {\n                if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n                    format_exc_check_arg(tstate, PyExc_NameError,\n                                         NAME_ERROR_MSG, name);\n                }\n                goto error;\n            }\n            #line 1629 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(LOAD_LOCALS) {\n            PyObject *_tmp_1;\n            {\n                PyObject *locals;\n                #line 1200 \"Python/bytecodes.c\"\n                locals = LOCALS();\n                if (locals == NULL) {\n                    _PyErr_SetString(tstate, PyExc_SystemError,\n                                     \"no locals found\");\n                    if (true) goto error;\n                }\n                Py_INCREF(locals);\n                #line 1645 \"Python/generated_cases.c.h\"\n                _tmp_1 = locals;\n            }\n            STACK_GROW(1);\n            stack_pointer[-1] = _tmp_1;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_NAME) {\n            PyObject *_tmp_1;\n            {\n                PyObject *locals;\n                #line 1200 \"Python/bytecodes.c\"\n                locals = LOCALS();\n                if (locals == NULL) {\n                    _PyErr_SetString(tstate, PyExc_SystemError,\n                                     \"no locals found\");\n                    if (true) goto error;\n                }\n                Py_INCREF(locals);\n                #line 1665 \"Python/generated_cases.c.h\"\n                _tmp_1 = locals;\n            }\n            {\n                PyObject *mod_or_class_dict = _tmp_1;\n                PyObject *v;\n                #line 1212 \"Python/bytecodes.c\"\n                PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n                if (PyDict_CheckExact(mod_or_class_dict)) {\n                    v = PyDict_GetItemWithError(mod_or_class_dict, name);\n                    if (v != NULL) {\n                        Py_INCREF(v);\n                    }\n                    else if (_PyErr_Occurred(tstate)) {\n                        Py_DECREF(mod_or_class_dict);\n                        goto error;\n                    }\n                }\n                else {\n                    v = PyObject_GetItem(mod_or_class_dict, name);\n                    if (v == NULL) {\n                        if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n                            Py_DECREF(mod_or_class_dict);\n                            goto error;\n                        }\n                        _PyErr_Clear(tstate);\n                    }\n                }\n                Py_DECREF(mod_or_class_dict);\n                if (v == NULL) {\n                    v = PyDict_GetItemWithError(GLOBALS(), name);\n                    if (v != NULL) {\n                        Py_INCREF(v);\n                    }\n                    else if (_PyErr_Occurred(tstate)) {\n                        goto error;\n                    }\n                    else {\n                        if (PyDict_CheckExact(BUILTINS())) {\n                            v = PyDict_GetItemWithError(BUILTINS(), name);\n                            if (v == NULL) {\n                                if (!_PyErr_Occurred(tstate)) {\n                                    format_exc_check_arg(\n                                            tstate, PyExc_NameError,\n                                            NAME_ERROR_MSG, name);\n                                }\n                                goto error;\n                            }\n                            Py_INCREF(v);\n                        }\n                        else {\n                            v = PyObject_GetItem(BUILTINS(), name);\n                            if (v == NULL) {\n                                if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n                                    format_exc_check_arg(\n                                                tstate, PyExc_NameError,\n                                                NAME_ERROR_MSG, name);\n                                }\n                                goto error;\n                            }\n                        }\n                    }\n                }\n                #line 1728 \"Python/generated_cases.c.h\"\n                _tmp_1 = v;\n            }\n            STACK_GROW(1);\n            stack_pointer[-1] = _tmp_1;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_FROM_DICT_OR_GLOBALS) {\n            PyObject *_tmp_1 = stack_pointer[-1];\n            {\n                PyObject *mod_or_class_dict = _tmp_1;\n                PyObject *v;\n                #line 1212 \"Python/bytecodes.c\"\n                PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n                if (PyDict_CheckExact(mod_or_class_dict)) {\n                    v = PyDict_GetItemWithError(mod_or_class_dict, name);\n                    if (v != NULL) {\n                        Py_INCREF(v);\n                    }\n                    else if (_PyErr_Occurred(tstate)) {\n                        Py_DECREF(mod_or_class_dict);\n                        goto error;\n                    }\n                }\n                else {\n                    v = PyObject_GetItem(mod_or_class_dict, name);\n                    if (v == NULL) {\n                        if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n                            Py_DECREF(mod_or_class_dict);\n                            goto error;\n                        }\n                        _PyErr_Clear(tstate);\n                    }\n                }\n                Py_DECREF(mod_or_class_dict);\n                if (v == NULL) {\n                    v = PyDict_GetItemWithError(GLOBALS(), name);\n                    if (v != NULL) {\n                        Py_INCREF(v);\n                    }\n                    else if (_PyErr_Occurred(tstate)) {\n                        goto error;\n                    }\n                    else {\n                        if (PyDict_CheckExact(BUILTINS())) {\n                            v = PyDict_GetItemWithError(BUILTINS(), name);\n                            if (v == NULL) {\n                                if (!_PyErr_Occurred(tstate)) {\n                                    format_exc_check_arg(\n                                            tstate, PyExc_NameError,\n                                            NAME_ERROR_MSG, name);\n                                }\n                                goto error;\n                            }\n                            Py_INCREF(v);\n                        }\n                        else {\n                            v = PyObject_GetItem(BUILTINS(), name);\n                            if (v == NULL) {\n                                if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n                                    format_exc_check_arg(\n                                                tstate, PyExc_NameError,\n                                                NAME_ERROR_MSG, name);\n                                }\n                                goto error;\n                            }\n                        }\n                    }\n                }\n                #line 1798 \"Python/generated_cases.c.h\"\n                _tmp_1 = v;\n            }\n            stack_pointer[-1] = _tmp_1;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_GLOBAL) {\n            PREDICTED(LOAD_GLOBAL);\n            static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, \"incorrect cache size\");\n            PyObject *null = NULL;\n            PyObject *v;\n            #line 1281 \"Python/bytecodes.c\"\n            #if ENABLE_SPECIALIZATION\n            _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);\n                next_instr--;\n                _Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(LOAD_GLOBAL, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);\n            if (PyDict_CheckExact(GLOBALS())\n                && PyDict_CheckExact(BUILTINS()))\n            {\n                v = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(),\n                                       (PyDictObject *)BUILTINS(),\n                                       name);\n                if (v == NULL) {\n                    if (!_PyErr_Occurred(tstate)) {\n                        /* _PyDict_LoadGlobal() returns NULL without raising\n                         * an exception if the key doesn't exist */\n                        format_exc_check_arg(tstate, PyExc_NameError,\n                                             NAME_ERROR_MSG, name);\n                    }\n                    if (true) goto error;\n                }\n                Py_INCREF(v);\n            }\n            else {\n                /* Slow-path if globals or builtins is not a dict */\n\n                /* namespace 1: globals */\n                v = PyObject_GetItem(GLOBALS(), name);\n                if (v == NULL) {\n                    if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) goto error;\n                    _PyErr_Clear(tstate);\n\n                    /* namespace 2: builtins */\n                    v = PyObject_GetItem(BUILTINS(), name);\n                    if (v == NULL) {\n                        if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n                            format_exc_check_arg(\n                                        tstate, PyExc_NameError,\n                                        NAME_ERROR_MSG, name);\n                        }\n                        if (true) goto error;\n                    }\n                }\n            }\n            null = NULL;\n            #line 1862 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = v;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = null; }\n            next_instr += 4;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_GLOBAL_MODULE) {\n            PyObject *null = NULL;\n            PyObject *res;\n            uint16_t index = read_u16(&next_instr[1].cache);\n            uint16_t version = read_u16(&next_instr[2].cache);\n            #line 1335 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);\n            PyDictObject *dict = (PyDictObject *)GLOBALS();\n            DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);\n            assert(DK_IS_UNICODE(dict->ma_keys));\n            PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);\n            res = entries[index].me_value;\n            DEOPT_IF(res == NULL, LOAD_GLOBAL);\n            Py_INCREF(res);\n            STAT_INC(LOAD_GLOBAL, hit);\n            null = NULL;\n            #line 1887 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = null; }\n            next_instr += 4;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_GLOBAL_BUILTIN) {\n            PyObject *null = NULL;\n            PyObject *res;\n            uint16_t index = read_u16(&next_instr[1].cache);\n            uint16_t mod_version = read_u16(&next_instr[2].cache);\n            uint16_t bltn_version = read_u16(&next_instr[3].cache);\n            #line 1348 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);\n            DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL);\n            PyDictObject *mdict = (PyDictObject *)GLOBALS();\n            PyDictObject *bdict = (PyDictObject *)BUILTINS();\n            assert(opcode == LOAD_GLOBAL_BUILTIN);\n            DEOPT_IF(mdict->ma_keys->dk_version != mod_version, LOAD_GLOBAL);\n            DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL);\n            assert(DK_IS_UNICODE(bdict->ma_keys));\n            PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys);\n            res = entries[index].me_value;\n            DEOPT_IF(res == NULL, LOAD_GLOBAL);\n            Py_INCREF(res);\n            STAT_INC(LOAD_GLOBAL, hit);\n            null = NULL;\n            #line 1917 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = null; }\n            next_instr += 4;\n            DISPATCH();\n        }\n\n        TARGET(DELETE_FAST) {\n            #line 1365 \"Python/bytecodes.c\"\n            PyObject *v = GETLOCAL(oparg);\n            if (v == NULL) goto unbound_local_error;\n            SETLOCAL(oparg, NULL);\n            #line 1931 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(MAKE_CELL) {\n            #line 1371 \"Python/bytecodes.c\"\n            // \"initial\" is probably NULL but not if it's an arg (or set\n            // via PyFrame_LocalsToFast() before MAKE_CELL has run).\n            PyObject *initial = GETLOCAL(oparg);\n            PyObject *cell = PyCell_New(initial);\n            if (cell == NULL) {\n                goto resume_with_error;\n            }\n            SETLOCAL(oparg, cell);\n            #line 1945 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(DELETE_DEREF) {\n            #line 1382 \"Python/bytecodes.c\"\n            PyObject *cell = GETLOCAL(oparg);\n            PyObject *oldobj = PyCell_GET(cell);\n            // Can't use ERROR_IF here.\n            // Fortunately we don't need its superpower.\n            if (oldobj == NULL) {\n                format_exc_unbound(tstate, frame->f_code, oparg);\n                goto error;\n            }\n            PyCell_SET(cell, NULL);\n            Py_DECREF(oldobj);\n            #line 1961 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(LOAD_FROM_DICT_OR_DEREF) {\n            PyObject *class_dict = stack_pointer[-1];\n            PyObject *value;\n            #line 1395 \"Python/bytecodes.c\"\n            PyObject *name;\n            assert(class_dict);\n            assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus);\n            name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg);\n            if (PyDict_CheckExact(class_dict)) {\n                value = PyDict_GetItemWithError(class_dict, name);\n                if (value != NULL) {\n                    Py_INCREF(value);\n                }\n                else if (_PyErr_Occurred(tstate)) {\n                    Py_DECREF(class_dict);\n                    goto error;\n                }\n            }\n            else {\n                value = PyObject_GetItem(class_dict, name);\n                if (value == NULL) {\n                    if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n                        Py_DECREF(class_dict);\n                        goto error;\n                    }\n                    _PyErr_Clear(tstate);\n                }\n            }\n            Py_DECREF(class_dict);\n            if (!value) {\n                PyObject *cell = GETLOCAL(oparg);\n                value = PyCell_GET(cell);\n                if (value == NULL) {\n                    format_exc_unbound(tstate, frame->f_code, oparg);\n                    goto error;\n                }\n                Py_INCREF(value);\n            }\n            #line 2003 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = value;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_DEREF) {\n            PyObject *value;\n            #line 1432 \"Python/bytecodes.c\"\n            PyObject *cell = GETLOCAL(oparg);\n            value = PyCell_GET(cell);\n            if (value == NULL) {\n                format_exc_unbound(tstate, frame->f_code, oparg);\n                if (true) goto error;\n            }\n            Py_INCREF(value);\n            #line 2018 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = value;\n            DISPATCH();\n        }\n\n        TARGET(STORE_DEREF) {\n            PyObject *v = stack_pointer[-1];\n            #line 1442 \"Python/bytecodes.c\"\n            PyObject *cell = GETLOCAL(oparg);\n            PyObject *oldobj = PyCell_GET(cell);\n            PyCell_SET(cell, v);\n            Py_XDECREF(oldobj);\n            #line 2031 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(COPY_FREE_VARS) {\n            #line 1449 \"Python/bytecodes.c\"\n            /* Copy closure variables to free variables */\n            PyCodeObject *co = frame->f_code;\n            assert(PyFunction_Check(frame->f_funcobj));\n            PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;\n            assert(oparg == co->co_nfreevars);\n            int offset = co->co_nlocalsplus - oparg;\n            for (int i = 0; i < oparg; ++i) {\n                PyObject *o = PyTuple_GET_ITEM(closure, i);\n                frame->localsplus[offset + i] = Py_NewRef(o);\n            }\n            #line 2048 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(BUILD_STRING) {\n            PyObject **pieces = (stack_pointer - oparg);\n            PyObject *str;\n            #line 1462 \"Python/bytecodes.c\"\n            str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg);\n            #line 2057 \"Python/generated_cases.c.h\"\n            for (int _i = oparg; --_i >= 0;) {\n                Py_DECREF(pieces[_i]);\n            }\n            #line 1464 \"Python/bytecodes.c\"\n            if (str == NULL) { STACK_SHRINK(oparg); goto error; }\n            #line 2063 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_GROW(1);\n            stack_pointer[-1] = str;\n            DISPATCH();\n        }\n\n        TARGET(BUILD_TUPLE) {\n            PyObject **values = (stack_pointer - oparg);\n            PyObject *tup;\n            #line 1468 \"Python/bytecodes.c\"\n            tup = _PyTuple_FromArraySteal(values, oparg);\n            if (tup == NULL) { STACK_SHRINK(oparg); goto error; }\n            #line 2076 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_GROW(1);\n            stack_pointer[-1] = tup;\n            DISPATCH();\n        }\n\n        TARGET(BUILD_LIST) {\n            PyObject **values = (stack_pointer - oparg);\n            PyObject *list;\n            #line 1473 \"Python/bytecodes.c\"\n            list = _PyList_FromArraySteal(values, oparg);\n            if (list == NULL) { STACK_SHRINK(oparg); goto error; }\n            #line 2089 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_GROW(1);\n            stack_pointer[-1] = list;\n            DISPATCH();\n        }\n\n        TARGET(LIST_EXTEND) {\n            PyObject *iterable = stack_pointer[-1];\n            PyObject *list = stack_pointer[-(2 + (oparg-1))];\n            #line 1478 \"Python/bytecodes.c\"\n            PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable);\n            if (none_val == NULL) {\n                if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&\n                   (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable)))\n                {\n                    _PyErr_Clear(tstate);\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                          \"Value after * must be an iterable, not %.200s\",\n                          Py_TYPE(iterable)->tp_name);\n                }\n            #line 2110 \"Python/generated_cases.c.h\"\n                Py_DECREF(iterable);\n            #line 1489 \"Python/bytecodes.c\"\n                if (true) goto pop_1_error;\n            }\n            assert(Py_IsNone(none_val));\n            #line 2116 \"Python/generated_cases.c.h\"\n            Py_DECREF(iterable);\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(SET_UPDATE) {\n            PyObject *iterable = stack_pointer[-1];\n            PyObject *set = stack_pointer[-(2 + (oparg-1))];\n            #line 1496 \"Python/bytecodes.c\"\n            int err = _PySet_Update(set, iterable);\n            #line 2127 \"Python/generated_cases.c.h\"\n            Py_DECREF(iterable);\n            #line 1498 \"Python/bytecodes.c\"\n            if (err < 0) goto pop_1_error;\n            #line 2131 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(BUILD_SET) {\n            PyObject **values = (stack_pointer - oparg);\n            PyObject *set;\n            #line 1502 \"Python/bytecodes.c\"\n            set = PySet_New(NULL);\n            if (set == NULL)\n                goto error;\n            int err = 0;\n            for (int i = 0; i < oparg; i++) {\n                PyObject *item = values[i];\n                if (err == 0)\n                    err = PySet_Add(set, item);\n                Py_DECREF(item);\n            }\n            if (err != 0) {\n                Py_DECREF(set);\n                if (true) { STACK_SHRINK(oparg); goto error; }\n            }\n            #line 2154 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_GROW(1);\n            stack_pointer[-1] = set;\n            DISPATCH();\n        }\n\n        TARGET(BUILD_MAP) {\n            PyObject **values = (stack_pointer - oparg*2);\n            PyObject *map;\n            #line 1519 \"Python/bytecodes.c\"\n            map = _PyDict_FromItems(\n                    values, 2,\n                    values+1, 2,\n                    oparg);\n            if (map == NULL)\n                goto error;\n\n            #line 2172 \"Python/generated_cases.c.h\"\n            for (int _i = oparg*2; --_i >= 0;) {\n                Py_DECREF(values[_i]);\n            }\n            #line 1527 \"Python/bytecodes.c\"\n            if (map == NULL) { STACK_SHRINK(oparg*2); goto error; }\n            #line 2178 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg*2);\n            STACK_GROW(1);\n            stack_pointer[-1] = map;\n            DISPATCH();\n        }\n\n        TARGET(SETUP_ANNOTATIONS) {\n            #line 1531 \"Python/bytecodes.c\"\n            int err;\n            PyObject *ann_dict;\n            if (LOCALS() == NULL) {\n                _PyErr_Format(tstate, PyExc_SystemError,\n                              \"no locals found when setting up annotations\");\n                if (true) goto error;\n            }\n            /* check if __annotations__ in locals()... */\n            if (PyDict_CheckExact(LOCALS())) {\n                ann_dict = _PyDict_GetItemWithError(LOCALS(),\n                                                    &_Py_ID(__annotations__));\n                if (ann_dict == NULL) {\n                    if (_PyErr_Occurred(tstate)) goto error;\n                    /* ...if not, create a new one */\n                    ann_dict = PyDict_New();\n                    if (ann_dict == NULL) goto error;\n                    err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__),\n                                         ann_dict);\n                    Py_DECREF(ann_dict);\n                    if (err) goto error;\n                }\n            }\n            else {\n                /* do the same if locals() is not a dict */\n                ann_dict = PyObject_GetItem(LOCALS(), &_Py_ID(__annotations__));\n                if (ann_dict == NULL) {\n                    if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) goto error;\n                    _PyErr_Clear(tstate);\n                    ann_dict = PyDict_New();\n                    if (ann_dict == NULL) goto error;\n                    err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__),\n                                           ann_dict);\n                    Py_DECREF(ann_dict);\n                    if (err) goto error;\n                }\n                else {\n                    Py_DECREF(ann_dict);\n                }\n            }\n            #line 2226 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(BUILD_CONST_KEY_MAP) {\n            PyObject *keys = stack_pointer[-1];\n            PyObject **values = (stack_pointer - (1 + oparg));\n            PyObject *map;\n            #line 1573 \"Python/bytecodes.c\"\n            if (!PyTuple_CheckExact(keys) ||\n                PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) {\n                _PyErr_SetString(tstate, PyExc_SystemError,\n                                 \"bad BUILD_CONST_KEY_MAP keys argument\");\n                goto error;  // Pop the keys and values.\n            }\n            map = _PyDict_FromItems(\n                    &PyTuple_GET_ITEM(keys, 0), 1,\n                    values, 1, oparg);\n            #line 2244 \"Python/generated_cases.c.h\"\n            for (int _i = oparg; --_i >= 0;) {\n                Py_DECREF(values[_i]);\n            }\n            Py_DECREF(keys);\n            #line 1583 \"Python/bytecodes.c\"\n            if (map == NULL) { STACK_SHRINK(oparg); goto pop_1_error; }\n            #line 2251 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            stack_pointer[-1] = map;\n            DISPATCH();\n        }\n\n        TARGET(DICT_UPDATE) {\n            PyObject *update = stack_pointer[-1];\n            #line 1587 \"Python/bytecodes.c\"\n            PyObject *dict = PEEK(oparg + 1);  // update is still on the stack\n            if (PyDict_Update(dict, update) < 0) {\n                if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                    \"'%.200s' object is not a mapping\",\n                                    Py_TYPE(update)->tp_name);\n                }\n            #line 2267 \"Python/generated_cases.c.h\"\n                Py_DECREF(update);\n            #line 1595 \"Python/bytecodes.c\"\n                if (true) goto pop_1_error;\n            }\n            #line 2272 \"Python/generated_cases.c.h\"\n            Py_DECREF(update);\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(DICT_MERGE) {\n            PyObject *update = stack_pointer[-1];\n            #line 1601 \"Python/bytecodes.c\"\n            PyObject *dict = PEEK(oparg + 1);  // update is still on the stack\n\n            if (_PyDict_MergeEx(dict, update, 2) < 0) {\n                format_kwargs_error(tstate, PEEK(3 + oparg), update);\n            #line 2285 \"Python/generated_cases.c.h\"\n                Py_DECREF(update);\n            #line 1606 \"Python/bytecodes.c\"\n                if (true) goto pop_1_error;\n            }\n            #line 2290 \"Python/generated_cases.c.h\"\n            Py_DECREF(update);\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(MAP_ADD) {\n            PyObject *value = stack_pointer[-1];\n            PyObject *key = stack_pointer[-2];\n            #line 1612 \"Python/bytecodes.c\"\n            PyObject *dict = PEEK(oparg + 2);  // key, value are still on the stack\n            assert(PyDict_CheckExact(dict));\n            /* dict[key] = value */\n            // Do not DECREF INPUTS because the function steals the references\n            if (_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0) goto pop_2_error;\n            #line 2305 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(2);\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_LOAD_SUPER_ATTR) {\n            #line 1620 \"Python/bytecodes.c\"\n            _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr;\n            // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we\n            // don't want to specialize instrumented instructions\n            INCREMENT_ADAPTIVE_COUNTER(cache->counter);\n            GO_TO_INSTRUCTION(LOAD_SUPER_ATTR);\n            #line 2317 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(LOAD_SUPER_ATTR) {\n            PREDICTED(LOAD_SUPER_ATTR);\n            static_assert(INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR == 1, \"incorrect cache size\");\n            PyObject *self = stack_pointer[-1];\n            PyObject *class = stack_pointer[-2];\n            PyObject *global_super = stack_pointer[-3];\n            PyObject *res2 = NULL;\n            PyObject *res;\n            #line 1634 \"Python/bytecodes.c\"\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);\n            int load_method = oparg & 1;\n            #if ENABLE_SPECIALIZATION\n            _PySuperAttrCache *cache = (_PySuperAttrCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_LoadSuperAttr(global_super, class, next_instr, load_method);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(LOAD_SUPER_ATTR, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n\n            if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {\n                PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;\n                int err = _Py_call_instrumentation_2args(\n                        tstate, PY_MONITORING_EVENT_CALL,\n                        frame, next_instr-1, global_super, arg);\n                if (err) goto pop_3_error;\n            }\n\n            // we make no attempt to optimize here; specializations should\n            // handle any case whose performance we care about\n            PyObject *stack[] = {class, self};\n            PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL);\n            if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {\n                PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;\n                if (super == NULL) {\n                    _Py_call_instrumentation_exc2(\n                        tstate, PY_MONITORING_EVENT_C_RAISE,\n                        frame, next_instr-1, global_super, arg);\n                }\n                else {\n                    int err = _Py_call_instrumentation_2args(\n                        tstate, PY_MONITORING_EVENT_C_RETURN,\n                        frame, next_instr-1, global_super, arg);\n                    if (err < 0) {\n                        Py_CLEAR(super);\n                    }\n                }\n            }\n            #line 2370 \"Python/generated_cases.c.h\"\n            Py_DECREF(global_super);\n            Py_DECREF(class);\n            Py_DECREF(self);\n            #line 1676 \"Python/bytecodes.c\"\n            if (super == NULL) goto pop_3_error;\n            res = PyObject_GetAttr(super, name);\n            Py_DECREF(super);\n            if (res == NULL) goto pop_3_error;\n            #line 2379 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(2);\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_SUPER_ATTR_ATTR) {\n            PyObject *self = stack_pointer[-1];\n            PyObject *class = stack_pointer[-2];\n            PyObject *global_super = stack_pointer[-3];\n            PyObject *res2 = NULL;\n            PyObject *res;\n            #line 1695 \"Python/bytecodes.c\"\n            assert(!(oparg & 1));\n            DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);\n            DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);\n            STAT_INC(LOAD_SUPER_ATTR, hit);\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);\n            res = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL);\n            #line 2401 \"Python/generated_cases.c.h\"\n            Py_DECREF(global_super);\n            Py_DECREF(class);\n            Py_DECREF(self);\n            #line 1702 \"Python/bytecodes.c\"\n            if (res == NULL) goto pop_3_error;\n            #line 2407 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(2);\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_SUPER_ATTR_METHOD) {\n            PyObject *self = stack_pointer[-1];\n            PyObject *class = stack_pointer[-2];\n            PyObject *global_super = stack_pointer[-3];\n            PyObject *res2;\n            PyObject *res;\n            #line 1706 \"Python/bytecodes.c\"\n            assert(oparg & 1);\n            DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);\n            DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);\n            STAT_INC(LOAD_SUPER_ATTR, hit);\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 2);\n            PyTypeObject *cls = (PyTypeObject *)class;\n            int method_found = 0;\n            res2 = _PySuper_Lookup(cls, self, name,\n                                   cls->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL);\n            Py_DECREF(global_super);\n            Py_DECREF(class);\n            if (res2 == NULL) {\n                Py_DECREF(self);\n                if (true) goto pop_3_error;\n            }\n            if (method_found) {\n                res = self; // transfer ownership\n            } else {\n                Py_DECREF(self);\n                res = res2;\n                res2 = NULL;\n            }\n            #line 2445 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            stack_pointer[-2] = res2;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_ATTR) {\n            PREDICTED(LOAD_ATTR);\n            static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, \"incorrect cache size\");\n            PyObject *owner = stack_pointer[-1];\n            PyObject *res2 = NULL;\n            PyObject *res;\n            #line 1745 \"Python/bytecodes.c\"\n            #if ENABLE_SPECIALIZATION\n            _PyAttrCache *cache = (_PyAttrCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);\n                next_instr--;\n                _Py_Specialize_LoadAttr(owner, next_instr, name);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(LOAD_ATTR, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 1);\n            if (oparg & 1) {\n                /* Designed to work in tandem with CALL, pushes two values. */\n                PyObject* meth = NULL;\n                if (_PyObject_GetMethod(owner, name, &meth)) {\n                    /* We can bypass temporary bound method object.\n                       meth is unbound method and obj is self.\n\n                       meth | self | arg1 | ... | argN\n                     */\n                    assert(meth != NULL);  // No errors on this branch\n                    res2 = meth;\n                    res = owner;  // Transfer ownership\n                }\n                else {\n                    /* meth is not an unbound method (but a regular attr, or\n                       something was returned by a descriptor protocol).  Set\n                       the second element of the stack to NULL, to signal\n                       CALL that it's not a method call.\n\n                       NULL | meth | arg1 | ... | argN\n                    */\n            #line 2493 \"Python/generated_cases.c.h\"\n                    Py_DECREF(owner);\n            #line 1779 \"Python/bytecodes.c\"\n                    if (meth == NULL) goto pop_1_error;\n                    res2 = NULL;\n                    res = meth;\n                }\n            }\n            else {\n                /* Classic, pushes one value. */\n                res = PyObject_GetAttr(owner, name);\n            #line 2504 \"Python/generated_cases.c.h\"\n                Py_DECREF(owner);\n            #line 1788 \"Python/bytecodes.c\"\n                if (res == NULL) goto pop_1_error;\n            }\n            #line 2509 \"Python/generated_cases.c.h\"\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }\n            next_instr += 9;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_ATTR_INSTANCE_VALUE) {\n            PyObject *owner = stack_pointer[-1];\n            PyObject *res2 = NULL;\n            PyObject *res;\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            uint16_t index = read_u16(&next_instr[3].cache);\n            #line 1797 \"Python/bytecodes.c\"\n            PyTypeObject *tp = Py_TYPE(owner);\n            assert(type_version != 0);\n            DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);\n            assert(tp->tp_dictoffset < 0);\n            assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);\n            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);\n            DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);\n            res = _PyDictOrValues_GetValues(dorv)->values[index];\n            DEOPT_IF(res == NULL, LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            Py_INCREF(res);\n            res2 = NULL;\n            #line 2536 \"Python/generated_cases.c.h\"\n            Py_DECREF(owner);\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }\n            next_instr += 9;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_ATTR_MODULE) {\n            PyObject *owner = stack_pointer[-1];\n            PyObject *res2 = NULL;\n            PyObject *res;\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            uint16_t index = read_u16(&next_instr[3].cache);\n            #line 1813 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR);\n            PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;\n            assert(dict != NULL);\n            DEOPT_IF(dict->ma_keys->dk_version != type_version, LOAD_ATTR);\n            assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE);\n            assert(index < dict->ma_keys->dk_nentries);\n            PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index;\n            res = ep->me_value;\n            DEOPT_IF(res == NULL, LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            Py_INCREF(res);\n            res2 = NULL;\n            #line 2564 \"Python/generated_cases.c.h\"\n            Py_DECREF(owner);\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }\n            next_instr += 9;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_ATTR_WITH_HINT) {\n            PyObject *owner = stack_pointer[-1];\n            PyObject *res2 = NULL;\n            PyObject *res;\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            uint16_t index = read_u16(&next_instr[3].cache);\n            #line 1829 \"Python/bytecodes.c\"\n            PyTypeObject *tp = Py_TYPE(owner);\n            assert(type_version != 0);\n            DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);\n            assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);\n            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);\n            DEOPT_IF(_PyDictOrValues_IsValues(dorv), LOAD_ATTR);\n            PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);\n            DEOPT_IF(dict == NULL, LOAD_ATTR);\n            assert(PyDict_CheckExact((PyObject *)dict));\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg>>1);\n            uint16_t hint = index;\n            DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR);\n            if (DK_IS_UNICODE(dict->ma_keys)) {\n                PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;\n                DEOPT_IF(ep->me_key != name, LOAD_ATTR);\n                res = ep->me_value;\n            }\n            else {\n                PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint;\n                DEOPT_IF(ep->me_key != name, LOAD_ATTR);\n                res = ep->me_value;\n            }\n            DEOPT_IF(res == NULL, LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            Py_INCREF(res);\n            res2 = NULL;\n            #line 2606 \"Python/generated_cases.c.h\"\n            Py_DECREF(owner);\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }\n            next_instr += 9;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_ATTR_SLOT) {\n            PyObject *owner = stack_pointer[-1];\n            PyObject *res2 = NULL;\n            PyObject *res;\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            uint16_t index = read_u16(&next_instr[3].cache);\n            #line 1859 \"Python/bytecodes.c\"\n            PyTypeObject *tp = Py_TYPE(owner);\n            assert(type_version != 0);\n            DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR);\n            char *addr = (char *)owner + index;\n            res = *(PyObject **)addr;\n            DEOPT_IF(res == NULL, LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            Py_INCREF(res);\n            res2 = NULL;\n            #line 2631 \"Python/generated_cases.c.h\"\n            Py_DECREF(owner);\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }\n            next_instr += 9;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_ATTR_CLASS) {\n            PyObject *cls = stack_pointer[-1];\n            PyObject *res2 = NULL;\n            PyObject *res;\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            PyObject *descr = read_obj(&next_instr[5].cache);\n            #line 1872 \"Python/bytecodes.c\"\n\n            DEOPT_IF(!PyType_Check(cls), LOAD_ATTR);\n            DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version,\n                LOAD_ATTR);\n            assert(type_version != 0);\n\n            STAT_INC(LOAD_ATTR, hit);\n            res2 = NULL;\n            res = descr;\n            assert(res != NULL);\n            Py_INCREF(res);\n            #line 2658 \"Python/generated_cases.c.h\"\n            Py_DECREF(cls);\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }\n            next_instr += 9;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_ATTR_PROPERTY) {\n            PyObject *owner = stack_pointer[-1];\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            uint32_t func_version = read_u32(&next_instr[3].cache);\n            PyObject *fget = read_obj(&next_instr[5].cache);\n            #line 1887 \"Python/bytecodes.c\"\n            DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);\n\n            PyTypeObject *cls = Py_TYPE(owner);\n            DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR);\n            assert(type_version != 0);\n            assert(Py_IS_TYPE(fget, &PyFunction_Type));\n            PyFunctionObject *f = (PyFunctionObject *)fget;\n            assert(func_version != 0);\n            DEOPT_IF(f->func_version != func_version, LOAD_ATTR);\n            PyCodeObject *code = (PyCodeObject *)f->func_code;\n            assert(code->co_argcount == 1);\n            DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            Py_INCREF(fget);\n            _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 1);\n            // Manipulate stack directly because we exit with DISPATCH_INLINED().\n            SET_TOP(NULL);\n            int shrink_stack = !(oparg & 1);\n            STACK_SHRINK(shrink_stack);\n            new_frame->localsplus[0] = owner;\n            JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);\n            frame->return_offset = 0;\n            DISPATCH_INLINED(new_frame);\n            #line 2696 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) {\n            PyObject *owner = stack_pointer[-1];\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            uint32_t func_version = read_u32(&next_instr[3].cache);\n            PyObject *getattribute = read_obj(&next_instr[5].cache);\n            #line 1913 \"Python/bytecodes.c\"\n            DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR);\n            PyTypeObject *cls = Py_TYPE(owner);\n            DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR);\n            assert(type_version != 0);\n            assert(Py_IS_TYPE(getattribute, &PyFunction_Type));\n            PyFunctionObject *f = (PyFunctionObject *)getattribute;\n            assert(func_version != 0);\n            DEOPT_IF(f->func_version != func_version, LOAD_ATTR);\n            PyCodeObject *code = (PyCodeObject *)f->func_code;\n            assert(code->co_argcount == 2);\n            DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg >> 1);\n            Py_INCREF(f);\n            _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2);\n            // Manipulate stack directly because we exit with DISPATCH_INLINED().\n            SET_TOP(NULL);\n            int shrink_stack = !(oparg & 1);\n            STACK_SHRINK(shrink_stack);\n            new_frame->localsplus[0] = owner;\n            new_frame->localsplus[1] = Py_NewRef(name);\n            JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);\n            frame->return_offset = 0;\n            DISPATCH_INLINED(new_frame);\n            #line 2730 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(STORE_ATTR_INSTANCE_VALUE) {\n            PyObject *owner = stack_pointer[-1];\n            PyObject *value = stack_pointer[-2];\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            uint16_t index = read_u16(&next_instr[3].cache);\n            #line 1941 \"Python/bytecodes.c\"\n            PyTypeObject *tp = Py_TYPE(owner);\n            assert(type_version != 0);\n            DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);\n            assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);\n            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);\n            DEOPT_IF(!_PyDictOrValues_IsValues(dorv), STORE_ATTR);\n            STAT_INC(STORE_ATTR, hit);\n            PyDictValues *values = _PyDictOrValues_GetValues(dorv);\n            PyObject *old_value = values->values[index];\n            values->values[index] = value;\n            if (old_value == NULL) {\n                _PyDictValues_AddToInsertionOrder(values, index);\n            }\n            else {\n                Py_DECREF(old_value);\n            }\n            Py_DECREF(owner);\n            #line 2756 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(2);\n            next_instr += 4;\n            DISPATCH();\n        }\n\n        TARGET(STORE_ATTR_WITH_HINT) {\n            PyObject *owner = stack_pointer[-1];\n            PyObject *value = stack_pointer[-2];\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            uint16_t hint = read_u16(&next_instr[3].cache);\n            #line 1961 \"Python/bytecodes.c\"\n            PyTypeObject *tp = Py_TYPE(owner);\n            assert(type_version != 0);\n            DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);\n            assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);\n            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);\n            DEOPT_IF(_PyDictOrValues_IsValues(dorv), STORE_ATTR);\n            PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);\n            DEOPT_IF(dict == NULL, STORE_ATTR);\n            assert(PyDict_CheckExact((PyObject *)dict));\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR);\n            PyObject *old_value;\n            uint64_t new_version;\n            if (DK_IS_UNICODE(dict->ma_keys)) {\n                PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;\n                DEOPT_IF(ep->me_key != name, STORE_ATTR);\n                old_value = ep->me_value;\n                DEOPT_IF(old_value == NULL, STORE_ATTR);\n                new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);\n                ep->me_value = value;\n            }\n            else {\n                PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint;\n                DEOPT_IF(ep->me_key != name, STORE_ATTR);\n                old_value = ep->me_value;\n                DEOPT_IF(old_value == NULL, STORE_ATTR);\n                new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);\n                ep->me_value = value;\n            }\n            Py_DECREF(old_value);\n            STAT_INC(STORE_ATTR, hit);\n            /* Ensure dict is GC tracked if it needs to be */\n            if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(value)) {\n                _PyObject_GC_TRACK(dict);\n            }\n            /* PEP 509 */\n            dict->ma_version_tag = new_version;\n            Py_DECREF(owner);\n            #line 2806 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(2);\n            next_instr += 4;\n            DISPATCH();\n        }\n\n        TARGET(STORE_ATTR_SLOT) {\n            PyObject *owner = stack_pointer[-1];\n            PyObject *value = stack_pointer[-2];\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            uint16_t index = read_u16(&next_instr[3].cache);\n            #line 2002 \"Python/bytecodes.c\"\n            PyTypeObject *tp = Py_TYPE(owner);\n            assert(type_version != 0);\n            DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);\n            char *addr = (char *)owner + index;\n            STAT_INC(STORE_ATTR, hit);\n            PyObject *old_value = *(PyObject **)addr;\n            *(PyObject **)addr = value;\n            Py_XDECREF(old_value);\n            Py_DECREF(owner);\n            #line 2827 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(2);\n            next_instr += 4;\n            DISPATCH();\n        }\n\n        TARGET(COMPARE_OP) {\n            PREDICTED(COMPARE_OP);\n            static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, \"incorrect cache size\");\n            PyObject *right = stack_pointer[-1];\n            PyObject *left = stack_pointer[-2];\n            PyObject *res;\n            #line 2021 \"Python/bytecodes.c\"\n            #if ENABLE_SPECIALIZATION\n            _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_CompareOp(left, right, next_instr, oparg);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(COMPARE_OP, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            assert((oparg >> 4) <= Py_GE);\n            res = PyObject_RichCompare(left, right, oparg>>4);\n            #line 2852 \"Python/generated_cases.c.h\"\n            Py_DECREF(left);\n            Py_DECREF(right);\n            #line 2034 \"Python/bytecodes.c\"\n            if (res == NULL) goto pop_2_error;\n            #line 2857 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(COMPARE_OP_FLOAT) {\n            PyObject *right = stack_pointer[-1];\n            PyObject *left = stack_pointer[-2];\n            PyObject *res;\n            #line 2038 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP);\n            DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP);\n            STAT_INC(COMPARE_OP, hit);\n            double dleft = PyFloat_AS_DOUBLE(left);\n            double dright = PyFloat_AS_DOUBLE(right);\n            // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg\n            int sign_ish = COMPARISON_BIT(dleft, dright);\n            _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);\n            _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);\n            res = (sign_ish & oparg) ? Py_True : Py_False;\n            #line 2879 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(COMPARE_OP_INT) {\n            PyObject *right = stack_pointer[-1];\n            PyObject *left = stack_pointer[-2];\n            PyObject *res;\n            #line 2052 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP);\n            DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP);\n            DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP);\n            DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_OP);\n            STAT_INC(COMPARE_OP, hit);\n            assert(_PyLong_DigitCount((PyLongObject *)left) <= 1 &&\n                   _PyLong_DigitCount((PyLongObject *)right) <= 1);\n            Py_ssize_t ileft = _PyLong_CompactValue((PyLongObject *)left);\n            Py_ssize_t iright = _PyLong_CompactValue((PyLongObject *)right);\n            // 2 if <, 4 if >, 8 if ==; this matches the low 4 bits of the oparg\n            int sign_ish = COMPARISON_BIT(ileft, iright);\n            _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);\n            _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);\n            res = (sign_ish & oparg) ? Py_True : Py_False;\n            #line 2905 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(COMPARE_OP_STR) {\n            PyObject *right = stack_pointer[-1];\n            PyObject *left = stack_pointer[-2];\n            PyObject *res;\n            #line 2070 \"Python/bytecodes.c\"\n            DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);\n            DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP);\n            STAT_INC(COMPARE_OP, hit);\n            int eq = _PyUnicode_Equal(left, right);\n            assert((oparg >>4) == Py_EQ || (oparg >>4) == Py_NE);\n            _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);\n            _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);\n            assert(eq == 0 || eq == 1);\n            assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS);\n            assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS);\n            res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False;\n            #line 2928 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(IS_OP) {\n            PyObject *right = stack_pointer[-1];\n            PyObject *left = stack_pointer[-2];\n            PyObject *b;\n            #line 2084 \"Python/bytecodes.c\"\n            int res = Py_Is(left, right) ^ oparg;\n            #line 2941 \"Python/generated_cases.c.h\"\n            Py_DECREF(left);\n            Py_DECREF(right);\n            #line 2086 \"Python/bytecodes.c\"\n            b = res ? Py_True : Py_False;\n            #line 2946 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = b;\n            DISPATCH();\n        }\n\n        TARGET(CONTAINS_OP) {\n            PyObject *right = stack_pointer[-1];\n            PyObject *left = stack_pointer[-2];\n            PyObject *b;\n            #line 2090 \"Python/bytecodes.c\"\n            int res = PySequence_Contains(right, left);\n            #line 2958 \"Python/generated_cases.c.h\"\n            Py_DECREF(left);\n            Py_DECREF(right);\n            #line 2092 \"Python/bytecodes.c\"\n            if (res < 0) goto pop_2_error;\n            b = (res ^ oparg) ? Py_True : Py_False;\n            #line 2964 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = b;\n            DISPATCH();\n        }\n\n        TARGET(CHECK_EG_MATCH) {\n            PyObject *match_type = stack_pointer[-1];\n            PyObject *exc_value = stack_pointer[-2];\n            PyObject *rest;\n            PyObject *match;\n            #line 2097 \"Python/bytecodes.c\"\n            if (check_except_star_type_valid(tstate, match_type) < 0) {\n            #line 2977 \"Python/generated_cases.c.h\"\n                Py_DECREF(exc_value);\n                Py_DECREF(match_type);\n            #line 2099 \"Python/bytecodes.c\"\n                if (true) goto pop_2_error;\n            }\n\n            match = NULL;\n            rest = NULL;\n            int res = exception_group_match(exc_value, match_type,\n                                            &match, &rest);\n            #line 2988 \"Python/generated_cases.c.h\"\n            Py_DECREF(exc_value);\n            Py_DECREF(match_type);\n            #line 2107 \"Python/bytecodes.c\"\n            if (res < 0) goto pop_2_error;\n\n            assert((match == NULL) == (rest == NULL));\n            if (match == NULL) goto pop_2_error;\n\n            if (!Py_IsNone(match)) {\n                PyErr_SetHandledException(match);\n            }\n            #line 3000 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = match;\n            stack_pointer[-2] = rest;\n            DISPATCH();\n        }\n\n        TARGET(CHECK_EXC_MATCH) {\n            PyObject *right = stack_pointer[-1];\n            PyObject *left = stack_pointer[-2];\n            PyObject *b;\n            #line 2118 \"Python/bytecodes.c\"\n            assert(PyExceptionInstance_Check(left));\n            if (check_except_type_valid(tstate, right) < 0) {\n            #line 3013 \"Python/generated_cases.c.h\"\n                 Py_DECREF(right);\n            #line 2121 \"Python/bytecodes.c\"\n                 if (true) goto pop_1_error;\n            }\n\n            int res = PyErr_GivenExceptionMatches(left, right);\n            #line 3020 \"Python/generated_cases.c.h\"\n            Py_DECREF(right);\n            #line 2126 \"Python/bytecodes.c\"\n            b = res ? Py_True : Py_False;\n            #line 3024 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = b;\n            DISPATCH();\n        }\n\n        TARGET(IMPORT_NAME) {\n            PyObject *fromlist = stack_pointer[-1];\n            PyObject *level = stack_pointer[-2];\n            PyObject *res;\n            #line 2130 \"Python/bytecodes.c\"\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            res = import_name(tstate, frame, name, fromlist, level);\n            #line 3036 \"Python/generated_cases.c.h\"\n            Py_DECREF(level);\n            Py_DECREF(fromlist);\n            #line 2133 \"Python/bytecodes.c\"\n            if (res == NULL) goto pop_2_error;\n            #line 3041 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            DISPATCH();\n        }\n\n        TARGET(IMPORT_FROM) {\n            PyObject *from = stack_pointer[-1];\n            PyObject *res;\n            #line 2137 \"Python/bytecodes.c\"\n            PyObject *name = GETITEM(frame->f_code->co_names, oparg);\n            res = import_from(tstate, from, name);\n            if (res == NULL) goto error;\n            #line 3054 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = res;\n            DISPATCH();\n        }\n\n        TARGET(JUMP_FORWARD) {\n            #line 2143 \"Python/bytecodes.c\"\n            JUMPBY(oparg);\n            #line 3063 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(JUMP_BACKWARD) {\n            #line 2147 \"Python/bytecodes.c\"\n            _Py_CODEUNIT *here = next_instr - 1;\n            assert(oparg <= INSTR_OFFSET());\n            JUMPBY(1-oparg);\n            #if ENABLE_SPECIALIZATION\n            here[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER);\n            if (here[1].cache > tstate->interp->optimizer_backedge_threshold) {\n                OBJECT_STAT_INC(optimization_attempts);\n                frame = _PyOptimizer_BackEdge(frame, here, next_instr, stack_pointer);\n                if (frame == NULL) {\n                    frame = cframe.current_frame;\n                    goto error;\n                }\n                here[1].cache &= ((1 << OPTIMIZER_BITS_IN_COUNTER) -1);\n                goto resume_frame;\n            }\n            #endif  /* ENABLE_SPECIALIZATION */\n            #line 3085 \"Python/generated_cases.c.h\"\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(ENTER_EXECUTOR) {\n            #line 2177 \"Python/bytecodes.c\"\n            _PyExecutorObject *executor = (_PyExecutorObject *)frame->f_code->co_executors->executors[oparg];\n            Py_INCREF(executor);\n            frame = executor->execute(executor, frame, stack_pointer);\n            if (frame == NULL) {\n                frame = cframe.current_frame;\n                goto error;\n            }\n            goto resume_frame;\n            #line 3100 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(POP_JUMP_IF_FALSE) {\n            PyObject *cond = stack_pointer[-1];\n            #line 2188 \"Python/bytecodes.c\"\n            if (Py_IsFalse(cond)) {\n                JUMPBY(oparg);\n            }\n            else if (!Py_IsTrue(cond)) {\n                int err = PyObject_IsTrue(cond);\n            #line 3111 \"Python/generated_cases.c.h\"\n                Py_DECREF(cond);\n            #line 2194 \"Python/bytecodes.c\"\n                if (err == 0) {\n                    JUMPBY(oparg);\n                }\n                else {\n                    if (err < 0) goto pop_1_error;\n                }\n            }\n            #line 3121 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(POP_JUMP_IF_TRUE) {\n            PyObject *cond = stack_pointer[-1];\n            #line 2204 \"Python/bytecodes.c\"\n            if (Py_IsTrue(cond)) {\n                JUMPBY(oparg);\n            }\n            else if (!Py_IsFalse(cond)) {\n                int err = PyObject_IsTrue(cond);\n            #line 3134 \"Python/generated_cases.c.h\"\n                Py_DECREF(cond);\n            #line 2210 \"Python/bytecodes.c\"\n                if (err > 0) {\n                    JUMPBY(oparg);\n                }\n                else {\n                    if (err < 0) goto pop_1_error;\n                }\n            }\n            #line 3144 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(POP_JUMP_IF_NOT_NONE) {\n            PyObject *value = stack_pointer[-1];\n            #line 2220 \"Python/bytecodes.c\"\n            if (!Py_IsNone(value)) {\n            #line 3153 \"Python/generated_cases.c.h\"\n                Py_DECREF(value);\n            #line 2222 \"Python/bytecodes.c\"\n                JUMPBY(oparg);\n            }\n            #line 3158 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(POP_JUMP_IF_NONE) {\n            PyObject *value = stack_pointer[-1];\n            #line 2227 \"Python/bytecodes.c\"\n            if (Py_IsNone(value)) {\n                JUMPBY(oparg);\n            }\n            else {\n            #line 3170 \"Python/generated_cases.c.h\"\n                Py_DECREF(value);\n            #line 2232 \"Python/bytecodes.c\"\n            }\n            #line 3174 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            DISPATCH();\n        }\n\n        TARGET(JUMP_BACKWARD_NO_INTERRUPT) {\n            #line 2236 \"Python/bytecodes.c\"\n            /* This bytecode is used in the `yield from` or `await` loop.\n             * If there is an interrupt, we want it handled in the innermost\n             * generator or coroutine, so we deliberately do not check it here.\n             * (see bpo-30039).\n             */\n            JUMPBY(-oparg);\n            #line 3187 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(GET_LEN) {\n            PyObject *obj = stack_pointer[-1];\n            PyObject *len_o;\n            #line 2245 \"Python/bytecodes.c\"\n            // PUSH(len(TOS))\n            Py_ssize_t len_i = PyObject_Length(obj);\n            if (len_i < 0) goto error;\n            len_o = PyLong_FromSsize_t(len_i);\n            if (len_o == NULL) goto error;\n            #line 3200 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = len_o;\n            DISPATCH();\n        }\n\n        TARGET(MATCH_CLASS) {\n            PyObject *names = stack_pointer[-1];\n            PyObject *type = stack_pointer[-2];\n            PyObject *subject = stack_pointer[-3];\n            PyObject *attrs;\n            #line 2253 \"Python/bytecodes.c\"\n            // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or\n            // None on failure.\n            assert(PyTuple_CheckExact(names));\n            attrs = match_class(tstate, subject, type, oparg, names);\n            #line 3216 \"Python/generated_cases.c.h\"\n            Py_DECREF(subject);\n            Py_DECREF(type);\n            Py_DECREF(names);\n            #line 2258 \"Python/bytecodes.c\"\n            if (attrs) {\n                assert(PyTuple_CheckExact(attrs));  // Success!\n            }\n            else {\n                if (_PyErr_Occurred(tstate)) goto pop_3_error;\n                attrs = Py_None;  // Failure!\n            }\n            #line 3228 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(2);\n            stack_pointer[-1] = attrs;\n            DISPATCH();\n        }\n\n        TARGET(MATCH_MAPPING) {\n            PyObject *subject = stack_pointer[-1];\n            PyObject *res;\n            #line 2268 \"Python/bytecodes.c\"\n            int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING;\n            res = match ? Py_True : Py_False;\n            #line 3240 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = res;\n            DISPATCH();\n        }\n\n        TARGET(MATCH_SEQUENCE) {\n            PyObject *subject = stack_pointer[-1];\n            PyObject *res;\n            #line 2273 \"Python/bytecodes.c\"\n            int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE;\n            res = match ? Py_True : Py_False;\n            #line 3252 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = res;\n            DISPATCH();\n        }\n\n        TARGET(MATCH_KEYS) {\n            PyObject *keys = stack_pointer[-1];\n            PyObject *subject = stack_pointer[-2];\n            PyObject *values_or_none;\n            #line 2278 \"Python/bytecodes.c\"\n            // On successful match, PUSH(values). Otherwise, PUSH(None).\n            values_or_none = match_keys(tstate, subject, keys);\n            if (values_or_none == NULL) goto error;\n            #line 3266 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = values_or_none;\n            DISPATCH();\n        }\n\n        TARGET(GET_ITER) {\n            PyObject *iterable = stack_pointer[-1];\n            PyObject *iter;\n            #line 2284 \"Python/bytecodes.c\"\n            /* before: [obj]; after [getiter(obj)] */\n            iter = PyObject_GetIter(iterable);\n            #line 3278 \"Python/generated_cases.c.h\"\n            Py_DECREF(iterable);\n            #line 2287 \"Python/bytecodes.c\"\n            if (iter == NULL) goto pop_1_error;\n            #line 3282 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = iter;\n            DISPATCH();\n        }\n\n        TARGET(GET_YIELD_FROM_ITER) {\n            PyObject *iterable = stack_pointer[-1];\n            PyObject *iter;\n            #line 2291 \"Python/bytecodes.c\"\n            /* before: [obj]; after [getiter(obj)] */\n            if (PyCoro_CheckExact(iterable)) {\n                /* `iterable` is a coroutine */\n                if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {\n                    /* and it is used in a 'yield from' expression of a\n                       regular generator. */\n                    _PyErr_SetString(tstate, PyExc_TypeError,\n                                     \"cannot 'yield from' a coroutine object \"\n                                     \"in a non-coroutine generator\");\n                    goto error;\n                }\n                iter = iterable;\n            }\n            else if (PyGen_CheckExact(iterable)) {\n                iter = iterable;\n            }\n            else {\n                /* `iterable` is not a generator. */\n                iter = PyObject_GetIter(iterable);\n                if (iter == NULL) {\n                    goto error;\n                }\n            #line 3313 \"Python/generated_cases.c.h\"\n                Py_DECREF(iterable);\n            #line 2314 \"Python/bytecodes.c\"\n            }\n            #line 3317 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = iter;\n            DISPATCH();\n        }\n\n        TARGET(FOR_ITER) {\n            PREDICTED(FOR_ITER);\n            static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, \"incorrect cache size\");\n            PyObject *iter = stack_pointer[-1];\n            PyObject *next;\n            #line 2332 \"Python/bytecodes.c\"\n            #if ENABLE_SPECIALIZATION\n            _PyForIterCache *cache = (_PyForIterCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_ForIter(iter, next_instr, oparg);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(FOR_ITER, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */\n            next = (*Py_TYPE(iter)->tp_iternext)(iter);\n            if (next == NULL) {\n                if (_PyErr_Occurred(tstate)) {\n                    if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) {\n                        goto error;\n                    }\n                    monitor_raise(tstate, frame, next_instr-1);\n                    _PyErr_Clear(tstate);\n                }\n                /* iterator ended normally */\n                assert(next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == END_FOR ||\n                       next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == INSTRUMENTED_END_FOR);\n                Py_DECREF(iter);\n                STACK_SHRINK(1);\n                /* Jump forward oparg, then skip following END_FOR instruction */\n                JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);\n                DISPATCH();\n            }\n            // Common case: no jump, leave it to the code generator\n            #line 3358 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = next;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_FOR_ITER) {\n            #line 2365 \"Python/bytecodes.c\"\n            _Py_CODEUNIT *here = next_instr-1;\n            _Py_CODEUNIT *target;\n            PyObject *iter = TOP();\n            PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter);\n            if (next != NULL) {\n                PUSH(next);\n                target = next_instr + INLINE_CACHE_ENTRIES_FOR_ITER;\n            }\n            else {\n                if (_PyErr_Occurred(tstate)) {\n                    if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) {\n                        goto error;\n                    }\n                    monitor_raise(tstate, frame, here);\n                    _PyErr_Clear(tstate);\n                }\n                /* iterator ended normally */\n                assert(next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == END_FOR ||\n                       next_instr[INLINE_CACHE_ENTRIES_FOR_ITER + oparg].op.code == INSTRUMENTED_END_FOR);\n                STACK_SHRINK(1);\n                Py_DECREF(iter);\n                /* Skip END_FOR */\n                target = next_instr + INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1;\n            }\n            INSTRUMENTED_JUMP(here, target, PY_MONITORING_EVENT_BRANCH);\n            #line 3392 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(FOR_ITER_LIST) {\n            PyObject *iter = stack_pointer[-1];\n            PyObject *next;\n            #line 2393 \"Python/bytecodes.c\"\n            DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, FOR_ITER);\n            _PyListIterObject *it = (_PyListIterObject *)iter;\n            STAT_INC(FOR_ITER, hit);\n            PyListObject *seq = it->it_seq;\n            if (seq) {\n                if (it->it_index < PyList_GET_SIZE(seq)) {\n                    next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++));\n                    goto end_for_iter_list;  // End of this instruction\n                }\n                it->it_seq = NULL;\n                Py_DECREF(seq);\n            }\n            Py_DECREF(iter);\n            STACK_SHRINK(1);\n            /* Jump forward oparg, then skip following END_FOR instruction */\n            JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);\n            DISPATCH();\n        end_for_iter_list:\n            // Common case: no jump, leave it to the code generator\n            #line 3419 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = next;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(FOR_ITER_TUPLE) {\n            PyObject *iter = stack_pointer[-1];\n            PyObject *next;\n            #line 2415 \"Python/bytecodes.c\"\n            _PyTupleIterObject *it = (_PyTupleIterObject *)iter;\n            DEOPT_IF(Py_TYPE(it) != &PyTupleIter_Type, FOR_ITER);\n            STAT_INC(FOR_ITER, hit);\n            PyTupleObject *seq = it->it_seq;\n            if (seq) {\n                if (it->it_index < PyTuple_GET_SIZE(seq)) {\n                    next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++));\n                    goto end_for_iter_tuple;  // End of this instruction\n                }\n                it->it_seq = NULL;\n                Py_DECREF(seq);\n            }\n            Py_DECREF(iter);\n            STACK_SHRINK(1);\n            /* Jump forward oparg, then skip following END_FOR instruction */\n            JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);\n            DISPATCH();\n        end_for_iter_tuple:\n            // Common case: no jump, leave it to the code generator\n            #line 3449 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = next;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(FOR_ITER_RANGE) {\n            PyObject *iter = stack_pointer[-1];\n            PyObject *next;\n            #line 2437 \"Python/bytecodes.c\"\n            _PyRangeIterObject *r = (_PyRangeIterObject *)iter;\n            DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER);\n            STAT_INC(FOR_ITER, hit);\n            if (r->len <= 0) {\n                STACK_SHRINK(1);\n                Py_DECREF(r);\n                // Jump over END_FOR instruction.\n                JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1);\n                DISPATCH();\n            }\n            long value = r->start;\n            r->start = value + r->step;\n            r->len--;\n            next = PyLong_FromLong(value);\n            if (next == NULL) {\n                goto error;\n            }\n            #line 3477 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = next;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(FOR_ITER_GEN) {\n            PyObject *iter = stack_pointer[-1];\n            #line 2457 \"Python/bytecodes.c\"\n            DEOPT_IF(tstate->interp->eval_frame, FOR_ITER);\n            PyGenObject *gen = (PyGenObject *)iter;\n            DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER);\n            DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, FOR_ITER);\n            STAT_INC(FOR_ITER, hit);\n            _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;\n            frame->return_offset = oparg;\n            _PyFrame_StackPush(gen_frame, Py_None);\n            gen->gi_frame_state = FRAME_EXECUTING;\n            gen->gi_exc_state.previous_item = tstate->exc_info;\n            tstate->exc_info = &gen->gi_exc_state;\n            JUMPBY(INLINE_CACHE_ENTRIES_FOR_ITER);\n            assert(next_instr[oparg].op.code == END_FOR ||\n                   next_instr[oparg].op.code == INSTRUMENTED_END_FOR);\n            DISPATCH_INLINED(gen_frame);\n            #line 3502 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(BEFORE_ASYNC_WITH) {\n            PyObject *mgr = stack_pointer[-1];\n            PyObject *exit;\n            PyObject *res;\n            #line 2475 \"Python/bytecodes.c\"\n            PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__));\n            if (enter == NULL) {\n                if (!_PyErr_Occurred(tstate)) {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                  \"'%.200s' object does not support the \"\n                                  \"asynchronous context manager protocol\",\n                                  Py_TYPE(mgr)->tp_name);\n                }\n                goto error;\n            }\n            exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__));\n            if (exit == NULL) {\n                if (!_PyErr_Occurred(tstate)) {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                  \"'%.200s' object does not support the \"\n                                  \"asynchronous context manager protocol \"\n                                  \"(missed __aexit__ method)\",\n                                  Py_TYPE(mgr)->tp_name);\n                }\n                Py_DECREF(enter);\n                goto error;\n            }\n            #line 3532 \"Python/generated_cases.c.h\"\n            Py_DECREF(mgr);\n            #line 2498 \"Python/bytecodes.c\"\n            res = _PyObject_CallNoArgs(enter);\n            Py_DECREF(enter);\n            if (res == NULL) {\n                Py_DECREF(exit);\n                if (true) goto pop_1_error;\n            }\n            #line 3541 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = res;\n            stack_pointer[-2] = exit;\n            DISPATCH();\n        }\n\n        TARGET(BEFORE_WITH) {\n            PyObject *mgr = stack_pointer[-1];\n            PyObject *exit;\n            PyObject *res;\n            #line 2507 \"Python/bytecodes.c\"\n            /* pop the context manager, push its __exit__ and the\n             * value returned from calling its __enter__\n             */\n            PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__enter__));\n            if (enter == NULL) {\n                if (!_PyErr_Occurred(tstate)) {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                  \"'%.200s' object does not support the \"\n                                  \"context manager protocol\",\n                                  Py_TYPE(mgr)->tp_name);\n                }\n                goto error;\n            }\n            exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__));\n            if (exit == NULL) {\n                if (!_PyErr_Occurred(tstate)) {\n                    _PyErr_Format(tstate, PyExc_TypeError,\n                                  \"'%.200s' object does not support the \"\n                                  \"context manager protocol \"\n                                  \"(missed __exit__ method)\",\n                                  Py_TYPE(mgr)->tp_name);\n                }\n                Py_DECREF(enter);\n                goto error;\n            }\n            #line 3578 \"Python/generated_cases.c.h\"\n            Py_DECREF(mgr);\n            #line 2533 \"Python/bytecodes.c\"\n            res = _PyObject_CallNoArgs(enter);\n            Py_DECREF(enter);\n            if (res == NULL) {\n                Py_DECREF(exit);\n                if (true) goto pop_1_error;\n            }\n            #line 3587 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = res;\n            stack_pointer[-2] = exit;\n            DISPATCH();\n        }\n\n        TARGET(WITH_EXCEPT_START) {\n            PyObject *val = stack_pointer[-1];\n            PyObject *lasti = stack_pointer[-3];\n            PyObject *exit_func = stack_pointer[-4];\n            PyObject *res;\n            #line 2542 \"Python/bytecodes.c\"\n            /* At the top of the stack are 4 values:\n               - val: TOP = exc_info()\n               - unused: SECOND = previous exception\n               - lasti: THIRD = lasti of exception in exc_info()\n               - exit_func: FOURTH = the context.__exit__ bound method\n               We call FOURTH(type(TOP), TOP, GetTraceback(TOP)).\n               Then we push the __exit__ return value.\n            */\n            PyObject *exc, *tb;\n\n            assert(val && PyExceptionInstance_Check(val));\n            exc = PyExceptionInstance_Class(val);\n            tb = PyException_GetTraceback(val);\n            Py_XDECREF(tb);\n            assert(PyLong_Check(lasti));\n            (void)lasti; // Shut up compiler warning if asserts are off\n            PyObject *stack[4] = {NULL, exc, val, tb};\n            res = PyObject_Vectorcall(exit_func, stack + 1,\n                    3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);\n            if (res == NULL) goto error;\n            #line 3620 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = res;\n            DISPATCH();\n        }\n\n        TARGET(PUSH_EXC_INFO) {\n            PyObject *new_exc = stack_pointer[-1];\n            PyObject *prev_exc;\n            #line 2581 \"Python/bytecodes.c\"\n            _PyErr_StackItem *exc_info = tstate->exc_info;\n            if (exc_info->exc_value != NULL) {\n                prev_exc = exc_info->exc_value;\n            }\n            else {\n                prev_exc = Py_None;\n            }\n            assert(PyExceptionInstance_Check(new_exc));\n            exc_info->exc_value = Py_NewRef(new_exc);\n            #line 3639 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = new_exc;\n            stack_pointer[-2] = prev_exc;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_ATTR_METHOD_WITH_VALUES) {\n            PyObject *self = stack_pointer[-1];\n            PyObject *res2 = NULL;\n            PyObject *res;\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            uint32_t keys_version = read_u32(&next_instr[3].cache);\n            PyObject *descr = read_obj(&next_instr[5].cache);\n            #line 2593 \"Python/bytecodes.c\"\n            /* Cached method object */\n            PyTypeObject *self_cls = Py_TYPE(self);\n            assert(type_version != 0);\n            DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);\n            assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT);\n            PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(self);\n            DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR);\n            PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls;\n            DEOPT_IF(self_heap_type->ht_cached_keys->dk_version !=\n                     keys_version, LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            assert(descr != NULL);\n            res2 = Py_NewRef(descr);\n            assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR));\n            res = self;\n            assert(oparg & 1);\n            #line 3670 \"Python/generated_cases.c.h\"\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }\n            next_instr += 9;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_ATTR_METHOD_NO_DICT) {\n            PyObject *self = stack_pointer[-1];\n            PyObject *res2 = NULL;\n            PyObject *res;\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            PyObject *descr = read_obj(&next_instr[5].cache);\n            #line 2612 \"Python/bytecodes.c\"\n            PyTypeObject *self_cls = Py_TYPE(self);\n            DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);\n            assert(self_cls->tp_dictoffset == 0);\n            STAT_INC(LOAD_ATTR, hit);\n            assert(descr != NULL);\n            assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));\n            res2 = Py_NewRef(descr);\n            res = self;\n            assert(oparg & 1);\n            #line 3694 \"Python/generated_cases.c.h\"\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }\n            next_instr += 9;\n            DISPATCH();\n        }\n\n        TARGET(LOAD_ATTR_METHOD_LAZY_DICT) {\n            PyObject *self = stack_pointer[-1];\n            PyObject *res2 = NULL;\n            PyObject *res;\n            uint32_t type_version = read_u32(&next_instr[1].cache);\n            PyObject *descr = read_obj(&next_instr[5].cache);\n            #line 2624 \"Python/bytecodes.c\"\n            PyTypeObject *self_cls = Py_TYPE(self);\n            DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR);\n            Py_ssize_t dictoffset = self_cls->tp_dictoffset;\n            assert(dictoffset > 0);\n            PyObject *dict = *(PyObject **)((char *)self + dictoffset);\n            /* This object has a __dict__, just not yet created */\n            DEOPT_IF(dict != NULL, LOAD_ATTR);\n            STAT_INC(LOAD_ATTR, hit);\n            assert(descr != NULL);\n            assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));\n            res2 = Py_NewRef(descr);\n            res = self;\n            assert(oparg & 1);\n            #line 3722 \"Python/generated_cases.c.h\"\n            STACK_GROW(((oparg & 1) ? 1 : 0));\n            stack_pointer[-1] = res;\n            if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; }\n            next_instr += 9;\n            DISPATCH();\n        }\n\n        TARGET(KW_NAMES) {\n            #line 2640 \"Python/bytecodes.c\"\n            assert(kwnames == NULL);\n            assert(oparg < PyTuple_GET_SIZE(frame->f_code->co_consts));\n            kwnames = GETITEM(frame->f_code->co_consts, oparg);\n            #line 3735 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_CALL) {\n            #line 2646 \"Python/bytecodes.c\"\n            int is_meth = PEEK(oparg+2) != NULL;\n            int total_args = oparg + is_meth;\n            PyObject *function = PEEK(total_args + 1);\n            PyObject *arg = total_args == 0 ?\n                &_PyInstrumentation_MISSING : PEEK(total_args);\n            int err = _Py_call_instrumentation_2args(\n                    tstate, PY_MONITORING_EVENT_CALL,\n                    frame, next_instr-1, function, arg);\n            if (err) goto error;\n            _PyCallCache *cache = (_PyCallCache *)next_instr;\n            INCREMENT_ADAPTIVE_COUNTER(cache->counter);\n            GO_TO_INSTRUCTION(CALL);\n            #line 3753 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(CALL) {\n            PREDICTED(CALL);\n            static_assert(INLINE_CACHE_ENTRIES_CALL == 3, \"incorrect cache size\");\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 2691 \"Python/bytecodes.c\"\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            #if ENABLE_SPECIALIZATION\n            _PyCallCache *cache = (_PyCallCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_Call(callable, next_instr, total_args, kwnames);\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(CALL, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            if (!is_meth && Py_TYPE(callable) == &PyMethod_Type) {\n                is_meth = 1;  // For consistenct; it's dead, though\n                args--;\n                total_args++;\n                PyObject *self = ((PyMethodObject *)callable)->im_self;\n                args[0] = Py_NewRef(self);\n                method = ((PyMethodObject *)callable)->im_func;\n                args[-1] = Py_NewRef(method);\n                Py_DECREF(callable);\n                callable = method;\n            }\n            int positional_args = total_args - KWNAMES_LEN();\n            // Check if the call can be inlined or not\n            if (Py_TYPE(callable) == &PyFunction_Type &&\n                tstate->interp->eval_frame == NULL &&\n                ((PyFunctionObject *)callable)->vectorcall == _PyFunction_Vectorcall)\n            {\n                int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags;\n                PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));\n                _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(\n                    tstate, (PyFunctionObject *)callable, locals,\n                    args, positional_args, kwnames\n                );\n                kwnames = NULL;\n                // Manipulate stack directly since we leave using DISPATCH_INLINED().\n                STACK_SHRINK(oparg + 2);\n                // The frame has stolen all the arguments from the stack,\n                // so there is no need to clean them up.\n                if (new_frame == NULL) {\n                    goto error;\n                }\n                JUMPBY(INLINE_CACHE_ENTRIES_CALL);\n                frame->return_offset = 0;\n                DISPATCH_INLINED(new_frame);\n            }\n            /* Callable is not a normal Python function */\n            res = PyObject_Vectorcall(\n                callable, args,\n                positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET,\n                kwnames);\n            if (opcode == INSTRUMENTED_CALL) {\n                PyObject *arg = total_args == 0 ?\n                    &_PyInstrumentation_MISSING : PEEK(total_args);\n                if (res == NULL) {\n                    _Py_call_instrumentation_exc2(\n                        tstate, PY_MONITORING_EVENT_C_RAISE,\n                        frame, next_instr-1, callable, arg);\n                }\n                else {\n                    int err = _Py_call_instrumentation_2args(\n                        tstate, PY_MONITORING_EVENT_C_RETURN,\n                        frame, next_instr-1, callable, arg);\n                    if (err < 0) {\n                        Py_CLEAR(res);\n                    }\n                }\n            }\n            kwnames = NULL;\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n            Py_DECREF(callable);\n            for (int i = 0; i < total_args; i++) {\n                Py_DECREF(args[i]);\n            }\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n            #line 3845 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(CALL_BOUND_METHOD_EXACT_ARGS) {\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            #line 2779 \"Python/bytecodes.c\"\n            DEOPT_IF(method != NULL, CALL);\n            DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL);\n            STAT_INC(CALL, hit);\n            PyObject *self = ((PyMethodObject *)callable)->im_self;\n            PEEK(oparg + 1) = Py_NewRef(self);  // callable\n            PyObject *meth = ((PyMethodObject *)callable)->im_func;\n            PEEK(oparg + 2) = Py_NewRef(meth);  // method\n            Py_DECREF(callable);\n            GO_TO_INSTRUCTION(CALL_PY_EXACT_ARGS);\n            #line 3867 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(CALL_PY_EXACT_ARGS) {\n            PREDICTED(CALL_PY_EXACT_ARGS);\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            uint32_t func_version = read_u32(&next_instr[1].cache);\n            #line 2791 \"Python/bytecodes.c\"\n            assert(kwnames == NULL);\n            DEOPT_IF(tstate->interp->eval_frame, CALL);\n            int is_meth = method != NULL;\n            int argcount = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                argcount++;\n            }\n            DEOPT_IF(!PyFunction_Check(callable), CALL);\n            PyFunctionObject *func = (PyFunctionObject *)callable;\n            DEOPT_IF(func->func_version != func_version, CALL);\n            PyCodeObject *code = (PyCodeObject *)func->func_code;\n            DEOPT_IF(code->co_argcount != argcount, CALL);\n            DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL);\n            STAT_INC(CALL, hit);\n            _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, func, argcount);\n            for (int i = 0; i < argcount; i++) {\n                new_frame->localsplus[i] = args[i];\n            }\n            // Manipulate stack directly since we leave using DISPATCH_INLINED().\n            STACK_SHRINK(oparg + 2);\n            JUMPBY(INLINE_CACHE_ENTRIES_CALL);\n            frame->return_offset = 0;\n            DISPATCH_INLINED(new_frame);\n            #line 3902 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(CALL_PY_WITH_DEFAULTS) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            uint32_t func_version = read_u32(&next_instr[1].cache);\n            #line 2819 \"Python/bytecodes.c\"\n            assert(kwnames == NULL);\n            DEOPT_IF(tstate->interp->eval_frame, CALL);\n            int is_meth = method != NULL;\n            int argcount = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                argcount++;\n            }\n            DEOPT_IF(!PyFunction_Check(callable), CALL);\n            PyFunctionObject *func = (PyFunctionObject *)callable;\n            DEOPT_IF(func->func_version != func_version, CALL);\n            PyCodeObject *code = (PyCodeObject *)func->func_code;\n            assert(func->func_defaults);\n            assert(PyTuple_CheckExact(func->func_defaults));\n            int defcount = (int)PyTuple_GET_SIZE(func->func_defaults);\n            assert(defcount <= code->co_argcount);\n            int min_args = code->co_argcount - defcount;\n            DEOPT_IF(argcount > code->co_argcount, CALL);\n            DEOPT_IF(argcount < min_args, CALL);\n            DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL);\n            STAT_INC(CALL, hit);\n            _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, func, code->co_argcount);\n            for (int i = 0; i < argcount; i++) {\n                new_frame->localsplus[i] = args[i];\n            }\n            for (int i = argcount; i < code->co_argcount; i++) {\n                PyObject *def = PyTuple_GET_ITEM(func->func_defaults, i - min_args);\n                new_frame->localsplus[i] = Py_NewRef(def);\n            }\n            // Manipulate stack and cache directly since we leave using DISPATCH_INLINED().\n            STACK_SHRINK(oparg + 2);\n            JUMPBY(INLINE_CACHE_ENTRIES_CALL);\n            frame->return_offset = 0;\n            DISPATCH_INLINED(new_frame);\n            #line 3946 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(CALL_NO_KW_TYPE_1) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *null = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 2857 \"Python/bytecodes.c\"\n            assert(kwnames == NULL);\n            assert(oparg == 1);\n            DEOPT_IF(null != NULL, CALL);\n            PyObject *obj = args[0];\n            DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL);\n            STAT_INC(CALL, hit);\n            res = Py_NewRef(Py_TYPE(obj));\n            Py_DECREF(obj);\n            Py_DECREF(&PyType_Type);  // I.e., callable\n            #line 3964 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            DISPATCH();\n        }\n\n        TARGET(CALL_NO_KW_STR_1) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *null = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 2869 \"Python/bytecodes.c\"\n            assert(kwnames == NULL);\n            assert(oparg == 1);\n            DEOPT_IF(null != NULL, CALL);\n            DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, CALL);\n            STAT_INC(CALL, hit);\n            PyObject *arg = args[0];\n            res = PyObject_Str(arg);\n            Py_DECREF(arg);\n            Py_DECREF(&PyUnicode_Type);  // I.e., callable\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n            #line 3988 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(CALL_NO_KW_TUPLE_1) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *null = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 2883 \"Python/bytecodes.c\"\n            assert(kwnames == NULL);\n            assert(oparg == 1);\n            DEOPT_IF(null != NULL, CALL);\n            DEOPT_IF(callable != (PyObject *)&PyTuple_Type, CALL);\n            STAT_INC(CALL, hit);\n            PyObject *arg = args[0];\n            res = PySequence_Tuple(arg);\n            Py_DECREF(arg);\n            Py_DECREF(&PyTuple_Type);  // I.e., tuple\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n            #line 4013 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(CALL_BUILTIN_CLASS) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 2897 \"Python/bytecodes.c\"\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            int kwnames_len = KWNAMES_LEN();\n            DEOPT_IF(!PyType_Check(callable), CALL);\n            PyTypeObject *tp = (PyTypeObject *)callable;\n            DEOPT_IF(tp->tp_vectorcall == NULL, CALL);\n            STAT_INC(CALL, hit);\n            res = tp->tp_vectorcall((PyObject *)tp, args,\n                                    total_args - kwnames_len, kwnames);\n            kwnames = NULL;\n            /* Free the arguments. */\n            for (int i = 0; i < total_args; i++) {\n                Py_DECREF(args[i]);\n            }\n            Py_DECREF(tp);\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n            #line 4049 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(CALL_NO_KW_BUILTIN_O) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 2922 \"Python/bytecodes.c\"\n            /* Builtin METH_O functions */\n            assert(kwnames == NULL);\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            DEOPT_IF(total_args != 1, CALL);\n            DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);\n            DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL);\n            STAT_INC(CALL, hit);\n            PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);\n            // This is slower but CPython promises to check all non-vectorcall\n            // function calls.\n            if (_Py_EnterRecursiveCallTstate(tstate, \" while calling a Python object\")) {\n                goto error;\n            }\n            PyObject *arg = args[0];\n            res = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable), arg);\n            _Py_LeaveRecursiveCallTstate(tstate);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n\n            Py_DECREF(arg);\n            Py_DECREF(callable);\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n            #line 4091 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(CALL_NO_KW_BUILTIN_FAST) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 2953 \"Python/bytecodes.c\"\n            /* Builtin METH_FASTCALL functions, without keywords */\n            assert(kwnames == NULL);\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);\n            DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL, CALL);\n            STAT_INC(CALL, hit);\n            PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);\n            /* res = func(self, args, nargs) */\n            res = ((_PyCFunctionFast)(void(*)(void))cfunc)(\n                PyCFunction_GET_SELF(callable),\n                args,\n                total_args);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n\n            /* Free the arguments. */\n            for (int i = 0; i < total_args; i++) {\n                Py_DECREF(args[i]);\n            }\n            Py_DECREF(callable);\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n                /* Not deopting because this doesn't mean our optimization was\n                   wrong. `res` can be NULL for valid reasons. Eg. getattr(x,\n                   'invalid'). In those cases an exception is set, so we must\n                   handle it.\n                */\n            #line 4137 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(CALL_BUILTIN_FAST_WITH_KEYWORDS) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 2988 \"Python/bytecodes.c\"\n            /* Builtin METH_FASTCALL | METH_KEYWORDS functions */\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);\n            DEOPT_IF(PyCFunction_GET_FLAGS(callable) !=\n                (METH_FASTCALL | METH_KEYWORDS), CALL);\n            STAT_INC(CALL, hit);\n            /* res = func(self, args, nargs, kwnames) */\n            _PyCFunctionFastWithKeywords cfunc =\n                (_PyCFunctionFastWithKeywords)(void(*)(void))\n                PyCFunction_GET_FUNCTION(callable);\n            res = cfunc(\n                PyCFunction_GET_SELF(callable),\n                args,\n                total_args - KWNAMES_LEN(),\n                kwnames\n            );\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n            kwnames = NULL;\n\n            /* Free the arguments. */\n            for (int i = 0; i < total_args; i++) {\n                Py_DECREF(args[i]);\n            }\n            Py_DECREF(callable);\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n            #line 4183 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(CALL_NO_KW_LEN) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 3023 \"Python/bytecodes.c\"\n            assert(kwnames == NULL);\n            /* len(o) */\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            DEOPT_IF(total_args != 1, CALL);\n            PyInterpreterState *interp = _PyInterpreterState_GET();\n            DEOPT_IF(callable != interp->callable_cache.len, CALL);\n            STAT_INC(CALL, hit);\n            PyObject *arg = args[0];\n            Py_ssize_t len_i = PyObject_Length(arg);\n            if (len_i < 0) {\n                goto error;\n            }\n            res = PyLong_FromSsize_t(len_i);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n\n            Py_DECREF(callable);\n            Py_DECREF(arg);\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n            #line 4222 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            DISPATCH();\n        }\n\n        TARGET(CALL_NO_KW_ISINSTANCE) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *callable = stack_pointer[-(1 + oparg)];\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 3050 \"Python/bytecodes.c\"\n            assert(kwnames == NULL);\n            /* isinstance(o, o2) */\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                callable = method;\n                args--;\n                total_args++;\n            }\n            DEOPT_IF(total_args != 2, CALL);\n            PyInterpreterState *interp = _PyInterpreterState_GET();\n            DEOPT_IF(callable != interp->callable_cache.isinstance, CALL);\n            STAT_INC(CALL, hit);\n            PyObject *cls = args[1];\n            PyObject *inst = args[0];\n            int retval = PyObject_IsInstance(inst, cls);\n            if (retval < 0) {\n                goto error;\n            }\n            res = PyBool_FromLong(retval);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n\n            Py_DECREF(inst);\n            Py_DECREF(cls);\n            Py_DECREF(callable);\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n            #line 4262 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            DISPATCH();\n        }\n\n        TARGET(CALL_NO_KW_LIST_APPEND) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *self = stack_pointer[-(1 + oparg)];\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            #line 3080 \"Python/bytecodes.c\"\n            assert(kwnames == NULL);\n            assert(oparg == 1);\n            assert(method != NULL);\n            PyInterpreterState *interp = _PyInterpreterState_GET();\n            DEOPT_IF(method != interp->callable_cache.list_append, CALL);\n            DEOPT_IF(!PyList_Check(self), CALL);\n            STAT_INC(CALL, hit);\n            if (_PyList_AppendTakeRef((PyListObject *)self, args[0]) < 0) {\n                goto pop_1_error;  // Since arg is DECREF'ed already\n            }\n            Py_DECREF(self);\n            Py_DECREF(method);\n            STACK_SHRINK(3);\n            // CALL + POP_TOP\n            JUMPBY(INLINE_CACHE_ENTRIES_CALL + 1);\n            assert(next_instr[-1].op.code == POP_TOP);\n            DISPATCH();\n            #line 4292 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_O) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 3100 \"Python/bytecodes.c\"\n            assert(kwnames == NULL);\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                args--;\n                total_args++;\n            }\n            PyMethodDescrObject *callable =\n                (PyMethodDescrObject *)PEEK(total_args + 1);\n            DEOPT_IF(total_args != 2, CALL);\n            DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL);\n            PyMethodDef *meth = callable->d_method;\n            DEOPT_IF(meth->ml_flags != METH_O, CALL);\n            PyObject *arg = args[1];\n            PyObject *self = args[0];\n            DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL);\n            STAT_INC(CALL, hit);\n            PyCFunction cfunc = meth->ml_meth;\n            // This is slower but CPython promises to check all non-vectorcall\n            // function calls.\n            if (_Py_EnterRecursiveCallTstate(tstate, \" while calling a Python object\")) {\n                goto error;\n            }\n            res = _PyCFunction_TrampolineCall(cfunc, self, arg);\n            _Py_LeaveRecursiveCallTstate(tstate);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n            Py_DECREF(self);\n            Py_DECREF(arg);\n            Py_DECREF(callable);\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n            #line 4330 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 3134 \"Python/bytecodes.c\"\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                args--;\n                total_args++;\n            }\n            PyMethodDescrObject *callable =\n                (PyMethodDescrObject *)PEEK(total_args + 1);\n            DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL);\n            PyMethodDef *meth = callable->d_method;\n            DEOPT_IF(meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS), CALL);\n            PyTypeObject *d_type = callable->d_common.d_type;\n            PyObject *self = args[0];\n            DEOPT_IF(!Py_IS_TYPE(self, d_type), CALL);\n            STAT_INC(CALL, hit);\n            int nargs = total_args - 1;\n            _PyCFunctionFastWithKeywords cfunc =\n                (_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;\n            res = cfunc(self, args + 1, nargs - KWNAMES_LEN(), kwnames);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n            kwnames = NULL;\n\n            /* Free the arguments. */\n            for (int i = 0; i < total_args; i++) {\n                Py_DECREF(args[i]);\n            }\n            Py_DECREF(callable);\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n            #line 4372 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 3166 \"Python/bytecodes.c\"\n            assert(kwnames == NULL);\n            assert(oparg == 0 || oparg == 1);\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                args--;\n                total_args++;\n            }\n            DEOPT_IF(total_args != 1, CALL);\n            PyMethodDescrObject *callable = (PyMethodDescrObject *)SECOND();\n            DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL);\n            PyMethodDef *meth = callable->d_method;\n            PyObject *self = args[0];\n            DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL);\n            DEOPT_IF(meth->ml_flags != METH_NOARGS, CALL);\n            STAT_INC(CALL, hit);\n            PyCFunction cfunc = meth->ml_meth;\n            // This is slower but CPython promises to check all non-vectorcall\n            // function calls.\n            if (_Py_EnterRecursiveCallTstate(tstate, \" while calling a Python object\")) {\n                goto error;\n            }\n            res = _PyCFunction_TrampolineCall(cfunc, self, NULL);\n            _Py_LeaveRecursiveCallTstate(tstate);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n            Py_DECREF(self);\n            Py_DECREF(callable);\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n            #line 4414 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_FAST) {\n            PyObject **args = (stack_pointer - oparg);\n            PyObject *method = stack_pointer[-(2 + oparg)];\n            PyObject *res;\n            #line 3198 \"Python/bytecodes.c\"\n            assert(kwnames == NULL);\n            int is_meth = method != NULL;\n            int total_args = oparg;\n            if (is_meth) {\n                args--;\n                total_args++;\n            }\n            PyMethodDescrObject *callable =\n                (PyMethodDescrObject *)PEEK(total_args + 1);\n            /* Builtin METH_FASTCALL methods, without keywords */\n            DEOPT_IF(!Py_IS_TYPE(callable, &PyMethodDescr_Type), CALL);\n            PyMethodDef *meth = callable->d_method;\n            DEOPT_IF(meth->ml_flags != METH_FASTCALL, CALL);\n            PyObject *self = args[0];\n            DEOPT_IF(!Py_IS_TYPE(self, callable->d_common.d_type), CALL);\n            STAT_INC(CALL, hit);\n            _PyCFunctionFast cfunc =\n                (_PyCFunctionFast)(void(*)(void))meth->ml_meth;\n            int nargs = total_args - 1;\n            res = cfunc(self, args + 1, nargs);\n            assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));\n            /* Clear the stack of the arguments. */\n            for (int i = 0; i < total_args; i++) {\n                Py_DECREF(args[i]);\n            }\n            Py_DECREF(callable);\n            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }\n            #line 4455 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(oparg);\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 3;\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_CALL_FUNCTION_EX) {\n            #line 3229 \"Python/bytecodes.c\"\n            GO_TO_INSTRUCTION(CALL_FUNCTION_EX);\n            #line 4467 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(CALL_FUNCTION_EX) {\n            PREDICTED(CALL_FUNCTION_EX);\n            PyObject *kwargs = (oparg & 1) ? stack_pointer[-(((oparg & 1) ? 1 : 0))] : NULL;\n            PyObject *callargs = stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))];\n            PyObject *func = stack_pointer[-(2 + ((oparg & 1) ? 1 : 0))];\n            PyObject *result;\n            #line 3233 \"Python/bytecodes.c\"\n            // DICT_MERGE is called before this opcode if there are kwargs.\n            // It converts all dict subtypes in kwargs into regular dicts.\n            assert(kwargs == NULL || PyDict_CheckExact(kwargs));\n            if (!PyTuple_CheckExact(callargs)) {\n                if (check_args_iterable(tstate, func, callargs) < 0) {\n                    goto error;\n                }\n                PyObject *tuple = PySequence_Tuple(callargs);\n                if (tuple == NULL) {\n                    goto error;\n                }\n                Py_SETREF(callargs, tuple);\n            }\n            assert(PyTuple_CheckExact(callargs));\n            EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_FUNCTION_EX, func);\n            if (opcode == INSTRUMENTED_CALL_FUNCTION_EX &&\n                !PyFunction_Check(func) && !PyMethod_Check(func)\n            ) {\n                PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ?\n                    PyTuple_GET_ITEM(callargs, 0) : Py_None;\n                int err = _Py_call_instrumentation_2args(\n                    tstate, PY_MONITORING_EVENT_CALL,\n                    frame, next_instr-1, func, arg);\n                if (err) goto error;\n                result = PyObject_Call(func, callargs, kwargs);\n                if (result == NULL) {\n                    _Py_call_instrumentation_exc2(\n                        tstate, PY_MONITORING_EVENT_C_RAISE,\n                        frame, next_instr-1, func, arg);\n                }\n                else {\n                    int err = _Py_call_instrumentation_2args(\n                        tstate, PY_MONITORING_EVENT_C_RETURN,\n                        frame, next_instr-1, func, arg);\n                    if (err < 0) {\n                        Py_CLEAR(result);\n                    }\n                }\n            }\n            else {\n                if (Py_TYPE(func) == &PyFunction_Type &&\n                    tstate->interp->eval_frame == NULL &&\n                    ((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) {\n                    assert(PyTuple_CheckExact(callargs));\n                    Py_ssize_t nargs = PyTuple_GET_SIZE(callargs);\n                    int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags;\n                    PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func));\n\n                    _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(tstate,\n                                                                                (PyFunctionObject *)func, locals,\n                                                                                nargs, callargs, kwargs);\n                    // Need to manually shrink the stack since we exit with DISPATCH_INLINED.\n                    STACK_SHRINK(oparg + 3);\n                    if (new_frame == NULL) {\n                        goto error;\n                    }\n                    frame->return_offset = 0;\n                    DISPATCH_INLINED(new_frame);\n                }\n                result = PyObject_Call(func, callargs, kwargs);\n            }\n            #line 4538 \"Python/generated_cases.c.h\"\n            Py_DECREF(func);\n            Py_DECREF(callargs);\n            Py_XDECREF(kwargs);\n            #line 3295 \"Python/bytecodes.c\"\n            assert(PEEK(3 + (oparg & 1)) == NULL);\n            if (result == NULL) { STACK_SHRINK(((oparg & 1) ? 1 : 0)); goto pop_3_error; }\n            #line 4545 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(((oparg & 1) ? 1 : 0));\n            STACK_SHRINK(2);\n            stack_pointer[-1] = result;\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(MAKE_FUNCTION) {\n            PyObject *codeobj = stack_pointer[-1];\n            PyObject *closure = (oparg & MAKE_FUNCTION_CLOSURE) ? stack_pointer[-(1 + ((oparg & MAKE_FUNCTION_CLOSURE) ? 1 : 0))] : NULL;\n            PyObject *annotations = (oparg & MAKE_FUNCTION_ANNOTATIONS) ? stack_pointer[-(1 + ((oparg & MAKE_FUNCTION_CLOSURE) ? 1 : 0) + ((oparg & MAKE_FUNCTION_ANNOTATIONS) ? 1 : 0))] : NULL;\n            PyObject *kwdefaults = (oparg & MAKE_FUNCTION_KWDEFAULTS) ? stack_pointer[-(1 + ((oparg & MAKE_FUNCTION_CLOSURE) ? 1 : 0) + ((oparg & MAKE_FUNCTION_ANNOTATIONS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_KWDEFAULTS) ? 1 : 0))] : NULL;\n            PyObject *defaults = (oparg & MAKE_FUNCTION_DEFAULTS) ? stack_pointer[-(1 + ((oparg & MAKE_FUNCTION_CLOSURE) ? 1 : 0) + ((oparg & MAKE_FUNCTION_ANNOTATIONS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_KWDEFAULTS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_DEFAULTS) ? 1 : 0))] : NULL;\n            PyObject *func;\n            #line 3305 \"Python/bytecodes.c\"\n\n            PyFunctionObject *func_obj = (PyFunctionObject *)\n                PyFunction_New(codeobj, GLOBALS());\n\n            Py_DECREF(codeobj);\n            if (func_obj == NULL) {\n                goto error;\n            }\n\n            if (oparg & MAKE_FUNCTION_CLOSURE) {\n                assert(PyTuple_CheckExact(closure));\n                func_obj->func_closure = closure;\n            }\n            if (oparg & MAKE_FUNCTION_ANNOTATIONS) {\n                assert(PyTuple_CheckExact(annotations));\n                func_obj->func_annotations = annotations;\n            }\n            if (oparg & MAKE_FUNCTION_KWDEFAULTS) {\n                assert(PyDict_CheckExact(kwdefaults));\n                func_obj->func_kwdefaults = kwdefaults;\n            }\n            if (oparg & MAKE_FUNCTION_DEFAULTS) {\n                assert(PyTuple_CheckExact(defaults));\n                func_obj->func_defaults = defaults;\n            }\n\n            func_obj->func_version = ((PyCodeObject *)codeobj)->co_version;\n            func = (PyObject *)func_obj;\n            #line 4589 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(((oparg & MAKE_FUNCTION_DEFAULTS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_KWDEFAULTS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_ANNOTATIONS) ? 1 : 0) + ((oparg & MAKE_FUNCTION_CLOSURE) ? 1 : 0));\n            stack_pointer[-1] = func;\n            DISPATCH();\n        }\n\n        TARGET(RETURN_GENERATOR) {\n            #line 3336 \"Python/bytecodes.c\"\n            assert(PyFunction_Check(frame->f_funcobj));\n            PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;\n            PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);\n            if (gen == NULL) {\n                goto error;\n            }\n            assert(EMPTY());\n            _PyFrame_SetStackPointer(frame, stack_pointer);\n            _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;\n            _PyFrame_Copy(frame, gen_frame);\n            assert(frame->frame_obj == NULL);\n            gen->gi_frame_state = FRAME_CREATED;\n            gen_frame->owner = FRAME_OWNED_BY_GENERATOR;\n            _Py_LeaveRecursiveCallPy(tstate);\n            assert(frame != &entry_frame);\n            _PyInterpreterFrame *prev = frame->previous;\n            _PyThreadState_PopFrame(tstate, frame);\n            frame = cframe.current_frame = prev;\n            _PyFrame_StackPush(frame, (PyObject *)gen);\n            goto resume_frame;\n            #line 4617 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(BUILD_SLICE) {\n            PyObject *step = (oparg == 3) ? stack_pointer[-(((oparg == 3) ? 1 : 0))] : NULL;\n            PyObject *stop = stack_pointer[-(1 + ((oparg == 3) ? 1 : 0))];\n            PyObject *start = stack_pointer[-(2 + ((oparg == 3) ? 1 : 0))];\n            PyObject *slice;\n            #line 3359 \"Python/bytecodes.c\"\n            slice = PySlice_New(start, stop, step);\n            #line 4627 \"Python/generated_cases.c.h\"\n            Py_DECREF(start);\n            Py_DECREF(stop);\n            Py_XDECREF(step);\n            #line 3361 \"Python/bytecodes.c\"\n            if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error; }\n            #line 4633 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(((oparg == 3) ? 1 : 0));\n            STACK_SHRINK(1);\n            stack_pointer[-1] = slice;\n            DISPATCH();\n        }\n\n        TARGET(FORMAT_VALUE) {\n            PyObject *fmt_spec = ((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? stack_pointer[-((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0))] : NULL;\n            PyObject *value = stack_pointer[-(1 + (((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0))];\n            PyObject *result;\n            #line 3365 \"Python/bytecodes.c\"\n            /* Handles f-string value formatting. */\n            PyObject *(*conv_fn)(PyObject *);\n            int which_conversion = oparg & FVC_MASK;\n\n            /* See if any conversion is specified. */\n            switch (which_conversion) {\n            case FVC_NONE:  conv_fn = NULL;           break;\n            case FVC_STR:   conv_fn = PyObject_Str;   break;\n            case FVC_REPR:  conv_fn = PyObject_Repr;  break;\n            case FVC_ASCII: conv_fn = PyObject_ASCII; break;\n            default:\n                _PyErr_Format(tstate, PyExc_SystemError,\n                              \"unexpected conversion flag %d\",\n                              which_conversion);\n                goto error;\n            }\n\n            /* If there's a conversion function, call it and replace\n               value with that result. Otherwise, just use value,\n               without conversion. */\n            if (conv_fn != NULL) {\n                result = conv_fn(value);\n                Py_DECREF(value);\n                if (result == NULL) {\n                    Py_XDECREF(fmt_spec);\n                    if (true) { STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0)); goto pop_1_error; }\n                }\n                value = result;\n            }\n\n            result = PyObject_Format(value, fmt_spec);\n            Py_DECREF(value);\n            Py_XDECREF(fmt_spec);\n            if (result == NULL) { STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0)); goto pop_1_error; }\n            #line 4679 \"Python/generated_cases.c.h\"\n            STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0));\n            stack_pointer[-1] = result;\n            DISPATCH();\n        }\n\n        TARGET(COPY) {\n            PyObject *bottom = stack_pointer[-(1 + (oparg-1))];\n            PyObject *top;\n            #line 3402 \"Python/bytecodes.c\"\n            assert(oparg > 0);\n            top = Py_NewRef(bottom);\n            #line 4691 \"Python/generated_cases.c.h\"\n            STACK_GROW(1);\n            stack_pointer[-1] = top;\n            DISPATCH();\n        }\n\n        TARGET(BINARY_OP) {\n            PREDICTED(BINARY_OP);\n            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, \"incorrect cache size\");\n            PyObject *rhs = stack_pointer[-1];\n            PyObject *lhs = stack_pointer[-2];\n            PyObject *res;\n            #line 3407 \"Python/bytecodes.c\"\n            #if ENABLE_SPECIALIZATION\n            _PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr;\n            if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {\n                next_instr--;\n                _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, &GETLOCAL(0));\n                DISPATCH_SAME_OPARG();\n            }\n            STAT_INC(BINARY_OP, deferred);\n            DECREMENT_ADAPTIVE_COUNTER(cache->counter);\n            #endif  /* ENABLE_SPECIALIZATION */\n            assert(0 <= oparg);\n            assert((unsigned)oparg < Py_ARRAY_LENGTH(binary_ops));\n            assert(binary_ops[oparg]);\n            res = binary_ops[oparg](lhs, rhs);\n            #line 4718 \"Python/generated_cases.c.h\"\n            Py_DECREF(lhs);\n            Py_DECREF(rhs);\n            #line 3422 \"Python/bytecodes.c\"\n            if (res == NULL) goto pop_2_error;\n            #line 4723 \"Python/generated_cases.c.h\"\n            STACK_SHRINK(1);\n            stack_pointer[-1] = res;\n            next_instr += 1;\n            DISPATCH();\n        }\n\n        TARGET(SWAP) {\n            PyObject *top = stack_pointer[-1];\n            PyObject *bottom = stack_pointer[-(2 + (oparg-2))];\n            #line 3427 \"Python/bytecodes.c\"\n            assert(oparg >= 2);\n            #line 4735 \"Python/generated_cases.c.h\"\n            stack_pointer[-1] = bottom;\n            stack_pointer[-(2 + (oparg-2))] = top;\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_INSTRUCTION) {\n            #line 3431 \"Python/bytecodes.c\"\n            int next_opcode = _Py_call_instrumentation_instruction(\n                tstate, frame, next_instr-1);\n            if (next_opcode < 0) goto error;\n            next_instr--;\n            if (_PyOpcode_Caches[next_opcode]) {\n                _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1);\n                INCREMENT_ADAPTIVE_COUNTER(cache->counter);\n            }\n            assert(next_opcode > 0 && next_opcode < 256);\n            opcode = next_opcode;\n            DISPATCH_GOTO();\n            #line 4754 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(INSTRUMENTED_JUMP_FORWARD) {\n            #line 3445 \"Python/bytecodes.c\"\n            INSTRUMENTED_JUMP(next_instr-1, next_instr+oparg, PY_MONITORING_EVENT_JUMP);\n            #line 4760 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_JUMP_BACKWARD) {\n            #line 3449 \"Python/bytecodes.c\"\n            INSTRUMENTED_JUMP(next_instr-1, next_instr+1-oparg, PY_MONITORING_EVENT_JUMP);\n            #line 4767 \"Python/generated_cases.c.h\"\n            CHECK_EVAL_BREAKER();\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_POP_JUMP_IF_TRUE) {\n            #line 3454 \"Python/bytecodes.c\"\n            PyObject *cond = POP();\n            int err = PyObject_IsTrue(cond);\n            Py_DECREF(cond);\n            if (err < 0) goto error;\n            _Py_CODEUNIT *here = next_instr-1;\n            assert(err == 0 || err == 1);\n            int offset = err*oparg;\n            INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);\n            #line 4782 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_POP_JUMP_IF_FALSE) {\n            #line 3465 \"Python/bytecodes.c\"\n            PyObject *cond = POP();\n            int err = PyObject_IsTrue(cond);\n            Py_DECREF(cond);\n            if (err < 0) goto error;\n            _Py_CODEUNIT *here = next_instr-1;\n            assert(err == 0 || err == 1);\n            int offset = (1-err)*oparg;\n            INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);\n            #line 4796 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_POP_JUMP_IF_NONE) {\n            #line 3476 \"Python/bytecodes.c\"\n            PyObject *value = POP();\n            _Py_CODEUNIT *here = next_instr-1;\n            int offset;\n            if (Py_IsNone(value)) {\n                offset = oparg;\n            }\n            else {\n                Py_DECREF(value);\n                offset = 0;\n            }\n            INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);\n            #line 4813 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(INSTRUMENTED_POP_JUMP_IF_NOT_NONE) {\n            #line 3490 \"Python/bytecodes.c\"\n            PyObject *value = POP();\n            _Py_CODEUNIT *here = next_instr-1;\n            int offset;\n            if (Py_IsNone(value)) {\n                offset = 0;\n            }\n            else {\n                Py_DECREF(value);\n                 offset = oparg;\n            }\n            INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH);\n            #line 4830 \"Python/generated_cases.c.h\"\n            DISPATCH();\n        }\n\n        TARGET(EXTENDED_ARG) {\n            #line 3504 \"Python/bytecodes.c\"\n            assert(oparg);\n            opcode = next_instr->op.code;\n            oparg = oparg << 8 | next_instr->op.arg;\n            PRE_DISPATCH_GOTO();\n            DISPATCH_GOTO();\n            #line 4841 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(CACHE) {\n            #line 3512 \"Python/bytecodes.c\"\n            assert(0 && \"Executing a cache.\");\n            Py_UNREACHABLE();\n            #line 4848 \"Python/generated_cases.c.h\"\n        }\n\n        TARGET(RESERVED) {\n            #line 3517 \"Python/bytecodes.c\"\n            assert(0 && \"Executing RESERVED instruction.\");\n            Py_UNREACHABLE();\n            #line 4855 \"Python/generated_cases.c.h\"\n        }\n"
  },
  {
    "path": "GetArgs.c",
    "content": "\n/* New getargs implementation */\n\n#include \"Python.h\"\n#include \"pycore_tuple.h\"         // _PyTuple_ITEMS()\n#include \"pycore_pylifecycle.h\"   // _PyArg_Fini\n\n#include <ctype.h>\n#include <float.h>\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Export Stable ABIs (abi only) */\nPyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...);\nPyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, const char *, ...);\nPyAPI_FUNC(int) _PyArg_ParseTupleAndKeywords_SizeT(PyObject *, PyObject *,\n                                                  const char *, char **, ...);\nPyAPI_FUNC(int) _PyArg_VaParse_SizeT(PyObject *, const char *, va_list);\nPyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *,\n                                              const char *, char **, va_list);\n\n#define FLAG_COMPAT 1\n\ntypedef int (*destr_t)(PyObject *, void *);\n\n\n/* Keep track of \"objects\" that have been allocated or initialized and\n   which will need to be deallocated or cleaned up somehow if overall\n   parsing fails.\n*/\ntypedef struct {\n  void *item;\n  destr_t destructor;\n} freelistentry_t;\n\ntypedef struct {\n  freelistentry_t *entries;\n  int first_available;\n  int entries_malloced;\n} freelist_t;\n\n#define STATIC_FREELIST_ENTRIES 8\n\n/* Forward */\nstatic int vgetargs1_impl(PyObject *args, PyObject *const *stack, Py_ssize_t nargs,\n                          const char *format, va_list *p_va, int flags);\nstatic int vgetargs1(PyObject *, const char *, va_list *, int);\nstatic void seterror(Py_ssize_t, const char *, int *, const char *, const char *);\nstatic const char *convertitem(PyObject *, const char **, va_list *, int, int *,\n                               char *, size_t, freelist_t *);\nstatic const char *converttuple(PyObject *, const char **, va_list *, int,\n                                int *, char *, size_t, int, freelist_t *);\nstatic const char *convertsimple(PyObject *, const char **, va_list *, int,\n                                 char *, size_t, freelist_t *);\nstatic Py_ssize_t convertbuffer(PyObject *, const void **p, const char **);\nstatic int getbuffer(PyObject *, Py_buffer *, const char**);\n\nstatic int vgetargskeywords(PyObject *, PyObject *,\n                            const char *, char **, va_list *, int);\nstatic int vgetargskeywordsfast(PyObject *, PyObject *,\n                            struct _PyArg_Parser *, va_list *, int);\nstatic int vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,\n                          PyObject *keywords, PyObject *kwnames,\n                          struct _PyArg_Parser *parser,\n                          va_list *p_va, int flags);\nstatic const char *skipitem(const char **, va_list *, int);\n\nint\nPyArg_Parse(PyObject *args, const char *format, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, format);\n    retval = vgetargs1(args, format, &va, FLAG_COMPAT);\n    va_end(va);\n    return retval;\n}\n\nPyAPI_FUNC(int)\n_PyArg_Parse_SizeT(PyObject *args, const char *format, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, format);\n    retval = vgetargs1(args, format, &va, FLAG_COMPAT);\n    va_end(va);\n    return retval;\n}\n\n\nint\nPyArg_ParseTuple(PyObject *args, const char *format, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, format);\n    retval = vgetargs1(args, format, &va, 0);\n    va_end(va);\n    return retval;\n}\n\nint\n_PyArg_ParseTuple_SizeT(PyObject *args, const char *format, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, format);\n    retval = vgetargs1(args, format, &va, 0);\n    va_end(va);\n    return retval;\n}\n\n\nint\n_PyArg_ParseStack(PyObject *const *args, Py_ssize_t nargs, const char *format, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, format);\n    retval = vgetargs1_impl(NULL, args, nargs, format, &va, 0);\n    va_end(va);\n    return retval;\n}\n\nint\nPyArg_VaParse(PyObject *args, const char *format, va_list va)\n{\n    va_list lva;\n    int retval;\n\n    va_copy(lva, va);\n\n    retval = vgetargs1(args, format, &lva, 0);\n    va_end(lva);\n    return retval;\n}\n\nint\n_PyArg_VaParse_SizeT(PyObject *args, const char *format, va_list va)\n{\n    va_list lva;\n    int retval;\n\n    va_copy(lva, va);\n\n    retval = vgetargs1(args, format, &lva, 0);\n    va_end(lva);\n    return retval;\n}\n\n\n/* Handle cleanup of allocated memory in case of exception */\n\nstatic int\ncleanup_ptr(PyObject *self, void *ptr)\n{\n    void **pptr = (void **)ptr;\n    PyMem_Free(*pptr);\n    *pptr = NULL;\n    return 0;\n}\n\nstatic int\ncleanup_buffer(PyObject *self, void *ptr)\n{\n    Py_buffer *buf = (Py_buffer *)ptr;\n    if (buf) {\n        PyBuffer_Release(buf);\n    }\n    return 0;\n}\n\nstatic int\naddcleanup(void *ptr, freelist_t *freelist, destr_t destructor)\n{\n    int index;\n\n    index = freelist->first_available;\n    freelist->first_available += 1;\n\n    freelist->entries[index].item = ptr;\n    freelist->entries[index].destructor = destructor;\n\n    return 0;\n}\n\nstatic int\ncleanreturn(int retval, freelist_t *freelist)\n{\n    int index;\n\n    if (retval == 0) {\n      /* A failure occurred, therefore execute all of the cleanup\n         functions.\n      */\n      for (index = 0; index < freelist->first_available; ++index) {\n          freelist->entries[index].destructor(NULL,\n                                              freelist->entries[index].item);\n      }\n    }\n    if (freelist->entries_malloced)\n        PyMem_Free(freelist->entries);\n    return retval;\n}\n\n\nstatic int\nvgetargs1_impl(PyObject *compat_args, PyObject *const *stack, Py_ssize_t nargs, const char *format,\n               va_list *p_va, int flags)\n{\n    char msgbuf[256];\n    int levels[32];\n    const char *fname = NULL;\n    const char *message = NULL;\n    int min = -1;\n    int max = 0;\n    int level = 0;\n    int endfmt = 0;\n    const char *formatsave = format;\n    Py_ssize_t i;\n    const char *msg;\n    int compat = flags & FLAG_COMPAT;\n    freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];\n    freelist_t freelist;\n\n    assert(nargs == 0 || stack != NULL);\n\n    freelist.entries = static_entries;\n    freelist.first_available = 0;\n    freelist.entries_malloced = 0;\n\n    flags = flags & ~FLAG_COMPAT;\n\n    while (endfmt == 0) {\n        int c = *format++;\n        switch (c) {\n        case '(':\n            if (level == 0)\n                max++;\n            level++;\n            if (level >= 30)\n                Py_FatalError(\"too many tuple nesting levels \"\n                              \"in argument format string\");\n            break;\n        case ')':\n            if (level == 0)\n                Py_FatalError(\"excess ')' in getargs format\");\n            else\n                level--;\n            break;\n        case '\\0':\n            endfmt = 1;\n            break;\n        case ':':\n            fname = format;\n            endfmt = 1;\n            break;\n        case ';':\n            message = format;\n            endfmt = 1;\n            break;\n        case '|':\n            if (level == 0)\n                min = max;\n            break;\n        default:\n            if (level == 0) {\n                if (Py_ISALPHA(c))\n                    if (c != 'e') /* skip encoded */\n                        max++;\n            }\n            break;\n        }\n    }\n\n    if (level != 0)\n        Py_FatalError(/* '(' */ \"missing ')' in getargs format\");\n\n    if (min < 0)\n        min = max;\n\n    format = formatsave;\n\n    if (max > STATIC_FREELIST_ENTRIES) {\n        freelist.entries = PyMem_NEW(freelistentry_t, max);\n        if (freelist.entries == NULL) {\n            PyErr_NoMemory();\n            return 0;\n        }\n        freelist.entries_malloced = 1;\n    }\n\n    if (compat) {\n        if (max == 0) {\n            if (compat_args == NULL)\n                return 1;\n            PyErr_Format(PyExc_TypeError,\n                         \"%.200s%s takes no arguments\",\n                         fname==NULL ? \"function\" : fname,\n                         fname==NULL ? \"\" : \"()\");\n            return cleanreturn(0, &freelist);\n        }\n        else if (min == 1 && max == 1) {\n            if (compat_args == NULL) {\n                PyErr_Format(PyExc_TypeError,\n                             \"%.200s%s takes at least one argument\",\n                             fname==NULL ? \"function\" : fname,\n                             fname==NULL ? \"\" : \"()\");\n                return cleanreturn(0, &freelist);\n            }\n            msg = convertitem(compat_args, &format, p_va, flags, levels,\n                              msgbuf, sizeof(msgbuf), &freelist);\n            if (msg == NULL)\n                return cleanreturn(1, &freelist);\n            seterror(levels[0], msg, levels+1, fname, message);\n            return cleanreturn(0, &freelist);\n        }\n        else {\n            PyErr_SetString(PyExc_SystemError,\n                \"old style getargs format uses new features\");\n            return cleanreturn(0, &freelist);\n        }\n    }\n\n    if (nargs < min || max < nargs) {\n        if (message == NULL)\n            PyErr_Format(PyExc_TypeError,\n                         \"%.150s%s takes %s %d argument%s (%zd given)\",\n                         fname==NULL ? \"function\" : fname,\n                         fname==NULL ? \"\" : \"()\",\n                         min==max ? \"exactly\"\n                         : nargs < min ? \"at least\" : \"at most\",\n                         nargs < min ? min : max,\n                         (nargs < min ? min : max) == 1 ? \"\" : \"s\",\n                         nargs);\n        else\n            PyErr_SetString(PyExc_TypeError, message);\n        return cleanreturn(0, &freelist);\n    }\n\n    for (i = 0; i < nargs; i++) {\n        if (*format == '|')\n            format++;\n        msg = convertitem(stack[i], &format, p_va,\n                          flags, levels, msgbuf,\n                          sizeof(msgbuf), &freelist);\n        if (msg) {\n            seterror(i+1, msg, levels, fname, message);\n            return cleanreturn(0, &freelist);\n        }\n    }\n\n    if (*format != '\\0' && !Py_ISALPHA(*format) &&\n        *format != '(' &&\n        *format != '|' && *format != ':' && *format != ';') {\n        PyErr_Format(PyExc_SystemError,\n                     \"bad format string: %.200s\", formatsave);\n        return cleanreturn(0, &freelist);\n    }\n\n    return cleanreturn(1, &freelist);\n}\n\nstatic int\nvgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)\n{\n    PyObject **stack;\n    Py_ssize_t nargs;\n\n    if (!(flags & FLAG_COMPAT)) {\n        assert(args != NULL);\n\n        if (!PyTuple_Check(args)) {\n            PyErr_SetString(PyExc_SystemError,\n                \"new style getargs format but argument is not a tuple\");\n            return 0;\n        }\n\n        stack = _PyTuple_ITEMS(args);\n        nargs = PyTuple_GET_SIZE(args);\n    }\n    else {\n        stack = NULL;\n        nargs = 0;\n    }\n\n    return vgetargs1_impl(args, stack, nargs, format, p_va, flags);\n}\n\n\nstatic void\nseterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname,\n         const char *message)\n{\n    char buf[512];\n    int i;\n    char *p = buf;\n\n    if (PyErr_Occurred())\n        return;\n    else if (message == NULL) {\n        if (fname != NULL) {\n            PyOS_snprintf(p, sizeof(buf), \"%.200s() \", fname);\n            p += strlen(p);\n        }\n        if (iarg != 0) {\n            PyOS_snprintf(p, sizeof(buf) - (p - buf),\n                          \"argument %zd\", iarg);\n            i = 0;\n            p += strlen(p);\n            while (i < 32 && levels[i] > 0 && (int)(p-buf) < 220) {\n                PyOS_snprintf(p, sizeof(buf) - (p - buf),\n                              \", item %d\", levels[i]-1);\n                p += strlen(p);\n                i++;\n            }\n        }\n        else {\n            PyOS_snprintf(p, sizeof(buf) - (p - buf), \"argument\");\n            p += strlen(p);\n        }\n        PyOS_snprintf(p, sizeof(buf) - (p - buf), \" %.256s\", msg);\n        message = buf;\n    }\n    if (msg[0] == '(') {\n        PyErr_SetString(PyExc_SystemError, message);\n    }\n    else {\n        PyErr_SetString(PyExc_TypeError, message);\n    }\n}\n\n\n/* Convert a tuple argument.\n   On entry, *p_format points to the character _after_ the opening '('.\n   On successful exit, *p_format points to the closing ')'.\n   If successful:\n      *p_format and *p_va are updated,\n      *levels and *msgbuf are untouched,\n      and NULL is returned.\n   If the argument is invalid:\n      *p_format is unchanged,\n      *p_va is undefined,\n      *levels is a 0-terminated list of item numbers,\n      *msgbuf contains an error message, whose format is:\n     \"must be <typename1>, not <typename2>\", where:\n        <typename1> is the name of the expected type, and\n        <typename2> is the name of the actual type,\n      and msgbuf is returned.\n*/\n\nstatic const char *\nconverttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags,\n             int *levels, char *msgbuf, size_t bufsize, int toplevel,\n             freelist_t *freelist)\n{\n    int level = 0;\n    int n = 0;\n    const char *format = *p_format;\n    int i;\n    Py_ssize_t len;\n\n    for (;;) {\n        int c = *format++;\n        if (c == '(') {\n            if (level == 0)\n                n++;\n            level++;\n        }\n        else if (c == ')') {\n            if (level == 0)\n                break;\n            level--;\n        }\n        else if (c == ':' || c == ';' || c == '\\0')\n            break;\n        else if (level == 0 && Py_ISALPHA(c))\n            n++;\n    }\n\n    if (!PySequence_Check(arg) || PyBytes_Check(arg)) {\n        levels[0] = 0;\n        PyOS_snprintf(msgbuf, bufsize,\n                      toplevel ? \"expected %d arguments, not %.50s\" :\n                      \"must be %d-item sequence, not %.50s\",\n                  n,\n                  arg == Py_None ? \"None\" : Py_TYPE(arg)->tp_name);\n        return msgbuf;\n    }\n\n    len = PySequence_Size(arg);\n    if (len != n) {\n        levels[0] = 0;\n        if (toplevel) {\n            PyOS_snprintf(msgbuf, bufsize,\n                          \"expected %d argument%s, not %zd\",\n                          n,\n                          n == 1 ? \"\" : \"s\",\n                          len);\n        }\n        else {\n            PyOS_snprintf(msgbuf, bufsize,\n                          \"must be sequence of length %d, not %zd\",\n                          n, len);\n        }\n        return msgbuf;\n    }\n\n    format = *p_format;\n    for (i = 0; i < n; i++) {\n        const char *msg;\n        PyObject *item;\n        item = PySequence_GetItem(arg, i);\n        if (item == NULL) {\n            PyErr_Clear();\n            levels[0] = i+1;\n            levels[1] = 0;\n            strncpy(msgbuf, \"is not retrievable\", bufsize);\n            return msgbuf;\n        }\n        msg = convertitem(item, &format, p_va, flags, levels+1,\n                          msgbuf, bufsize, freelist);\n        /* PySequence_GetItem calls tp->sq_item, which INCREFs */\n        Py_XDECREF(item);\n        if (msg != NULL) {\n            levels[0] = i+1;\n            return msg;\n        }\n    }\n\n    *p_format = format;\n    return NULL;\n}\n\n\n/* Convert a single item. */\n\nstatic const char *\nconvertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags,\n            int *levels, char *msgbuf, size_t bufsize, freelist_t *freelist)\n{\n    const char *msg;\n    const char *format = *p_format;\n\n    if (*format == '(' /* ')' */) {\n        format++;\n        msg = converttuple(arg, &format, p_va, flags, levels, msgbuf,\n                           bufsize, 0, freelist);\n        if (msg == NULL)\n            format++;\n    }\n    else {\n        msg = convertsimple(arg, &format, p_va, flags,\n                            msgbuf, bufsize, freelist);\n        if (msg != NULL)\n            levels[0] = 0;\n    }\n    if (msg == NULL)\n        *p_format = format;\n    return msg;\n}\n\n\n\n/* Format an error message generated by convertsimple().\n   displayname must be UTF-8 encoded.\n*/\n\nvoid\n_PyArg_BadArgument(const char *fname, const char *displayname,\n                   const char *expected, PyObject *arg)\n{\n    PyErr_Format(PyExc_TypeError,\n                 \"%.200s() %.200s must be %.50s, not %.50s\",\n                 fname, displayname, expected,\n                 arg == Py_None ? \"None\" : Py_TYPE(arg)->tp_name);\n}\n\nstatic const char *\nconverterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize)\n{\n    assert(expected != NULL);\n    assert(arg != NULL);\n    if (expected[0] == '(') {\n        PyOS_snprintf(msgbuf, bufsize,\n                      \"%.100s\", expected);\n    }\n    else {\n        PyOS_snprintf(msgbuf, bufsize,\n                      \"must be %.50s, not %.50s\", expected,\n                      arg == Py_None ? \"None\" : Py_TYPE(arg)->tp_name);\n    }\n    return msgbuf;\n}\n\n#define CONV_UNICODE \"(unicode conversion error)\"\n\n/* Convert a non-tuple argument.  Return NULL if conversion went OK,\n   or a string with a message describing the failure.  The message is\n   formatted as \"must be <desired type>, not <actual type>\".\n   When failing, an exception may or may not have been raised.\n   Don't call if a tuple is expected.\n\n   When you add new format codes, please don't forget poor skipitem() below.\n*/\n\nstatic const char *\nconvertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,\n              char *msgbuf, size_t bufsize, freelist_t *freelist)\n{\n#define RETURN_ERR_OCCURRED return msgbuf\n\n    const char *format = *p_format;\n    char c = *format++;\n    const char *sarg;\n\n    switch (c) {\n\n    case 'b': { /* unsigned byte -- very short int */\n        char *p = va_arg(*p_va, char *);\n        long ival = PyLong_AsLong(arg);\n        if (ival == -1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else if (ival < 0) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"unsigned byte integer is less than minimum\");\n            RETURN_ERR_OCCURRED;\n        }\n        else if (ival > UCHAR_MAX) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"unsigned byte integer is greater than maximum\");\n            RETURN_ERR_OCCURRED;\n        }\n        else\n            *p = (unsigned char) ival;\n        break;\n    }\n\n    case 'B': {/* byte sized bitfield - both signed and unsigned\n                  values allowed */\n        char *p = va_arg(*p_va, char *);\n        unsigned long ival = PyLong_AsUnsignedLongMask(arg);\n        if (ival == (unsigned long)-1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = (unsigned char) ival;\n        break;\n    }\n\n    case 'h': {/* signed short int */\n        short *p = va_arg(*p_va, short *);\n        long ival = PyLong_AsLong(arg);\n        if (ival == -1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else if (ival < SHRT_MIN) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"signed short integer is less than minimum\");\n            RETURN_ERR_OCCURRED;\n        }\n        else if (ival > SHRT_MAX) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"signed short integer is greater than maximum\");\n            RETURN_ERR_OCCURRED;\n        }\n        else\n            *p = (short) ival;\n        break;\n    }\n\n    case 'H': { /* short int sized bitfield, both signed and\n                   unsigned allowed */\n        unsigned short *p = va_arg(*p_va, unsigned short *);\n        unsigned long ival = PyLong_AsUnsignedLongMask(arg);\n        if (ival == (unsigned long)-1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = (unsigned short) ival;\n        break;\n    }\n\n    case 'i': {/* signed int */\n        int *p = va_arg(*p_va, int *);\n        long ival = PyLong_AsLong(arg);\n        if (ival == -1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else if (ival > INT_MAX) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"signed integer is greater than maximum\");\n            RETURN_ERR_OCCURRED;\n        }\n        else if (ival < INT_MIN) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"signed integer is less than minimum\");\n            RETURN_ERR_OCCURRED;\n        }\n        else\n            *p = ival;\n        break;\n    }\n\n    case 'I': { /* int sized bitfield, both signed and\n                   unsigned allowed */\n        unsigned int *p = va_arg(*p_va, unsigned int *);\n        unsigned long ival = PyLong_AsUnsignedLongMask(arg);\n        if (ival == (unsigned long)-1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = (unsigned int) ival;\n        break;\n    }\n\n    case 'n': /* Py_ssize_t */\n    {\n        PyObject *iobj;\n        Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *);\n        Py_ssize_t ival = -1;\n        iobj = _PyNumber_Index(arg);\n        if (iobj != NULL) {\n            ival = PyLong_AsSsize_t(iobj);\n            Py_DECREF(iobj);\n        }\n        if (ival == -1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        *p = ival;\n        break;\n    }\n    case 'l': {/* long int */\n        long *p = va_arg(*p_va, long *);\n        long ival = PyLong_AsLong(arg);\n        if (ival == -1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = ival;\n        break;\n    }\n\n    case 'k': { /* long sized bitfield */\n        unsigned long *p = va_arg(*p_va, unsigned long *);\n        unsigned long ival;\n        if (PyLong_Check(arg))\n            ival = PyLong_AsUnsignedLongMask(arg);\n        else\n            return converterr(\"int\", arg, msgbuf, bufsize);\n        *p = ival;\n        break;\n    }\n\n    case 'L': {/* long long */\n        long long *p = va_arg( *p_va, long long * );\n        long long ival = PyLong_AsLongLong(arg);\n        if (ival == (long long)-1 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = ival;\n        break;\n    }\n\n    case 'K': { /* long long sized bitfield */\n        unsigned long long *p = va_arg(*p_va, unsigned long long *);\n        unsigned long long ival;\n        if (PyLong_Check(arg))\n            ival = PyLong_AsUnsignedLongLongMask(arg);\n        else\n            return converterr(\"int\", arg, msgbuf, bufsize);\n        *p = ival;\n        break;\n    }\n\n    case 'f': {/* float */\n        float *p = va_arg(*p_va, float *);\n        double dval = PyFloat_AsDouble(arg);\n        if (dval == -1.0 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = (float) dval;\n        break;\n    }\n\n    case 'd': {/* double */\n        double *p = va_arg(*p_va, double *);\n        double dval = PyFloat_AsDouble(arg);\n        if (dval == -1.0 && PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = dval;\n        break;\n    }\n\n    case 'D': {/* complex double */\n        Py_complex *p = va_arg(*p_va, Py_complex *);\n        Py_complex cval;\n        cval = PyComplex_AsCComplex(arg);\n        if (PyErr_Occurred())\n            RETURN_ERR_OCCURRED;\n        else\n            *p = cval;\n        break;\n    }\n\n    case 'c': {/* char */\n        char *p = va_arg(*p_va, char *);\n        if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1)\n            *p = PyBytes_AS_STRING(arg)[0];\n        else if (PyByteArray_Check(arg) && PyByteArray_Size(arg) == 1)\n            *p = PyByteArray_AS_STRING(arg)[0];\n        else\n            return converterr(\"a byte string of length 1\", arg, msgbuf, bufsize);\n        break;\n    }\n\n    case 'C': {/* unicode char */\n        int *p = va_arg(*p_va, int *);\n        int kind;\n        const void *data;\n\n        if (!PyUnicode_Check(arg))\n            return converterr(\"a unicode character\", arg, msgbuf, bufsize);\n\n        if (PyUnicode_GET_LENGTH(arg) != 1)\n            return converterr(\"a unicode character\", arg, msgbuf, bufsize);\n\n        kind = PyUnicode_KIND(arg);\n        data = PyUnicode_DATA(arg);\n        *p = PyUnicode_READ(kind, data, 0);\n        break;\n    }\n\n    case 'p': {/* boolean *p*redicate */\n        int *p = va_arg(*p_va, int *);\n        int val = PyObject_IsTrue(arg);\n        if (val > 0)\n            *p = 1;\n        else if (val == 0)\n            *p = 0;\n        else\n            RETURN_ERR_OCCURRED;\n        break;\n    }\n\n    /* XXX WAAAAH!  's', 'y', 'z', 'u', 'Z', 'e', 'w' codes all\n       need to be cleaned up! */\n\n    case 'y': {/* any bytes-like object */\n        void **p = (void **)va_arg(*p_va, char **);\n        const char *buf;\n        Py_ssize_t count;\n        if (*format == '*') {\n            if (getbuffer(arg, (Py_buffer*)p, &buf) < 0)\n                return converterr(buf, arg, msgbuf, bufsize);\n            format++;\n            if (addcleanup(p, freelist, cleanup_buffer)) {\n                return converterr(\n                    \"(cleanup problem)\",\n                    arg, msgbuf, bufsize);\n            }\n            break;\n        }\n        count = convertbuffer(arg, (const void **)p, &buf);\n        if (count < 0)\n            return converterr(buf, arg, msgbuf, bufsize);\n        if (*format == '#') {\n            Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);\n            *psize = count;\n            format++;\n        } else {\n            if (strlen(*p) != (size_t)count) {\n                PyErr_SetString(PyExc_ValueError, \"embedded null byte\");\n                RETURN_ERR_OCCURRED;\n            }\n        }\n        break;\n    }\n\n    case 's': /* text string or bytes-like object */\n    case 'z': /* text string, bytes-like object or None */\n    {\n        if (*format == '*') {\n            /* \"s*\" or \"z*\" */\n            Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *);\n\n            if (c == 'z' && arg == Py_None)\n                PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0);\n            else if (PyUnicode_Check(arg)) {\n                Py_ssize_t len;\n                sarg = PyUnicode_AsUTF8AndSize(arg, &len);\n                if (sarg == NULL)\n                    return converterr(CONV_UNICODE,\n                                      arg, msgbuf, bufsize);\n                PyBuffer_FillInfo(p, arg, (void *)sarg, len, 1, 0);\n            }\n            else { /* any bytes-like object */\n                const char *buf;\n                if (getbuffer(arg, p, &buf) < 0)\n                    return converterr(buf, arg, msgbuf, bufsize);\n            }\n            if (addcleanup(p, freelist, cleanup_buffer)) {\n                return converterr(\n                    \"(cleanup problem)\",\n                    arg, msgbuf, bufsize);\n            }\n            format++;\n        } else if (*format == '#') { /* a string or read-only bytes-like object */\n            /* \"s#\" or \"z#\" */\n            const void **p = (const void **)va_arg(*p_va, const char **);\n            Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);\n\n            if (c == 'z' && arg == Py_None) {\n                *p = NULL;\n                *psize = 0;\n            }\n            else if (PyUnicode_Check(arg)) {\n                Py_ssize_t len;\n                sarg = PyUnicode_AsUTF8AndSize(arg, &len);\n                if (sarg == NULL)\n                    return converterr(CONV_UNICODE,\n                                      arg, msgbuf, bufsize);\n                *p = sarg;\n                *psize = len;\n            }\n            else { /* read-only bytes-like object */\n                /* XXX Really? */\n                const char *buf;\n                Py_ssize_t count = convertbuffer(arg, p, &buf);\n                if (count < 0)\n                    return converterr(buf, arg, msgbuf, bufsize);\n                *psize = count;\n            }\n            format++;\n        } else {\n            /* \"s\" or \"z\" */\n            const char **p = va_arg(*p_va, const char **);\n            Py_ssize_t len;\n            sarg = NULL;\n\n            if (c == 'z' && arg == Py_None)\n                *p = NULL;\n            else if (PyUnicode_Check(arg)) {\n                sarg = PyUnicode_AsUTF8AndSize(arg, &len);\n                if (sarg == NULL)\n                    return converterr(CONV_UNICODE,\n                                      arg, msgbuf, bufsize);\n                if (strlen(sarg) != (size_t)len) {\n                    PyErr_SetString(PyExc_ValueError, \"embedded null character\");\n                    RETURN_ERR_OCCURRED;\n                }\n                *p = sarg;\n            }\n            else\n                return converterr(c == 'z' ? \"str or None\" : \"str\",\n                                  arg, msgbuf, bufsize);\n        }\n        break;\n    }\n\n    case 'e': {/* encoded string */\n        char **buffer;\n        const char *encoding;\n        PyObject *s;\n        int recode_strings;\n        Py_ssize_t size;\n        const char *ptr;\n\n        /* Get 'e' parameter: the encoding name */\n        encoding = (const char *)va_arg(*p_va, const char *);\n        if (encoding == NULL)\n            encoding = PyUnicode_GetDefaultEncoding();\n\n        /* Get output buffer parameter:\n           's' (recode all objects via Unicode) or\n           't' (only recode non-string objects)\n        */\n        if (*format == 's')\n            recode_strings = 1;\n        else if (*format == 't')\n            recode_strings = 0;\n        else\n            return converterr(\n                \"(unknown parser marker combination)\",\n                arg, msgbuf, bufsize);\n        buffer = (char **)va_arg(*p_va, char **);\n        format++;\n        if (buffer == NULL)\n            return converterr(\"(buffer is NULL)\",\n                              arg, msgbuf, bufsize);\n\n        /* Encode object */\n        if (!recode_strings &&\n            (PyBytes_Check(arg) || PyByteArray_Check(arg))) {\n            s = Py_NewRef(arg);\n            if (PyBytes_Check(arg)) {\n                size = PyBytes_GET_SIZE(s);\n                ptr = PyBytes_AS_STRING(s);\n            }\n            else {\n                size = PyByteArray_GET_SIZE(s);\n                ptr = PyByteArray_AS_STRING(s);\n            }\n        }\n        else if (PyUnicode_Check(arg)) {\n            /* Encode object; use default error handling */\n            s = PyUnicode_AsEncodedString(arg,\n                                          encoding,\n                                          NULL);\n            if (s == NULL)\n                return converterr(\"(encoding failed)\",\n                                  arg, msgbuf, bufsize);\n            assert(PyBytes_Check(s));\n            size = PyBytes_GET_SIZE(s);\n            ptr = PyBytes_AS_STRING(s);\n            if (ptr == NULL)\n                ptr = \"\";\n        }\n        else {\n            return converterr(\n                recode_strings ? \"str\" : \"str, bytes or bytearray\",\n                arg, msgbuf, bufsize);\n        }\n\n        /* Write output; output is guaranteed to be 0-terminated */\n        if (*format == '#') {\n            /* Using buffer length parameter '#':\n\n               - if *buffer is NULL, a new buffer of the\n               needed size is allocated and the data\n               copied into it; *buffer is updated to point\n               to the new buffer; the caller is\n               responsible for PyMem_Free()ing it after\n               usage\n\n               - if *buffer is not NULL, the data is\n               copied to *buffer; *buffer_len has to be\n               set to the size of the buffer on input;\n               buffer overflow is signalled with an error;\n               buffer has to provide enough room for the\n               encoded string plus the trailing 0-byte\n\n               - in both cases, *buffer_len is updated to\n               the size of the buffer /excluding/ the\n               trailing 0-byte\n\n            */\n            Py_ssize_t *psize = va_arg(*p_va, Py_ssize_t*);\n\n            format++;\n            if (psize == NULL) {\n                Py_DECREF(s);\n                return converterr(\n                    \"(buffer_len is NULL)\",\n                    arg, msgbuf, bufsize);\n            }\n            if (*buffer == NULL) {\n                *buffer = PyMem_NEW(char, size + 1);\n                if (*buffer == NULL) {\n                    Py_DECREF(s);\n                    PyErr_NoMemory();\n                    RETURN_ERR_OCCURRED;\n                }\n                if (addcleanup(buffer, freelist, cleanup_ptr)) {\n                    Py_DECREF(s);\n                    return converterr(\n                        \"(cleanup problem)\",\n                        arg, msgbuf, bufsize);\n                }\n            } else {\n                if (size + 1 > *psize) {\n                    Py_DECREF(s);\n                    PyErr_Format(PyExc_ValueError,\n                                 \"encoded string too long \"\n                                 \"(%zd, maximum length %zd)\",\n                                 (Py_ssize_t)size, (Py_ssize_t)(*psize - 1));\n                    RETURN_ERR_OCCURRED;\n                }\n            }\n            memcpy(*buffer, ptr, size+1);\n\n            *psize = size;\n        }\n        else {\n            /* Using a 0-terminated buffer:\n\n               - the encoded string has to be 0-terminated\n               for this variant to work; if it is not, an\n               error raised\n\n               - a new buffer of the needed size is\n               allocated and the data copied into it;\n               *buffer is updated to point to the new\n               buffer; the caller is responsible for\n               PyMem_Free()ing it after usage\n\n            */\n            if ((Py_ssize_t)strlen(ptr) != size) {\n                Py_DECREF(s);\n                return converterr(\n                    \"encoded string without null bytes\",\n                    arg, msgbuf, bufsize);\n            }\n            *buffer = PyMem_NEW(char, size + 1);\n            if (*buffer == NULL) {\n                Py_DECREF(s);\n                PyErr_NoMemory();\n                RETURN_ERR_OCCURRED;\n            }\n            if (addcleanup(buffer, freelist, cleanup_ptr)) {\n                Py_DECREF(s);\n                return converterr(\"(cleanup problem)\",\n                                arg, msgbuf, bufsize);\n            }\n            memcpy(*buffer, ptr, size+1);\n        }\n        Py_DECREF(s);\n        break;\n    }\n\n    case 'S': { /* PyBytes object */\n        PyObject **p = va_arg(*p_va, PyObject **);\n        if (PyBytes_Check(arg))\n            *p = arg;\n        else\n            return converterr(\"bytes\", arg, msgbuf, bufsize);\n        break;\n    }\n\n    case 'Y': { /* PyByteArray object */\n        PyObject **p = va_arg(*p_va, PyObject **);\n        if (PyByteArray_Check(arg))\n            *p = arg;\n        else\n            return converterr(\"bytearray\", arg, msgbuf, bufsize);\n        break;\n    }\n\n    case 'U': { /* PyUnicode object */\n        PyObject **p = va_arg(*p_va, PyObject **);\n        if (PyUnicode_Check(arg)) {\n            *p = arg;\n        }\n        else\n            return converterr(\"str\", arg, msgbuf, bufsize);\n        break;\n    }\n\n    case 'O': { /* object */\n        PyTypeObject *type;\n        PyObject **p;\n        if (*format == '!') {\n            type = va_arg(*p_va, PyTypeObject*);\n            p = va_arg(*p_va, PyObject **);\n            format++;\n            if (PyType_IsSubtype(Py_TYPE(arg), type))\n                *p = arg;\n            else\n                return converterr(type->tp_name, arg, msgbuf, bufsize);\n\n        }\n        else if (*format == '&') {\n            typedef int (*converter)(PyObject *, void *);\n            converter convert = va_arg(*p_va, converter);\n            void *addr = va_arg(*p_va, void *);\n            int res;\n            format++;\n            if (! (res = (*convert)(arg, addr)))\n                return converterr(\"(unspecified)\",\n                                  arg, msgbuf, bufsize);\n            if (res == Py_CLEANUP_SUPPORTED &&\n                addcleanup(addr, freelist, convert) == -1)\n                return converterr(\"(cleanup problem)\",\n                                arg, msgbuf, bufsize);\n        }\n        else {\n            p = va_arg(*p_va, PyObject **);\n            *p = arg;\n        }\n        break;\n    }\n\n\n    case 'w': { /* \"w*\": memory buffer, read-write access */\n        void **p = va_arg(*p_va, void **);\n\n        if (*format != '*')\n            return converterr(\n                \"(invalid use of 'w' format character)\",\n                arg, msgbuf, bufsize);\n        format++;\n\n        /* Caller is interested in Py_buffer, and the object\n           supports it directly. */\n        if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) {\n            PyErr_Clear();\n            return converterr(\"read-write bytes-like object\",\n                              arg, msgbuf, bufsize);\n        }\n        if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) {\n            PyBuffer_Release((Py_buffer*)p);\n            return converterr(\"contiguous buffer\", arg, msgbuf, bufsize);\n        }\n        if (addcleanup(p, freelist, cleanup_buffer)) {\n            return converterr(\n                \"(cleanup problem)\",\n                arg, msgbuf, bufsize);\n        }\n        break;\n    }\n\n    default:\n        return converterr(\"(impossible<bad format char>)\", arg, msgbuf, bufsize);\n\n    }\n\n    *p_format = format;\n    return NULL;\n\n#undef RETURN_ERR_OCCURRED\n}\n\nstatic Py_ssize_t\nconvertbuffer(PyObject *arg, const void **p, const char **errmsg)\n{\n    PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer;\n    Py_ssize_t count;\n    Py_buffer view;\n\n    *errmsg = NULL;\n    *p = NULL;\n    if (pb != NULL && pb->bf_releasebuffer != NULL) {\n        *errmsg = \"read-only bytes-like object\";\n        return -1;\n    }\n\n    if (getbuffer(arg, &view, errmsg) < 0)\n        return -1;\n    count = view.len;\n    *p = view.buf;\n    PyBuffer_Release(&view);\n    return count;\n}\n\nstatic int\ngetbuffer(PyObject *arg, Py_buffer *view, const char **errmsg)\n{\n    if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) {\n        *errmsg = \"bytes-like object\";\n        return -1;\n    }\n    if (!PyBuffer_IsContiguous(view, 'C')) {\n        PyBuffer_Release(view);\n        *errmsg = \"contiguous buffer\";\n        return -1;\n    }\n    return 0;\n}\n\n/* Support for keyword arguments donated by\n   Geoff Philbrick <philbric@delphi.hks.com> */\n\n/* Return false (0) for error, else true. */\nint\nPyArg_ParseTupleAndKeywords(PyObject *args,\n                            PyObject *keywords,\n                            const char *format,\n                            char **kwlist, ...)\n{\n    int retval;\n    va_list va;\n\n    if ((args == NULL || !PyTuple_Check(args)) ||\n        (keywords != NULL && !PyDict_Check(keywords)) ||\n        format == NULL ||\n        kwlist == NULL)\n    {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    va_start(va, kwlist);\n    retval = vgetargskeywords(args, keywords, format, kwlist, &va, 0);\n    va_end(va);\n    return retval;\n}\n\nint\n_PyArg_ParseTupleAndKeywords_SizeT(PyObject *args,\n                                  PyObject *keywords,\n                                  const char *format,\n                                  char **kwlist, ...)\n{\n    int retval;\n    va_list va;\n\n    if ((args == NULL || !PyTuple_Check(args)) ||\n        (keywords != NULL && !PyDict_Check(keywords)) ||\n        format == NULL ||\n        kwlist == NULL)\n    {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    va_start(va, kwlist);\n    retval = vgetargskeywords(args, keywords, format,\n                              kwlist, &va, 0);\n    va_end(va);\n    return retval;\n}\n\n\nint\nPyArg_VaParseTupleAndKeywords(PyObject *args,\n                              PyObject *keywords,\n                              const char *format,\n                              char **kwlist, va_list va)\n{\n    int retval;\n    va_list lva;\n\n    if ((args == NULL || !PyTuple_Check(args)) ||\n        (keywords != NULL && !PyDict_Check(keywords)) ||\n        format == NULL ||\n        kwlist == NULL)\n    {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    va_copy(lva, va);\n\n    retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0);\n    va_end(lva);\n    return retval;\n}\n\nint\n_PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args,\n                                    PyObject *keywords,\n                                    const char *format,\n                                    char **kwlist, va_list va)\n{\n    int retval;\n    va_list lva;\n\n    if ((args == NULL || !PyTuple_Check(args)) ||\n        (keywords != NULL && !PyDict_Check(keywords)) ||\n        format == NULL ||\n        kwlist == NULL)\n    {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    va_copy(lva, va);\n\n    retval = vgetargskeywords(args, keywords, format,\n                              kwlist, &lva, 0);\n    va_end(lva);\n    return retval;\n}\n\nPyAPI_FUNC(int)\n_PyArg_ParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords,\n                            struct _PyArg_Parser *parser, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, parser);\n    retval = vgetargskeywordsfast(args, keywords, parser, &va, 0);\n    va_end(va);\n    return retval;\n}\n\nint\n_PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,\n                            struct _PyArg_Parser *parser, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, parser);\n    retval = vgetargskeywordsfast(args, keywords, parser, &va, 0);\n    va_end(va);\n    return retval;\n}\n\nint\n_PyArg_ParseStackAndKeywords(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames,\n                  struct _PyArg_Parser *parser, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, parser);\n    retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, 0);\n    va_end(va);\n    return retval;\n}\n\nint\n_PyArg_ParseStackAndKeywords_SizeT(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames,\n                        struct _PyArg_Parser *parser, ...)\n{\n    int retval;\n    va_list va;\n\n    va_start(va, parser);\n    retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, 0);\n    va_end(va);\n    return retval;\n}\n\n\nPyAPI_FUNC(int)\n_PyArg_VaParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords,\n                            struct _PyArg_Parser *parser, va_list va)\n{\n    int retval;\n    va_list lva;\n\n    va_copy(lva, va);\n\n    retval = vgetargskeywordsfast(args, keywords, parser, &lva, 0);\n    va_end(lva);\n    return retval;\n}\n\nstatic void\nerror_unexpected_keyword_arg(PyObject *kwargs, PyObject *kwnames, PyObject *kwtuple, const char *fname)\n{\n    /* make sure there are no extraneous keyword arguments */\n    Py_ssize_t j = 0;\n    while (1) {\n        PyObject *keyword;\n        if (kwargs != NULL) {\n            if (!PyDict_Next(kwargs, &j, &keyword, NULL))\n                break;\n        }\n        else {\n            if (j >= PyTuple_GET_SIZE(kwnames))\n                break;\n            keyword = PyTuple_GET_ITEM(kwnames, j);\n            j++;\n        }\n        if (!PyUnicode_Check(keyword)) {\n            PyErr_SetString(PyExc_TypeError,\n                            \"keywords must be strings\");\n            return;\n        }\n\n        int match = PySequence_Contains(kwtuple, keyword);\n        if (match <= 0) {\n            if (!match) {\n                PyErr_Format(PyExc_TypeError,\n                             \"'%S' is an invalid keyword \"\n                             \"argument for %.200s%s\",\n                             keyword,\n                             (fname == NULL) ? \"this function\" : fname,\n                             (fname == NULL) ? \"\" : \"()\");\n            }\n            return;\n        }\n    }\n    /* Something wrong happened. There are extraneous keyword arguments,\n     * but we don't know what. And we don't bother. */\n    PyErr_Format(PyExc_TypeError,\n                 \"invalid keyword argument for %.200s%s\",\n                 (fname == NULL) ? \"this function\" : fname,\n                 (fname == NULL) ? \"\" : \"()\");\n}\n\nint\nPyArg_ValidateKeywordArguments(PyObject *kwargs)\n{\n    if (!PyDict_Check(kwargs)) {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n    if (!_PyDict_HasOnlyStringKeys(kwargs)) {\n        PyErr_SetString(PyExc_TypeError,\n                        \"keywords must be strings\");\n        return 0;\n    }\n    return 1;\n}\n\n#define IS_END_OF_FORMAT(c) (c == '\\0' || c == ';' || c == ':')\n\nstatic int\nvgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,\n                 char **kwlist, va_list *p_va, int flags)\n{\n    char msgbuf[512];\n    int levels[32];\n    const char *fname, *msg, *custom_msg;\n    int min = INT_MAX;\n    int max = INT_MAX;\n    int i, pos, len;\n    int skip = 0;\n    Py_ssize_t nargs, nkwargs;\n    PyObject *current_arg;\n    freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];\n    freelist_t freelist;\n\n    freelist.entries = static_entries;\n    freelist.first_available = 0;\n    freelist.entries_malloced = 0;\n\n    assert(args != NULL && PyTuple_Check(args));\n    assert(kwargs == NULL || PyDict_Check(kwargs));\n    assert(format != NULL);\n    assert(kwlist != NULL);\n    assert(p_va != NULL);\n\n    /* grab the function name or custom error msg first (mutually exclusive) */\n    fname = strchr(format, ':');\n    if (fname) {\n        fname++;\n        custom_msg = NULL;\n    }\n    else {\n        custom_msg = strchr(format,';');\n        if (custom_msg)\n            custom_msg++;\n    }\n\n    /* scan kwlist and count the number of positional-only parameters */\n    for (pos = 0; kwlist[pos] && !*kwlist[pos]; pos++) {\n    }\n    /* scan kwlist and get greatest possible nbr of args */\n    for (len = pos; kwlist[len]; len++) {\n        if (!*kwlist[len]) {\n            PyErr_SetString(PyExc_SystemError,\n                            \"Empty keyword parameter name\");\n            return cleanreturn(0, &freelist);\n        }\n    }\n\n    if (len > STATIC_FREELIST_ENTRIES) {\n        freelist.entries = PyMem_NEW(freelistentry_t, len);\n        if (freelist.entries == NULL) {\n            PyErr_NoMemory();\n            return 0;\n        }\n        freelist.entries_malloced = 1;\n    }\n\n    nargs = PyTuple_GET_SIZE(args);\n    nkwargs = (kwargs == NULL) ? 0 : PyDict_GET_SIZE(kwargs);\n    if (nargs + nkwargs > len) {\n        /* Adding \"keyword\" (when nargs == 0) prevents producing wrong error\n           messages in some special cases (see bpo-31229). */\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s%s takes at most %d %sargument%s (%zd given)\",\n                     (fname == NULL) ? \"function\" : fname,\n                     (fname == NULL) ? \"\" : \"()\",\n                     len,\n                     (nargs == 0) ? \"keyword \" : \"\",\n                     (len == 1) ? \"\" : \"s\",\n                     nargs + nkwargs);\n        return cleanreturn(0, &freelist);\n    }\n\n    /* convert tuple args and keyword args in same loop, using kwlist to drive process */\n    for (i = 0; i < len; i++) {\n        if (*format == '|') {\n            if (min != INT_MAX) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Invalid format string (| specified twice)\");\n                return cleanreturn(0, &freelist);\n            }\n\n            min = i;\n            format++;\n\n            if (max != INT_MAX) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Invalid format string ($ before |)\");\n                return cleanreturn(0, &freelist);\n            }\n        }\n        if (*format == '$') {\n            if (max != INT_MAX) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Invalid format string ($ specified twice)\");\n                return cleanreturn(0, &freelist);\n            }\n\n            max = i;\n            format++;\n\n            if (max < pos) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Empty parameter name after $\");\n                return cleanreturn(0, &freelist);\n            }\n            if (skip) {\n                /* Now we know the minimal and the maximal numbers of\n                 * positional arguments and can raise an exception with\n                 * informative message (see below). */\n                break;\n            }\n            if (max < nargs) {\n                if (max == 0) {\n                    PyErr_Format(PyExc_TypeError,\n                                 \"%.200s%s takes no positional arguments\",\n                                 (fname == NULL) ? \"function\" : fname,\n                                 (fname == NULL) ? \"\" : \"()\");\n                }\n                else {\n                    PyErr_Format(PyExc_TypeError,\n                                 \"%.200s%s takes %s %d positional argument%s\"\n                                 \" (%zd given)\",\n                                 (fname == NULL) ? \"function\" : fname,\n                                 (fname == NULL) ? \"\" : \"()\",\n                                 (min != INT_MAX) ? \"at most\" : \"exactly\",\n                                 max,\n                                 max == 1 ? \"\" : \"s\",\n                                 nargs);\n                }\n                return cleanreturn(0, &freelist);\n            }\n        }\n        if (IS_END_OF_FORMAT(*format)) {\n            PyErr_Format(PyExc_SystemError,\n                         \"More keyword list entries (%d) than \"\n                         \"format specifiers (%d)\", len, i);\n            return cleanreturn(0, &freelist);\n        }\n        if (!skip) {\n            if (i < nargs) {\n                current_arg = PyTuple_GET_ITEM(args, i);\n            }\n            else if (nkwargs && i >= pos) {\n                current_arg = _PyDict_GetItemStringWithError(kwargs, kwlist[i]);\n                if (current_arg) {\n                    --nkwargs;\n                }\n                else if (PyErr_Occurred()) {\n                    return cleanreturn(0, &freelist);\n                }\n            }\n            else {\n                current_arg = NULL;\n            }\n\n            if (current_arg) {\n                msg = convertitem(current_arg, &format, p_va, flags,\n                    levels, msgbuf, sizeof(msgbuf), &freelist);\n                if (msg) {\n                    seterror(i+1, msg, levels, fname, custom_msg);\n                    return cleanreturn(0, &freelist);\n                }\n                continue;\n            }\n\n            if (i < min) {\n                if (i < pos) {\n                    assert (min == INT_MAX);\n                    assert (max == INT_MAX);\n                    skip = 1;\n                    /* At that moment we still don't know the minimal and\n                     * the maximal numbers of positional arguments.  Raising\n                     * an exception is deferred until we encounter | and $\n                     * or the end of the format. */\n                }\n                else {\n                    PyErr_Format(PyExc_TypeError,  \"%.200s%s missing required \"\n                                 \"argument '%s' (pos %d)\",\n                                 (fname == NULL) ? \"function\" : fname,\n                                 (fname == NULL) ? \"\" : \"()\",\n                                 kwlist[i], i+1);\n                    return cleanreturn(0, &freelist);\n                }\n            }\n            /* current code reports success when all required args\n             * fulfilled and no keyword args left, with no further\n             * validation. XXX Maybe skip this in debug build ?\n             */\n            if (!nkwargs && !skip) {\n                return cleanreturn(1, &freelist);\n            }\n        }\n\n        /* We are into optional args, skip through to any remaining\n         * keyword args */\n        msg = skipitem(&format, p_va, flags);\n        if (msg) {\n            PyErr_Format(PyExc_SystemError, \"%s: '%s'\", msg,\n                         format);\n            return cleanreturn(0, &freelist);\n        }\n    }\n\n    if (skip) {\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s%s takes %s %d positional argument%s\"\n                     \" (%zd given)\",\n                     (fname == NULL) ? \"function\" : fname,\n                     (fname == NULL) ? \"\" : \"()\",\n                     (Py_MIN(pos, min) < i) ? \"at least\" : \"exactly\",\n                     Py_MIN(pos, min),\n                     Py_MIN(pos, min) == 1 ? \"\" : \"s\",\n                     nargs);\n        return cleanreturn(0, &freelist);\n    }\n\n    if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) {\n        PyErr_Format(PyExc_SystemError,\n            \"more argument specifiers than keyword list entries \"\n            \"(remaining format:'%s')\", format);\n        return cleanreturn(0, &freelist);\n    }\n\n    if (nkwargs > 0) {\n        PyObject *key;\n        Py_ssize_t j;\n        /* make sure there are no arguments given by name and position */\n        for (i = pos; i < nargs; i++) {\n            current_arg = _PyDict_GetItemStringWithError(kwargs, kwlist[i]);\n            if (current_arg) {\n                /* arg present in tuple and in dict */\n                PyErr_Format(PyExc_TypeError,\n                             \"argument for %.200s%s given by name ('%s') \"\n                             \"and position (%d)\",\n                             (fname == NULL) ? \"function\" : fname,\n                             (fname == NULL) ? \"\" : \"()\",\n                             kwlist[i], i+1);\n                return cleanreturn(0, &freelist);\n            }\n            else if (PyErr_Occurred()) {\n                return cleanreturn(0, &freelist);\n            }\n        }\n        /* make sure there are no extraneous keyword arguments */\n        j = 0;\n        while (PyDict_Next(kwargs, &j, &key, NULL)) {\n            int match = 0;\n            if (!PyUnicode_Check(key)) {\n                PyErr_SetString(PyExc_TypeError,\n                                \"keywords must be strings\");\n                return cleanreturn(0, &freelist);\n            }\n            for (i = pos; i < len; i++) {\n                if (_PyUnicode_EqualToASCIIString(key, kwlist[i])) {\n                    match = 1;\n                    break;\n                }\n            }\n            if (!match) {\n                PyErr_Format(PyExc_TypeError,\n                             \"'%U' is an invalid keyword \"\n                             \"argument for %.200s%s\",\n                             key,\n                             (fname == NULL) ? \"this function\" : fname,\n                             (fname == NULL) ? \"\" : \"()\");\n                return cleanreturn(0, &freelist);\n            }\n        }\n        /* Something wrong happened. There are extraneous keyword arguments,\n         * but we don't know what. And we don't bother. */\n        PyErr_Format(PyExc_TypeError,\n                     \"invalid keyword argument for %.200s%s\",\n                     (fname == NULL) ? \"this function\" : fname,\n                     (fname == NULL) ? \"\" : \"()\");\n        return cleanreturn(0, &freelist);\n    }\n\n    return cleanreturn(1, &freelist);\n}\n\n\nstatic int\nscan_keywords(const char * const *keywords, int *ptotal, int *pposonly)\n{\n    /* scan keywords and count the number of positional-only parameters */\n    int i;\n    for (i = 0; keywords[i] && !*keywords[i]; i++) {\n    }\n    *pposonly = i;\n\n    /* scan keywords and get greatest possible nbr of args */\n    for (; keywords[i]; i++) {\n        if (!*keywords[i]) {\n            PyErr_SetString(PyExc_SystemError,\n                            \"Empty keyword parameter name\");\n            return -1;\n        }\n    }\n    *ptotal = i;\n    return 0;\n}\n\nstatic int\nparse_format(const char *format, int total, int npos,\n             const char **pfname, const char **pcustommsg,\n             int *pmin, int *pmax)\n{\n    /* grab the function name or custom error msg first (mutually exclusive) */\n    const char *custommsg;\n    const char *fname = strchr(format, ':');\n    if (fname) {\n        fname++;\n        custommsg = NULL;\n    }\n    else {\n        custommsg = strchr(format,';');\n        if (custommsg) {\n            custommsg++;\n        }\n    }\n\n    int min = INT_MAX;\n    int max = INT_MAX;\n    for (int i = 0; i < total; i++) {\n        if (*format == '|') {\n            if (min != INT_MAX) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Invalid format string (| specified twice)\");\n                return -1;\n            }\n            if (max != INT_MAX) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Invalid format string ($ before |)\");\n                return -1;\n            }\n            min = i;\n            format++;\n        }\n        if (*format == '$') {\n            if (max != INT_MAX) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Invalid format string ($ specified twice)\");\n                return -1;\n            }\n            if (i < npos) {\n                PyErr_SetString(PyExc_SystemError,\n                                \"Empty parameter name after $\");\n                return -1;\n            }\n            max = i;\n            format++;\n        }\n        if (IS_END_OF_FORMAT(*format)) {\n            PyErr_Format(PyExc_SystemError,\n                        \"More keyword list entries (%d) than \"\n                        \"format specifiers (%d)\", total, i);\n            return -1;\n        }\n\n        const char *msg = skipitem(&format, NULL, 0);\n        if (msg) {\n            PyErr_Format(PyExc_SystemError, \"%s: '%s'\", msg,\n                        format);\n            return -1;\n        }\n    }\n    min = Py_MIN(min, total);\n    max = Py_MIN(max, total);\n\n    if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) {\n        PyErr_Format(PyExc_SystemError,\n            \"more argument specifiers than keyword list entries \"\n            \"(remaining format:'%s')\", format);\n        return -1;\n    }\n\n    *pfname = fname;\n    *pcustommsg = custommsg;\n    *pmin = min;\n    *pmax = max;\n    return 0;\n}\n\nstatic PyObject *\nnew_kwtuple(const char * const *keywords, int total, int pos)\n{\n    int nkw = total - pos;\n    PyObject *kwtuple = PyTuple_New(nkw);\n    if (kwtuple == NULL) {\n        return NULL;\n    }\n    keywords += pos;\n    for (int i = 0; i < nkw; i++) {\n        PyObject *str = PyUnicode_FromString(keywords[i]);\n        if (str == NULL) {\n            Py_DECREF(kwtuple);\n            return NULL;\n        }\n        PyUnicode_InternInPlace(&str);\n        PyTuple_SET_ITEM(kwtuple, i, str);\n    }\n    return kwtuple;\n}\n\nstatic int\n_parser_init(struct _PyArg_Parser *parser)\n{\n    const char * const *keywords = parser->keywords;\n    assert(keywords != NULL);\n    assert(parser->pos == 0 &&\n           (parser->format == NULL || parser->fname == NULL) &&\n           parser->custom_msg == NULL &&\n           parser->min == 0 &&\n           parser->max == 0);\n\n    int len, pos;\n    if (scan_keywords(keywords, &len, &pos) < 0) {\n        return 0;\n    }\n\n    const char *fname, *custommsg = NULL;\n    int min = 0, max = 0;\n    if (parser->format) {\n        assert(parser->fname == NULL);\n        if (parse_format(parser->format, len, pos,\n                         &fname, &custommsg, &min, &max) < 0) {\n            return 0;\n        }\n    }\n    else {\n        assert(parser->fname != NULL);\n        fname = parser->fname;\n    }\n\n    int owned;\n    PyObject *kwtuple = parser->kwtuple;\n    if (kwtuple == NULL) {\n        kwtuple = new_kwtuple(keywords, len, pos);\n        if (kwtuple == NULL) {\n            return 0;\n        }\n        owned = 1;\n    }\n    else {\n        owned = 0;\n    }\n\n    parser->pos = pos;\n    parser->fname = fname;\n    parser->custom_msg = custommsg;\n    parser->min = min;\n    parser->max = max;\n    parser->kwtuple = kwtuple;\n    parser->initialized = owned ? 1 : -1;\n\n    assert(parser->next == NULL);\n    parser->next = _PyRuntime.getargs.static_parsers;\n    _PyRuntime.getargs.static_parsers = parser;\n    return 1;\n}\n\nstatic int\nparser_init(struct _PyArg_Parser *parser)\n{\n    // volatile as it can be modified by other threads\n    // and should not be optimized or reordered by compiler\n    if (*((volatile int *)&parser->initialized)) {\n        assert(parser->kwtuple != NULL);\n        return 1;\n    }\n    PyThread_acquire_lock(_PyRuntime.getargs.mutex, WAIT_LOCK);\n    // Check again if another thread initialized the parser\n    // while we were waiting for the lock.\n    if (*((volatile int *)&parser->initialized)) {\n        assert(parser->kwtuple != NULL);\n        PyThread_release_lock(_PyRuntime.getargs.mutex);\n        return 1;\n    }\n    int ret = _parser_init(parser);\n    PyThread_release_lock(_PyRuntime.getargs.mutex);\n    return ret;\n}\n\nstatic void\nparser_clear(struct _PyArg_Parser *parser)\n{\n    if (parser->initialized == 1) {\n        Py_CLEAR(parser->kwtuple);\n    }\n}\n\nstatic PyObject*\nfind_keyword(PyObject *kwnames, PyObject *const *kwstack, PyObject *key)\n{\n    Py_ssize_t i, nkwargs;\n\n    nkwargs = PyTuple_GET_SIZE(kwnames);\n    for (i = 0; i < nkwargs; i++) {\n        PyObject *kwname = PyTuple_GET_ITEM(kwnames, i);\n\n        /* kwname == key will normally find a match in since keyword keys\n           should be interned strings; if not retry below in a new loop. */\n        if (kwname == key) {\n            return kwstack[i];\n        }\n    }\n\n    for (i = 0; i < nkwargs; i++) {\n        PyObject *kwname = PyTuple_GET_ITEM(kwnames, i);\n        assert(PyUnicode_Check(kwname));\n        if (_PyUnicode_EQ(kwname, key)) {\n            return kwstack[i];\n        }\n    }\n    return NULL;\n}\n\nstatic int\nvgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,\n                          PyObject *kwargs, PyObject *kwnames,\n                          struct _PyArg_Parser *parser,\n                          va_list *p_va, int flags)\n{\n    PyObject *kwtuple;\n    char msgbuf[512];\n    int levels[32];\n    const char *format;\n    const char *msg;\n    PyObject *keyword;\n    int i, pos, len;\n    Py_ssize_t nkwargs;\n    PyObject *current_arg;\n    freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];\n    freelist_t freelist;\n    PyObject *const *kwstack = NULL;\n\n    freelist.entries = static_entries;\n    freelist.first_available = 0;\n    freelist.entries_malloced = 0;\n\n    assert(kwargs == NULL || PyDict_Check(kwargs));\n    assert(kwargs == NULL || kwnames == NULL);\n    assert(p_va != NULL);\n\n    if (parser == NULL) {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    if (kwnames != NULL && !PyTuple_Check(kwnames)) {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    if (!parser_init(parser)) {\n        return 0;\n    }\n\n    kwtuple = parser->kwtuple;\n    pos = parser->pos;\n    len = pos + (int)PyTuple_GET_SIZE(kwtuple);\n\n    if (len > STATIC_FREELIST_ENTRIES) {\n        freelist.entries = PyMem_NEW(freelistentry_t, len);\n        if (freelist.entries == NULL) {\n            PyErr_NoMemory();\n            return 0;\n        }\n        freelist.entries_malloced = 1;\n    }\n\n    if (kwargs != NULL) {\n        nkwargs = PyDict_GET_SIZE(kwargs);\n    }\n    else if (kwnames != NULL) {\n        nkwargs = PyTuple_GET_SIZE(kwnames);\n        kwstack = args + nargs;\n    }\n    else {\n        nkwargs = 0;\n    }\n    if (nargs + nkwargs > len) {\n        /* Adding \"keyword\" (when nargs == 0) prevents producing wrong error\n           messages in some special cases (see bpo-31229). */\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s%s takes at most %d %sargument%s (%zd given)\",\n                     (parser->fname == NULL) ? \"function\" : parser->fname,\n                     (parser->fname == NULL) ? \"\" : \"()\",\n                     len,\n                     (nargs == 0) ? \"keyword \" : \"\",\n                     (len == 1) ? \"\" : \"s\",\n                     nargs + nkwargs);\n        return cleanreturn(0, &freelist);\n    }\n    if (parser->max < nargs) {\n        if (parser->max == 0) {\n            PyErr_Format(PyExc_TypeError,\n                         \"%.200s%s takes no positional arguments\",\n                         (parser->fname == NULL) ? \"function\" : parser->fname,\n                         (parser->fname == NULL) ? \"\" : \"()\");\n        }\n        else {\n            PyErr_Format(PyExc_TypeError,\n                         \"%.200s%s takes %s %d positional argument%s (%zd given)\",\n                         (parser->fname == NULL) ? \"function\" : parser->fname,\n                         (parser->fname == NULL) ? \"\" : \"()\",\n                         (parser->min < parser->max) ? \"at most\" : \"exactly\",\n                         parser->max,\n                         parser->max == 1 ? \"\" : \"s\",\n                         nargs);\n        }\n        return cleanreturn(0, &freelist);\n    }\n\n    format = parser->format;\n    assert(format != NULL || len == 0);\n    /* convert tuple args and keyword args in same loop, using kwtuple to drive process */\n    for (i = 0; i < len; i++) {\n        if (*format == '|') {\n            format++;\n        }\n        if (*format == '$') {\n            format++;\n        }\n        assert(!IS_END_OF_FORMAT(*format));\n\n        if (i < nargs) {\n            current_arg = args[i];\n        }\n        else if (nkwargs && i >= pos) {\n            keyword = PyTuple_GET_ITEM(kwtuple, i - pos);\n            if (kwargs != NULL) {\n                current_arg = PyDict_GetItemWithError(kwargs, keyword);\n                if (!current_arg && PyErr_Occurred()) {\n                    return cleanreturn(0, &freelist);\n                }\n            }\n            else {\n                current_arg = find_keyword(kwnames, kwstack, keyword);\n            }\n            if (current_arg) {\n                --nkwargs;\n            }\n        }\n        else {\n            current_arg = NULL;\n        }\n\n        if (current_arg) {\n            msg = convertitem(current_arg, &format, p_va, flags,\n                levels, msgbuf, sizeof(msgbuf), &freelist);\n            if (msg) {\n                seterror(i+1, msg, levels, parser->fname, parser->custom_msg);\n                return cleanreturn(0, &freelist);\n            }\n            continue;\n        }\n\n        if (i < parser->min) {\n            /* Less arguments than required */\n            if (i < pos) {\n                Py_ssize_t min = Py_MIN(pos, parser->min);\n                PyErr_Format(PyExc_TypeError,\n                             \"%.200s%s takes %s %d positional argument%s\"\n                             \" (%zd given)\",\n                             (parser->fname == NULL) ? \"function\" : parser->fname,\n                             (parser->fname == NULL) ? \"\" : \"()\",\n                             min < parser->max ? \"at least\" : \"exactly\",\n                             min,\n                             min == 1 ? \"\" : \"s\",\n                             nargs);\n            }\n            else {\n                keyword = PyTuple_GET_ITEM(kwtuple, i - pos);\n                PyErr_Format(PyExc_TypeError,  \"%.200s%s missing required \"\n                             \"argument '%U' (pos %d)\",\n                             (parser->fname == NULL) ? \"function\" : parser->fname,\n                             (parser->fname == NULL) ? \"\" : \"()\",\n                             keyword, i+1);\n            }\n            return cleanreturn(0, &freelist);\n        }\n        /* current code reports success when all required args\n         * fulfilled and no keyword args left, with no further\n         * validation. XXX Maybe skip this in debug build ?\n         */\n        if (!nkwargs) {\n            return cleanreturn(1, &freelist);\n        }\n\n        /* We are into optional args, skip through to any remaining\n         * keyword args */\n        msg = skipitem(&format, p_va, flags);\n        assert(msg == NULL);\n    }\n\n    assert(IS_END_OF_FORMAT(*format) || (*format == '|') || (*format == '$'));\n\n    if (nkwargs > 0) {\n        /* make sure there are no arguments given by name and position */\n        for (i = pos; i < nargs; i++) {\n            keyword = PyTuple_GET_ITEM(kwtuple, i - pos);\n            if (kwargs != NULL) {\n                current_arg = PyDict_GetItemWithError(kwargs, keyword);\n                if (!current_arg && PyErr_Occurred()) {\n                    return cleanreturn(0, &freelist);\n                }\n            }\n            else {\n                current_arg = find_keyword(kwnames, kwstack, keyword);\n            }\n            if (current_arg) {\n                /* arg present in tuple and in dict */\n                PyErr_Format(PyExc_TypeError,\n                             \"argument for %.200s%s given by name ('%U') \"\n                             \"and position (%d)\",\n                             (parser->fname == NULL) ? \"function\" : parser->fname,\n                             (parser->fname == NULL) ? \"\" : \"()\",\n                             keyword, i+1);\n                return cleanreturn(0, &freelist);\n            }\n        }\n\n        error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname);\n        return cleanreturn(0, &freelist);\n    }\n\n    return cleanreturn(1, &freelist);\n}\n\nstatic int\nvgetargskeywordsfast(PyObject *args, PyObject *keywords,\n                     struct _PyArg_Parser *parser, va_list *p_va, int flags)\n{\n    PyObject **stack;\n    Py_ssize_t nargs;\n\n    if (args == NULL\n        || !PyTuple_Check(args)\n        || (keywords != NULL && !PyDict_Check(keywords)))\n    {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n\n    stack = _PyTuple_ITEMS(args);\n    nargs = PyTuple_GET_SIZE(args);\n    return vgetargskeywordsfast_impl(stack, nargs, keywords, NULL,\n                                     parser, p_va, flags);\n}\n\n\n#undef _PyArg_UnpackKeywords\n\nPyObject * const *\n_PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,\n                      PyObject *kwargs, PyObject *kwnames,\n                      struct _PyArg_Parser *parser,\n                      int minpos, int maxpos, int minkw,\n                      PyObject **buf)\n{\n    PyObject *kwtuple;\n    PyObject *keyword;\n    int i, posonly, minposonly, maxargs;\n    int reqlimit = minkw ? maxpos + minkw : minpos;\n    Py_ssize_t nkwargs;\n    PyObject *current_arg;\n    PyObject * const *kwstack = NULL;\n\n    assert(kwargs == NULL || PyDict_Check(kwargs));\n    assert(kwargs == NULL || kwnames == NULL);\n\n    if (parser == NULL) {\n        PyErr_BadInternalCall();\n        return NULL;\n    }\n\n    if (kwnames != NULL && !PyTuple_Check(kwnames)) {\n        PyErr_BadInternalCall();\n        return NULL;\n    }\n\n    if (args == NULL && nargs == 0) {\n        args = buf;\n    }\n\n    if (!parser_init(parser)) {\n        return NULL;\n    }\n\n    kwtuple = parser->kwtuple;\n    posonly = parser->pos;\n    minposonly = Py_MIN(posonly, minpos);\n    maxargs = posonly + (int)PyTuple_GET_SIZE(kwtuple);\n\n    if (kwargs != NULL) {\n        nkwargs = PyDict_GET_SIZE(kwargs);\n    }\n    else if (kwnames != NULL) {\n        nkwargs = PyTuple_GET_SIZE(kwnames);\n        kwstack = args + nargs;\n    }\n    else {\n        nkwargs = 0;\n    }\n    if (nkwargs == 0 && minkw == 0 && minpos <= nargs && nargs <= maxpos) {\n        /* Fast path. */\n        return args;\n    }\n    if (nargs + nkwargs > maxargs) {\n        /* Adding \"keyword\" (when nargs == 0) prevents producing wrong error\n           messages in some special cases (see bpo-31229). */\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s%s takes at most %d %sargument%s (%zd given)\",\n                     (parser->fname == NULL) ? \"function\" : parser->fname,\n                     (parser->fname == NULL) ? \"\" : \"()\",\n                     maxargs,\n                     (nargs == 0) ? \"keyword \" : \"\",\n                     (maxargs == 1) ? \"\" : \"s\",\n                     nargs + nkwargs);\n        return NULL;\n    }\n    if (nargs > maxpos) {\n        if (maxpos == 0) {\n            PyErr_Format(PyExc_TypeError,\n                         \"%.200s%s takes no positional arguments\",\n                         (parser->fname == NULL) ? \"function\" : parser->fname,\n                         (parser->fname == NULL) ? \"\" : \"()\");\n        }\n        else {\n            PyErr_Format(PyExc_TypeError,\n                         \"%.200s%s takes %s %d positional argument%s (%zd given)\",\n                         (parser->fname == NULL) ? \"function\" : parser->fname,\n                         (parser->fname == NULL) ? \"\" : \"()\",\n                         (minpos < maxpos) ? \"at most\" : \"exactly\",\n                         maxpos,\n                         (maxpos == 1) ? \"\" : \"s\",\n                         nargs);\n        }\n        return NULL;\n    }\n    if (nargs < minposonly) {\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s%s takes %s %d positional argument%s\"\n                     \" (%zd given)\",\n                     (parser->fname == NULL) ? \"function\" : parser->fname,\n                     (parser->fname == NULL) ? \"\" : \"()\",\n                     minposonly < maxpos ? \"at least\" : \"exactly\",\n                     minposonly,\n                     minposonly == 1 ? \"\" : \"s\",\n                     nargs);\n        return NULL;\n    }\n\n    /* copy tuple args */\n    for (i = 0; i < nargs; i++) {\n        buf[i] = args[i];\n    }\n\n    /* copy keyword args using kwtuple to drive process */\n    for (i = Py_MAX((int)nargs, posonly); i < maxargs; i++) {\n        if (nkwargs) {\n            keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);\n            if (kwargs != NULL) {\n                current_arg = PyDict_GetItemWithError(kwargs, keyword);\n                if (!current_arg && PyErr_Occurred()) {\n                    return NULL;\n                }\n            }\n            else {\n                current_arg = find_keyword(kwnames, kwstack, keyword);\n            }\n        }\n        else if (i >= reqlimit) {\n            break;\n        }\n        else {\n            current_arg = NULL;\n        }\n\n        buf[i] = current_arg;\n\n        if (current_arg) {\n            --nkwargs;\n        }\n        else if (i < minpos || (maxpos <= i && i < reqlimit)) {\n            /* Less arguments than required */\n            keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);\n            PyErr_Format(PyExc_TypeError,  \"%.200s%s missing required \"\n                         \"argument '%U' (pos %d)\",\n                         (parser->fname == NULL) ? \"function\" : parser->fname,\n                         (parser->fname == NULL) ? \"\" : \"()\",\n                         keyword, i+1);\n            return NULL;\n        }\n    }\n\n    if (nkwargs > 0) {\n        /* make sure there are no arguments given by name and position */\n        for (i = posonly; i < nargs; i++) {\n            keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);\n            if (kwargs != NULL) {\n                current_arg = PyDict_GetItemWithError(kwargs, keyword);\n                if (!current_arg && PyErr_Occurred()) {\n                    return NULL;\n                }\n            }\n            else {\n                current_arg = find_keyword(kwnames, kwstack, keyword);\n            }\n            if (current_arg) {\n                /* arg present in tuple and in dict */\n                PyErr_Format(PyExc_TypeError,\n                             \"argument for %.200s%s given by name ('%U') \"\n                             \"and position (%d)\",\n                             (parser->fname == NULL) ? \"function\" : parser->fname,\n                             (parser->fname == NULL) ? \"\" : \"()\",\n                             keyword, i+1);\n                return NULL;\n            }\n        }\n\n        error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname);\n        return NULL;\n    }\n\n    return buf;\n}\n\nPyObject * const *\n_PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs,\n                                PyObject *kwargs, PyObject *kwnames,\n                                struct _PyArg_Parser *parser,\n                                int minpos, int maxpos, int minkw,\n                                int vararg, PyObject **buf)\n{\n    PyObject *kwtuple;\n    PyObject *keyword;\n    Py_ssize_t varargssize = 0;\n    int i, posonly, minposonly, maxargs;\n    int reqlimit = minkw ? maxpos + minkw : minpos;\n    Py_ssize_t nkwargs;\n    PyObject *current_arg;\n    PyObject * const *kwstack = NULL;\n\n    assert(kwargs == NULL || PyDict_Check(kwargs));\n    assert(kwargs == NULL || kwnames == NULL);\n\n    if (parser == NULL) {\n        PyErr_BadInternalCall();\n        return NULL;\n    }\n\n    if (kwnames != NULL && !PyTuple_Check(kwnames)) {\n        PyErr_BadInternalCall();\n        return NULL;\n    }\n\n    if (args == NULL && nargs == 0) {\n        args = buf;\n    }\n\n    if (!parser_init(parser)) {\n        return NULL;\n    }\n\n    kwtuple = parser->kwtuple;\n    posonly = parser->pos;\n    minposonly = Py_MIN(posonly, minpos);\n    maxargs = posonly + (int)PyTuple_GET_SIZE(kwtuple);\n    if (kwargs != NULL) {\n        nkwargs = PyDict_GET_SIZE(kwargs);\n    }\n    else if (kwnames != NULL) {\n        nkwargs = PyTuple_GET_SIZE(kwnames);\n        kwstack = args + nargs;\n    }\n    else {\n        nkwargs = 0;\n    }\n    if (nargs < minposonly) {\n        PyErr_Format(PyExc_TypeError,\n                     \"%.200s%s takes %s %d positional argument%s\"\n                     \" (%zd given)\",\n                     (parser->fname == NULL) ? \"function\" : parser->fname,\n                     (parser->fname == NULL) ? \"\" : \"()\",\n                     minposonly < maxpos ? \"at least\" : \"exactly\",\n                     minposonly,\n                     minposonly == 1 ? \"\" : \"s\",\n                     nargs);\n        return NULL;\n    }\n\n    /* create varargs tuple */\n    varargssize = nargs - maxpos;\n    if (varargssize < 0) {\n        varargssize = 0;\n    }\n    buf[vararg] = PyTuple_New(varargssize);\n    if (!buf[vararg]) {\n        return NULL;\n    }\n\n    /* copy tuple args */\n    for (i = 0; i < nargs; i++) {\n        if (i >= vararg) {\n            PyTuple_SET_ITEM(buf[vararg], i - vararg, Py_NewRef(args[i]));\n            continue;\n        }\n        else {\n            buf[i] = args[i];\n        }\n    }\n\n    /* copy keyword args using kwtuple to drive process */\n    for (i = Py_MAX((int)nargs, posonly) -\n         Py_SAFE_DOWNCAST(varargssize, Py_ssize_t, int); i < maxargs; i++) {\n        if (nkwargs) {\n            keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);\n            if (kwargs != NULL) {\n                current_arg = PyDict_GetItemWithError(kwargs, keyword);\n                if (!current_arg && PyErr_Occurred()) {\n                    goto exit;\n                }\n            }\n            else {\n                current_arg = find_keyword(kwnames, kwstack, keyword);\n            }\n        }\n        else {\n            current_arg = NULL;\n        }\n\n        /* If an arguments is passed in as a keyword argument,\n         * it should be placed before `buf[vararg]`.\n         *\n         * For example:\n         * def f(a, /, b, *args):\n         *     pass\n         * f(1, b=2)\n         *\n         * This `buf` array should be: [1, 2, NULL].\n         * In this case, nargs < vararg.\n         *\n         * Otherwise, we leave a place at `buf[vararg]` for vararg tuple\n         * so the index is `i + 1`. */\n        if (nargs < vararg) {\n            buf[i] = current_arg;\n        }\n        else {\n            buf[i + 1] = current_arg;\n        }\n\n        if (current_arg) {\n            --nkwargs;\n        }\n        else if (i < minpos || (maxpos <= i && i < reqlimit)) {\n            /* Less arguments than required */\n            keyword = PyTuple_GET_ITEM(kwtuple, i - posonly);\n            PyErr_Format(PyExc_TypeError,  \"%.200s%s missing required \"\n                         \"argument '%U' (pos %d)\",\n                         (parser->fname == NULL) ? \"function\" : parser->fname,\n                         (parser->fname == NULL) ? \"\" : \"()\",\n                         keyword, i+1);\n            goto exit;\n        }\n    }\n\n    if (nkwargs > 0) {\n        error_unexpected_keyword_arg(kwargs, kwnames, kwtuple, parser->fname);\n        goto exit;\n    }\n\n    return buf;\n\nexit:\n    Py_XDECREF(buf[vararg]);\n    return NULL;\n}\n\n\nstatic const char *\nskipitem(const char **p_format, va_list *p_va, int flags)\n{\n    const char *format = *p_format;\n    char c = *format++;\n\n    switch (c) {\n\n    /*\n     * codes that take a single data pointer as an argument\n     * (the type of the pointer is irrelevant)\n     */\n\n    case 'b': /* byte -- very short int */\n    case 'B': /* byte as bitfield */\n    case 'h': /* short int */\n    case 'H': /* short int as bitfield */\n    case 'i': /* int */\n    case 'I': /* int sized bitfield */\n    case 'l': /* long int */\n    case 'k': /* long int sized bitfield */\n    case 'L': /* long long */\n    case 'K': /* long long sized bitfield */\n    case 'n': /* Py_ssize_t */\n    case 'f': /* float */\n    case 'd': /* double */\n    case 'D': /* complex double */\n    case 'c': /* char */\n    case 'C': /* unicode char */\n    case 'p': /* boolean predicate */\n    case 'S': /* string object */\n    case 'Y': /* string object */\n    case 'U': /* unicode string object */\n        {\n            if (p_va != NULL) {\n                (void) va_arg(*p_va, void *);\n            }\n            break;\n        }\n\n    /* string codes */\n\n    case 'e': /* string with encoding */\n        {\n            if (p_va != NULL) {\n                (void) va_arg(*p_va, const char *);\n            }\n            if (!(*format == 's' || *format == 't'))\n                /* after 'e', only 's' and 't' is allowed */\n                goto err;\n            format++;\n        }\n        /* fall through */\n\n    case 's': /* string */\n    case 'z': /* string or None */\n    case 'y': /* bytes */\n    case 'w': /* buffer, read-write */\n        {\n            if (p_va != NULL) {\n                (void) va_arg(*p_va, char **);\n            }\n            if (*format == '#') {\n                if (p_va != NULL) {\n                    (void) va_arg(*p_va, Py_ssize_t *);\n                }\n                format++;\n            } else if ((c == 's' || c == 'z' || c == 'y' || c == 'w')\n                       && *format == '*')\n            {\n                format++;\n            }\n            break;\n        }\n\n    case 'O': /* object */\n        {\n            if (*format == '!') {\n                format++;\n                if (p_va != NULL) {\n                    (void) va_arg(*p_va, PyTypeObject*);\n                    (void) va_arg(*p_va, PyObject **);\n                }\n            }\n            else if (*format == '&') {\n                typedef int (*converter)(PyObject *, void *);\n                if (p_va != NULL) {\n                    (void) va_arg(*p_va, converter);\n                    (void) va_arg(*p_va, void *);\n                }\n                format++;\n            }\n            else {\n                if (p_va != NULL) {\n                    (void) va_arg(*p_va, PyObject **);\n                }\n            }\n            break;\n        }\n\n    case '(':           /* bypass tuple, not handled at all previously */\n        {\n            const char *msg;\n            for (;;) {\n                if (*format==')')\n                    break;\n                if (IS_END_OF_FORMAT(*format))\n                    return \"Unmatched left paren in format \"\n                           \"string\";\n                msg = skipitem(&format, p_va, flags);\n                if (msg)\n                    return msg;\n            }\n            format++;\n            break;\n        }\n\n    case ')':\n        return \"Unmatched right paren in format string\";\n\n    default:\nerr:\n        return \"impossible<bad format char>\";\n\n    }\n\n    *p_format = format;\n    return NULL;\n}\n\n\n#undef _PyArg_CheckPositional\n\nint\n_PyArg_CheckPositional(const char *name, Py_ssize_t nargs,\n                       Py_ssize_t min, Py_ssize_t max)\n{\n    assert(min >= 0);\n    assert(min <= max);\n\n    if (nargs < min) {\n        if (name != NULL)\n            PyErr_Format(\n                PyExc_TypeError,\n                \"%.200s expected %s%zd argument%s, got %zd\",\n                name, (min == max ? \"\" : \"at least \"), min, min == 1 ? \"\" : \"s\", nargs);\n        else\n            PyErr_Format(\n                PyExc_TypeError,\n                \"unpacked tuple should have %s%zd element%s,\"\n                \" but has %zd\",\n                (min == max ? \"\" : \"at least \"), min, min == 1 ? \"\" : \"s\", nargs);\n        return 0;\n    }\n\n    if (nargs == 0) {\n        return 1;\n    }\n\n    if (nargs > max) {\n        if (name != NULL)\n            PyErr_Format(\n                PyExc_TypeError,\n                \"%.200s expected %s%zd argument%s, got %zd\",\n                name, (min == max ? \"\" : \"at most \"), max, max == 1 ? \"\" : \"s\", nargs);\n        else\n            PyErr_Format(\n                PyExc_TypeError,\n                \"unpacked tuple should have %s%zd element%s,\"\n                \" but has %zd\",\n                (min == max ? \"\" : \"at most \"), max, max == 1 ? \"\" : \"s\", nargs);\n        return 0;\n    }\n\n    return 1;\n}\n\nstatic int\nunpack_stack(PyObject *const *args, Py_ssize_t nargs, const char *name,\n             Py_ssize_t min, Py_ssize_t max, va_list vargs)\n{\n    Py_ssize_t i;\n    PyObject **o;\n\n    if (!_PyArg_CheckPositional(name, nargs, min, max)) {\n        return 0;\n    }\n\n    for (i = 0; i < nargs; i++) {\n        o = va_arg(vargs, PyObject **);\n        *o = args[i];\n    }\n    return 1;\n}\n\nint\nPyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...)\n{\n    PyObject **stack;\n    Py_ssize_t nargs;\n    int retval;\n    va_list vargs;\n\n    if (!PyTuple_Check(args)) {\n        PyErr_SetString(PyExc_SystemError,\n            \"PyArg_UnpackTuple() argument list is not a tuple\");\n        return 0;\n    }\n    stack = _PyTuple_ITEMS(args);\n    nargs = PyTuple_GET_SIZE(args);\n\n    va_start(vargs, max);\n    retval = unpack_stack(stack, nargs, name, min, max, vargs);\n    va_end(vargs);\n    return retval;\n}\n\nint\n_PyArg_UnpackStack(PyObject *const *args, Py_ssize_t nargs, const char *name,\n                   Py_ssize_t min, Py_ssize_t max, ...)\n{\n    int retval;\n    va_list vargs;\n\n    va_start(vargs, max);\n    retval = unpack_stack(args, nargs, name, min, max, vargs);\n    va_end(vargs);\n    return retval;\n}\n\n\n#undef _PyArg_NoKeywords\n#undef _PyArg_NoKwnames\n#undef _PyArg_NoPositional\n\n/* For type constructors that don't take keyword args\n *\n * Sets a TypeError and returns 0 if the args/kwargs is\n * not empty, returns 1 otherwise\n */\nint\n_PyArg_NoKeywords(const char *funcname, PyObject *kwargs)\n{\n    if (kwargs == NULL) {\n        return 1;\n    }\n    if (!PyDict_CheckExact(kwargs)) {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n    if (PyDict_GET_SIZE(kwargs) == 0) {\n        return 1;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"%.200s() takes no keyword arguments\",\n                    funcname);\n    return 0;\n}\n\nint\n_PyArg_NoPositional(const char *funcname, PyObject *args)\n{\n    if (args == NULL)\n        return 1;\n    if (!PyTuple_CheckExact(args)) {\n        PyErr_BadInternalCall();\n        return 0;\n    }\n    if (PyTuple_GET_SIZE(args) == 0)\n        return 1;\n\n    PyErr_Format(PyExc_TypeError, \"%.200s() takes no positional arguments\",\n                    funcname);\n    return 0;\n}\n\nint\n_PyArg_NoKwnames(const char *funcname, PyObject *kwnames)\n{\n    if (kwnames == NULL) {\n        return 1;\n    }\n\n    assert(PyTuple_CheckExact(kwnames));\n\n    if (PyTuple_GET_SIZE(kwnames) == 0) {\n        return 1;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"%s() takes no keyword arguments\", funcname);\n    return 0;\n}\n\nvoid\n_PyArg_Fini(void)\n{\n    struct _PyArg_Parser *tmp, *s = _PyRuntime.getargs.static_parsers;\n    while (s) {\n        tmp = s->next;\n        s->next = NULL;\n        parser_clear(s);\n        s = tmp;\n    }\n    _PyRuntime.getargs.static_parsers = NULL;\n}\n\n#ifdef __cplusplus\n};\n#endif\n"
  },
  {
    "path": "GetCompiler.c",
    "content": "\n/* Return the compiler identification, if possible. */\n\n#include \"Python.h\"\n\n#ifndef COMPILER\n\n// Note the __clang__ conditional has to come before the __GNUC__ one because\n// clang pretends to be GCC.\n#if defined(__clang__)\n#define COMPILER \"[Clang \" __clang_version__ \"]\"\n#elif defined(__GNUC__)\n#define COMPILER \"[GCC \" __VERSION__ \"]\"\n// Generic fallbacks.\n#elif defined(__cplusplus)\n#define COMPILER \"[C++]\"\n#else\n#define COMPILER \"[C]\"\n#endif\n\n#endif /* !COMPILER */\n\nconst char *\nPy_GetCompiler(void)\n{\n    return COMPILER;\n}\n"
  },
  {
    "path": "GetCopyRight.c",
    "content": "/* Return the copyright string.  This is updated manually. */\n#include \"Python.h\"\n\nstatic const char cprt[] =\n\"\\\nCopyright (c) 2001-2023 Python Software Foundation.\\n\\\nAll Rights Reserved.\\n\\\n\\n\\\nCopyright (c) 2000 BeOpen.com.\\n\\\nAll Rights Reserved.\\n\\\n\\n\\\nCopyright (c) 1995-2001 Corporation for National Research Initiatives.\\n\\\nAll Rights Reserved.\\n\\\n\\n\\\nCopyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.\\n\\\nAll Rights Reserved.\";\n\nconst char *\nPy_GetCopyright(void)\n{\n    return cprt;\n}\n"
  },
  {
    "path": "GetCopyright.c",
    "content": "/* Return the copyright string.  This is updated manually. */\n\n#include \"Python.h\"\n\nstatic const char cprt[] =\n\"\\\nCopyright (c) 2001-2023 Python Software Foundation.\\n\\\nAll Rights Reserved.\\n\\\n\\n\\\nCopyright (c) 2000 BeOpen.com.\\n\\\nAll Rights Reserved.\\n\\\n\\n\\\nCopyright (c) 1995-2001 Corporation for National Research Initiatives.\\n\\\nAll Rights Reserved.\\n\\\n\\n\\\nCopyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.\\n\\\nAll Rights Reserved.\";\n\nconst char *\nPy_GetCopyright(void)\n{\n    return cprt;\n}\n"
  },
  {
    "path": "GetOpt.c",
    "content": "/*---------------------------------------------------------------------------*\n * <RCS keywords>\n *\n * C++ Library\n *\n * Copyright 1992-1994, David Gottner\n *\n *                    All Rights Reserved\n *\n * Permission to use, copy, modify, and distribute this software and its\n * documentation for any purpose and without fee is hereby granted,\n * provided that the above copyright notice, this permission notice and\n * the following disclaimer notice appear unmodified in all copies.\n *\n * I DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL I\n * BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY\n * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER\n * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT\n * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *---------------------------------------------------------------------------*/\n\n/* Modified to support --help and --version, as well as /? on Windows\n * by Georg Brandl. */\n\n#include <Python.h>\n#include <stdio.h>\n#include <string.h>\n#include <wchar.h>\n#include \"pycore_getopt.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nint _PyOS_opterr = 1;                 /* generate error messages */\nPy_ssize_t _PyOS_optind = 1;          /* index into argv array   */\nconst wchar_t *_PyOS_optarg = NULL;   /* optional argument       */\n\nstatic const wchar_t *opt_ptr = L\"\";\n\n/* Python command line short and long options */\n\n#define SHORT_OPTS L\"bBc:dEhiIJm:OPqRsStuvVW:xX:?\"\n\nstatic const _PyOS_LongOption longopts[] = {\n    /* name, has_arg, val (used in switch in initconfig.c) */\n    {L\"check-hash-based-pycs\", 1, 0},\n    {L\"help-all\", 0, 1},\n    {L\"help-env\", 0, 2},\n    {L\"help-xoptions\", 0, 3},\n    {NULL, 0, -1},                     /* sentinel */\n};\n\n\nvoid _PyOS_ResetGetOpt(void)\n{\n    _PyOS_opterr = 1;\n    _PyOS_optind = 1;\n    _PyOS_optarg = NULL;\n    opt_ptr = L\"\";\n}\n\nint _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)\n{\n    wchar_t *ptr;\n    wchar_t option;\n\n    if (*opt_ptr == '\\0') {\n\n        if (_PyOS_optind >= argc)\n            return -1;\n#ifdef MS_WINDOWS\n        else if (wcscmp(argv[_PyOS_optind], L\"/?\") == 0) {\n            ++_PyOS_optind;\n            return 'h';\n        }\n#endif\n\n        else if (argv[_PyOS_optind][0] != L'-' ||\n                 argv[_PyOS_optind][1] == L'\\0' /* lone dash */ )\n            return -1;\n\n        else if (wcscmp(argv[_PyOS_optind], L\"--\") == 0) {\n            ++_PyOS_optind;\n            return -1;\n        }\n\n        else if (wcscmp(argv[_PyOS_optind], L\"--help\") == 0) {\n            ++_PyOS_optind;\n            return 'h';\n        }\n\n        else if (wcscmp(argv[_PyOS_optind], L\"--version\") == 0) {\n            ++_PyOS_optind;\n            return 'V';\n        }\n\n        opt_ptr = &argv[_PyOS_optind++][1];\n    }\n\n    if ((option = *opt_ptr++) == L'\\0')\n        return -1;\n\n    if (option == L'-') {\n        // Parse long option.\n        if (*opt_ptr == L'\\0') {\n            if (_PyOS_opterr) {\n                fprintf(stderr, \"expected long option\\n\");\n            }\n            return -1;\n        }\n        *longindex = 0;\n        const _PyOS_LongOption *opt;\n        for (opt = &longopts[*longindex]; opt->name; opt = &longopts[++(*longindex)]) {\n            if (!wcscmp(opt->name, opt_ptr))\n                break;\n        }\n        if (!opt->name) {\n            if (_PyOS_opterr) {\n                fprintf(stderr, \"unknown option %ls\\n\", argv[_PyOS_optind - 1]);\n            }\n            return '_';\n        }\n        opt_ptr = L\"\";\n        if (!opt->has_arg) {\n            return opt->val;\n        }\n        if (_PyOS_optind >= argc) {\n            if (_PyOS_opterr) {\n                fprintf(stderr, \"Argument expected for the %ls options\\n\",\n                        argv[_PyOS_optind - 1]);\n            }\n            return '_';\n        }\n        _PyOS_optarg = argv[_PyOS_optind++];\n        return opt->val;\n    }\n\n    if (option == 'J') {\n        if (_PyOS_opterr) {\n            fprintf(stderr, \"-J is reserved for Jython\\n\");\n        }\n        return '_';\n    }\n\n    if ((ptr = wcschr(SHORT_OPTS, option)) == NULL) {\n        if (_PyOS_opterr) {\n            fprintf(stderr, \"Unknown option: -%c\\n\", (char)option);\n        }\n        return '_';\n    }\n\n    if (*(ptr + 1) == L':') {\n        if (*opt_ptr != L'\\0') {\n            _PyOS_optarg  = opt_ptr;\n            opt_ptr = L\"\";\n        }\n\n        else {\n            if (_PyOS_optind >= argc) {\n                if (_PyOS_opterr) {\n                    fprintf(stderr,\n                        \"Argument expected for the -%c option\\n\", (char)option);\n                }\n                return '_';\n            }\n\n            _PyOS_optarg = argv[_PyOS_optind++];\n        }\n    }\n\n    return option;\n}\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "GetPlatForm.c",
    "content": "\n#include \"Python.h\"\n\n#ifndef PLATFORM\n#define PLATFORM \"unknown\"\n#endif\n\nconst char *\nPy_GetPlatform(void)\n{\n    return PLATFORM;\n}\n"
  },
  {
    "path": "GetVersion.c",
    "content": "/* Return the full version string. */\n\n#include \"Python.h\"\n\n#include \"patchlevel.h\"\n\nstatic int initialized = 0;\nstatic char version[250];\n\nvoid _Py_InitVersion(void)\n{\n    if (initialized) {\n        return;\n    }\n    initialized = 1;\n    PyOS_snprintf(version, sizeof(version), \"%.80s (%.80s) %.80s\",\n                  PY_VERSION, Py_GetBuildInfo(), Py_GetCompiler());\n}\n\nconst char *\nPy_GetVersion(void)\n{\n    _Py_InitVersion();\n    return version;\n}\n\n// Export the Python hex version as a constant.\nconst unsigned long Py_Version = PY_VERSION_HEX;\n"
  },
  {
    "path": "Get_Compiler.c",
    "content": "\n/* Return the compiler identification, if possible. */\n\n#include \"Python.h\"\n\n#ifndef COMPILER\n\n// Note the __clang__ conditional has to come before the __GNUC__ one because\n// clang pretends to be GCC.\n#if defined(__clang__)\n#define COMPILER \"[Clang \" __clang_version__ \"]\"\n#elif defined(__GNUC__)\n#define COMPILER \"[GCC \" __VERSION__ \"]\"\n// Generic fallbacks.\n#elif defined(__cplusplus)\n#define COMPILER \"[C++]\"\n#else\n#define COMPILER \"[C]\"\n#endif\n\n#endif /* !COMPILER */\n\nconst char *\nPy_GetCompiler(void)\n{\n    return COMPILER;\n}\n"
  },
  {
    "path": "Get_Opt.c",
    "content": "/*---------------------------------------------------------------------------*\n * <RCS keywords>\n *\n * C++ Library\n *\n * Copyright 1992-1994, David Gottner\n *\n *                    All Rights Reserved\n *\n * Permission to use, copy, modify, and distribute this software and its\n * documentation for any purpose and without fee is hereby granted,\n * provided that the above copyright notice, this permission notice and\n * the following disclaimer notice appear unmodified in all copies.\n *\n * I DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL I\n * BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY\n * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER\n * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT\n * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *---------------------------------------------------------------------------*/\n\n/* Modified to support --help and --version, as well as /? on Windows\n * by Georg Brandl. */\n\n#include <Python.h>\n#include <stdio.h>\n#include <string.h>\n#include <wchar.h>\n#include \"pycore_getopt.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nint _PyOS_opterr = 1;                 /* generate error messages */\nPy_ssize_t _PyOS_optind = 1;          /* index into argv array   */\nconst wchar_t *_PyOS_optarg = NULL;   /* optional argument       */\n\nstatic const wchar_t *opt_ptr = L\"\";\n\n/* Python command line short and long options */\n\n#define SHORT_OPTS L\"bBc:dEhiIJm:OPqRsStuvVW:xX:?\"\n\nstatic const _PyOS_LongOption longopts[] = {\n    /* name, has_arg, val (used in switch in initconfig.c) */\n    {L\"check-hash-based-pycs\", 1, 0},\n    {L\"help-all\", 0, 1},\n    {L\"help-env\", 0, 2},\n    {L\"help-xoptions\", 0, 3},\n    {NULL, 0, -1},                     /* sentinel */\n};\n\n\nvoid _PyOS_ResetGetOpt(void)\n{\n    _PyOS_opterr = 1;\n    _PyOS_optind = 1;\n    _PyOS_optarg = NULL;\n    opt_ptr = L\"\";\n}\n\nint _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)\n{\n    wchar_t *ptr;\n    wchar_t option;\n\n    if (*opt_ptr == '\\0') {\n\n        if (_PyOS_optind >= argc)\n            return -1;\n#ifdef MS_WINDOWS\n        else if (wcscmp(argv[_PyOS_optind], L\"/?\") == 0) {\n            ++_PyOS_optind;\n            return 'h';\n        }\n#endif\n\n        else if (argv[_PyOS_optind][0] != L'-' ||\n                 argv[_PyOS_optind][1] == L'\\0' /* lone dash */ )\n            return -1;\n\n        else if (wcscmp(argv[_PyOS_optind], L\"--\") == 0) {\n            ++_PyOS_optind;\n            return -1;\n        }\n\n        else if (wcscmp(argv[_PyOS_optind], L\"--help\") == 0) {\n            ++_PyOS_optind;\n            return 'h';\n        }\n\n        else if (wcscmp(argv[_PyOS_optind], L\"--version\") == 0) {\n            ++_PyOS_optind;\n            return 'V';\n        }\n\n        opt_ptr = &argv[_PyOS_optind++][1];\n    }\n\n    if ((option = *opt_ptr++) == L'\\0')\n        return -1;\n\n    if (option == L'-') {\n        // Parse long option.\n        if (*opt_ptr == L'\\0') {\n            if (_PyOS_opterr) {\n                fprintf(stderr, \"expected long option\\n\");\n            }\n            return -1;\n        }\n        *longindex = 0;\n        const _PyOS_LongOption *opt;\n        for (opt = &longopts[*longindex]; opt->name; opt = &longopts[++(*longindex)]) {\n            if (!wcscmp(opt->name, opt_ptr))\n                break;\n        }\n        if (!opt->name) {\n            if (_PyOS_opterr) {\n                fprintf(stderr, \"unknown option %ls\\n\", argv[_PyOS_optind - 1]);\n            }\n            return '_';\n        }\n        opt_ptr = L\"\";\n        if (!opt->has_arg) {\n            return opt->val;\n        }\n        if (_PyOS_optind >= argc) {\n            if (_PyOS_opterr) {\n                fprintf(stderr, \"Argument expected for the %ls options\\n\",\n                        argv[_PyOS_optind - 1]);\n            }\n            return '_';\n        }\n        _PyOS_optarg = argv[_PyOS_optind++];\n        return opt->val;\n    }\n\n    if (option == 'J') {\n        if (_PyOS_opterr) {\n            fprintf(stderr, \"-J is reserved for Jython\\n\");\n        }\n        return '_';\n    }\n\n    if ((ptr = wcschr(SHORT_OPTS, option)) == NULL) {\n        if (_PyOS_opterr) {\n            fprintf(stderr, \"Unknown option: -%c\\n\", (char)option);\n        }\n        return '_';\n    }\n\n    if (*(ptr + 1) == L':') {\n        if (*opt_ptr != L'\\0') {\n            _PyOS_optarg  = opt_ptr;\n            opt_ptr = L\"\";\n        }\n\n        else {\n            if (_PyOS_optind >= argc) {\n                if (_PyOS_opterr) {\n                    fprintf(stderr,\n                        \"Argument expected for the -%c option\\n\", (char)option);\n                }\n                return '_';\n            }\n\n            _PyOS_optarg = argv[_PyOS_optind++];\n        }\n    }\n\n    return option;\n}\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "Get_Plat_Form.c",
    "content": "\n#include \"Python.h\"\n\n#ifndef PLATFORM\n#define PLATFORM \"unknown\"\n#endif\n\nconst char *\nPy_GetPlatform(void)\n{\n    return PLATFORM;\n}\n"
  },
  {
    "path": "Getversion.c",
    "content": "\n/* Return the full version string. */\n\n#include \"Python.h\"\n\n#include \"patchlevel.h\"\n\nstatic int initialized = 0;\nstatic char version[250];\n\nvoid _Py_InitVersion(void)\n{\n    if (initialized) {\n        return;\n    }\n    initialized = 1;\n    PyOS_snprintf(version, sizeof(version), \"%.80s (%.80s) %.80s\",\n                  PY_VERSION, Py_GetBuildInfo(), Py_GetCompiler());\n}\n\nconst char *\nPy_GetVersion(void)\n{\n    _Py_InitVersion();\n    return version;\n}\n\n// Export the Python hex version as a constant.\nconst unsigned long Py_Version = PY_VERSION_HEX;\n"
  },
  {
    "path": "Hamt.c",
    "content": "#include \"Python.h\"\n\n#include \"pycore_bitutils.h\"      // _Py_popcount32\n#include \"pycore_hamt.h\"\n#include \"pycore_initconfig.h\"    // _PyStatus_OK()\n#include \"pycore_object.h\"        // _PyObject_GC_TRACK()\n#include <stddef.h>               // offsetof()\n\n/*\nThis file provides an implementation of an immutable mapping using the\nHash Array Mapped Trie (or HAMT) datastructure.\n\nThis design allows to have:\n\n1. Efficient copy: immutable mappings can be copied by reference,\n   making it an O(1) operation.\n\n2. Efficient mutations: due to structural sharing, only a portion of\n   the trie needs to be copied when the collection is mutated.  The\n   cost of set/delete operations is O(log N).\n\n3. Efficient lookups: O(log N).\n\n(where N is number of key/value items in the immutable mapping.)\n\n\nHAMT\n====\n\nThe core idea of HAMT is that the shape of the trie is encoded into the\nhashes of keys.\n\nSay we want to store a K/V pair in our mapping.  First, we calculate the\nhash of K, let's say it's 19830128, or in binary:\n\n    0b1001011101001010101110000 = 19830128\n\nNow let's partition this bit representation of the hash into blocks of\n5 bits each:\n\n    0b00_00000_10010_11101_00101_01011_10000 = 19830128\n          (6)   (5)   (4)   (3)   (2)   (1)\n\nEach block of 5 bits represents a number between 0 and 31.  So if we have\na tree that consists of nodes, each of which is an array of 32 pointers,\nthose 5-bit blocks will encode a position on a single tree level.\n\nFor example, storing the key K with hash 19830128, results in the following\ntree structure:\n\n                     (array of 32 pointers)\n                     +---+ -- +----+----+----+ -- +----+\n  root node          | 0 | .. | 15 | 16 | 17 | .. | 31 |   0b10000 = 16 (1)\n  (level 1)          +---+ -- +----+----+----+ -- +----+\n                                      |\n                     +---+ -- +----+----+----+ -- +----+\n  a 2nd level node   | 0 | .. | 10 | 11 | 12 | .. | 31 |   0b01011 = 11 (2)\n                     +---+ -- +----+----+----+ -- +----+\n                                      |\n                     +---+ -- +----+----+----+ -- +----+\n  a 3rd level node   | 0 | .. | 04 | 05 | 06 | .. | 31 |   0b00101 = 5  (3)\n                     +---+ -- +----+----+----+ -- +----+\n                                      |\n                     +---+ -- +----+----+----+----+\n  a 4th level node   | 0 | .. | 04 | 29 | 30 | 31 |        0b11101 = 29 (4)\n                     +---+ -- +----+----+----+----+\n                                      |\n                     +---+ -- +----+----+----+ -- +----+\n  a 5th level node   | 0 | .. | 17 | 18 | 19 | .. | 31 |   0b10010 = 18 (5)\n                     +---+ -- +----+----+----+ -- +----+\n                                      |\n                       +--------------+\n                       |\n                     +---+ -- +----+----+----+ -- +----+\n  a 6th level node   | 0 | .. | 15 | 16 | 17 | .. | 31 |   0b00000 = 0  (6)\n                     +---+ -- +----+----+----+ -- +----+\n                       |\n                       V -- our value (or collision)\n\nTo rehash: for a K/V pair, the hash of K encodes where in the tree V will\nbe stored.\n\nTo optimize memory footprint and handle hash collisions, our implementation\nuses three different types of nodes:\n\n * A Bitmap node;\n * An Array node;\n * A Collision node.\n\nBecause we implement an immutable dictionary, our nodes are also\nimmutable.  Therefore, when we need to modify a node, we copy it, and\ndo that modification to the copy.\n\n\nArray Nodes\n-----------\n\nThese nodes are very simple.  Essentially they are arrays of 32 pointers\nwe used to illustrate the high-level idea in the previous section.\n\nWe use Array nodes only when we need to store more than 16 pointers\nin a single node.\n\nArray nodes do not store key objects or value objects.  They are used\nonly as an indirection level - their pointers point to other nodes in\nthe tree.\n\n\nBitmap Node\n-----------\n\nAllocating a new 32-pointers array for every node of our tree would be\nvery expensive.  Unless we store millions of keys, most of tree nodes would\nbe very sparse.\n\nWhen we have less than 16 elements in a node, we don't want to use the\nArray node, that would mean that we waste a lot of memory.  Instead,\nwe can use bitmap compression and can have just as many pointers\nas we need!\n\nBitmap nodes consist of two fields:\n\n1. An array of pointers.  If a Bitmap node holds N elements, the\n   array will be of N pointers.\n\n2. A 32bit integer -- a bitmap field.  If an N-th bit is set in the\n   bitmap, it means that the node has an N-th element.\n\nFor example, say we need to store a 3 elements sparse array:\n\n   +---+  --  +---+  --  +----+  --  +----+\n   | 0 |  ..  | 4 |  ..  | 11 |  ..  | 17 |\n   +---+  --  +---+  --  +----+  --  +----+\n                |          |           |\n                o1         o2          o3\n\nWe allocate a three-pointer Bitmap node.  Its bitmap field will be\nthen set to:\n\n   0b_00100_00010_00000_10000 == (1 << 17) | (1 << 11) | (1 << 4)\n\nTo check if our Bitmap node has an I-th element we can do:\n\n   bitmap & (1 << I)\n\n\nAnd here's a formula to calculate a position in our pointer array\nwhich would correspond to an I-th element:\n\n   popcount(bitmap & ((1 << I) - 1))\n\n\nLet's break it down:\n\n * `popcount` is a function that returns a number of bits set to 1;\n\n * `((1 << I) - 1)` is a mask to filter the bitmask to contain bits\n   set to the *right* of our bit.\n\n\nSo for our 17, 11, and 4 indexes:\n\n * bitmap & ((1 << 17) - 1) == 0b100000010000 => 2 bits are set => index is 2.\n\n * bitmap & ((1 << 11) - 1) == 0b10000 => 1 bit is set => index is 1.\n\n * bitmap & ((1 << 4) - 1) == 0b0 => 0 bits are set => index is 0.\n\n\nTo conclude: Bitmap nodes are just like Array nodes -- they can store\na number of pointers, but use bitmap compression to eliminate unused\npointers.\n\n\nBitmap nodes have two pointers for each item:\n\n  +----+----+----+----+  --  +----+----+\n  | k1 | v1 | k2 | v2 |  ..  | kN | vN |\n  +----+----+----+----+  --  +----+----+\n\nWhen kI == NULL, vI points to another tree level.\n\nWhen kI != NULL, the actual key object is stored in kI, and its\nvalue is stored in vI.\n\n\nCollision Nodes\n---------------\n\nCollision nodes are simple arrays of pointers -- two pointers per\nkey/value.  When there's a hash collision, say for k1/v1 and k2/v2\nwe have `hash(k1)==hash(k2)`.  Then our collision node will be:\n\n  +----+----+----+----+\n  | k1 | v1 | k2 | v2 |\n  +----+----+----+----+\n\n\nTree Structure\n--------------\n\nAll nodes are PyObjects.\n\nThe `PyHamtObject` object has a pointer to the root node (h_root),\nand has a length field (h_count).\n\nHigh-level functions accept a PyHamtObject object and dispatch to\nlower-level functions depending on what kind of node h_root points to.\n\n\nOperations\n==========\n\nThere are three fundamental operations on an immutable dictionary:\n\n1. \"o.assoc(k, v)\" will return a new immutable dictionary, that will be\n   a copy of \"o\", but with the \"k/v\" item set.\n\n   Functions in this file:\n\n        hamt_node_assoc, hamt_node_bitmap_assoc,\n        hamt_node_array_assoc, hamt_node_collision_assoc\n\n   `hamt_node_assoc` function accepts a node object, and calls\n   other functions depending on its actual type.\n\n2. \"o.find(k)\" will lookup key \"k\" in \"o\".\n\n   Functions:\n\n        hamt_node_find, hamt_node_bitmap_find,\n        hamt_node_array_find, hamt_node_collision_find\n\n3. \"o.without(k)\" will return a new immutable dictionary, that will be\n   a copy of \"o\", buth without the \"k\" key.\n\n   Functions:\n\n        hamt_node_without, hamt_node_bitmap_without,\n        hamt_node_array_without, hamt_node_collision_without\n\n\nFurther Reading\n===============\n\n1. http://blog.higher-order.net/2009/09/08/understanding-clojures-persistenthashmap-deftwice.html\n\n2. http://blog.higher-order.net/2010/08/16/assoc-and-clojures-persistenthashmap-part-ii.html\n\n3. Clojure's PersistentHashMap implementation:\n   https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentHashMap.java\n\n\nDebug\n=====\n\nThe HAMT datatype is accessible for testing purposes under the\n`_testcapi` module:\n\n    >>> from _testcapi import hamt\n    >>> h = hamt()\n    >>> h2 = h.set('a', 2)\n    >>> h3 = h2.set('b', 3)\n    >>> list(h3)\n    ['a', 'b']\n\nWhen CPython is built in debug mode, a '__dump__()' method is available\nto introspect the tree:\n\n    >>> print(h3.__dump__())\n    HAMT(len=2):\n        BitmapNode(size=4 count=2 bitmap=0b110 id=0x10eb9d9e8):\n            'a': 2\n            'b': 3\n*/\n\n\n#define IS_ARRAY_NODE(node)     Py_IS_TYPE(node, &_PyHamt_ArrayNode_Type)\n#define IS_BITMAP_NODE(node)    Py_IS_TYPE(node, &_PyHamt_BitmapNode_Type)\n#define IS_COLLISION_NODE(node) Py_IS_TYPE(node, &_PyHamt_CollisionNode_Type)\n\n\n/* Return type for 'find' (lookup a key) functions.\n\n   * F_ERROR - an error occurred;\n   * F_NOT_FOUND - the key was not found;\n   * F_FOUND - the key was found.\n*/\ntypedef enum {F_ERROR, F_NOT_FOUND, F_FOUND} hamt_find_t;\n\n\n/* Return type for 'without' (delete a key) functions.\n\n   * W_ERROR - an error occurred;\n   * W_NOT_FOUND - the key was not found: there's nothing to delete;\n   * W_EMPTY - the key was found: the node/tree would be empty\n     if the key is deleted;\n   * W_NEWNODE - the key was found: a new node/tree is returned\n     without that key.\n*/\ntypedef enum {W_ERROR, W_NOT_FOUND, W_EMPTY, W_NEWNODE} hamt_without_t;\n\n\n/* Low-level iterator protocol type.\n\n   * I_ITEM - a new item has been yielded;\n   * I_END - the whole tree was visited (similar to StopIteration).\n*/\ntypedef enum {I_ITEM, I_END} hamt_iter_t;\n\n\n#define HAMT_ARRAY_NODE_SIZE 32\n\n\ntypedef struct {\n    PyObject_HEAD\n    PyHamtNode *a_array[HAMT_ARRAY_NODE_SIZE];\n    Py_ssize_t a_count;\n} PyHamtNode_Array;\n\n\ntypedef struct {\n    PyObject_VAR_HEAD\n    int32_t c_hash;\n    PyObject *c_array[1];\n} PyHamtNode_Collision;\n\n\nstatic PyHamtObject *\nhamt_alloc(void);\n\nstatic PyHamtNode *\nhamt_node_assoc(PyHamtNode *node,\n                uint32_t shift, int32_t hash,\n                PyObject *key, PyObject *val, int* added_leaf);\n\nstatic hamt_without_t\nhamt_node_without(PyHamtNode *node,\n                  uint32_t shift, int32_t hash,\n                  PyObject *key,\n                  PyHamtNode **new_node);\n\nstatic hamt_find_t\nhamt_node_find(PyHamtNode *node,\n               uint32_t shift, int32_t hash,\n               PyObject *key, PyObject **val);\n\n#ifdef Py_DEBUG\nstatic int\nhamt_node_dump(PyHamtNode *node,\n               _PyUnicodeWriter *writer, int level);\n#endif\n\nstatic PyHamtNode *\nhamt_node_array_new(Py_ssize_t);\n\nstatic PyHamtNode *\nhamt_node_collision_new(int32_t hash, Py_ssize_t size);\n\nstatic inline Py_ssize_t\nhamt_node_collision_count(PyHamtNode_Collision *node);\n\n\n#ifdef Py_DEBUG\nstatic void\n_hamt_node_array_validate(void *obj_raw)\n{\n    PyObject *obj = _PyObject_CAST(obj_raw);\n    assert(IS_ARRAY_NODE(obj));\n    PyHamtNode_Array *node = (PyHamtNode_Array*)obj;\n    Py_ssize_t i = 0, count = 0;\n    for (; i < HAMT_ARRAY_NODE_SIZE; i++) {\n        if (node->a_array[i] != NULL) {\n            count++;\n        }\n    }\n    assert(count == node->a_count);\n}\n\n#define VALIDATE_ARRAY_NODE(NODE) \\\n    do { _hamt_node_array_validate(NODE); } while (0);\n#else\n#define VALIDATE_ARRAY_NODE(NODE)\n#endif\n\n\n/* Returns -1 on error */\nstatic inline int32_t\nhamt_hash(PyObject *o)\n{\n    Py_hash_t hash = PyObject_Hash(o);\n\n#if SIZEOF_PY_HASH_T <= 4\n    return hash;\n#else\n    if (hash == -1) {\n        /* exception */\n        return -1;\n    }\n\n    /* While it's somewhat suboptimal to reduce Python's 64 bit hash to\n       32 bits via XOR, it seems that the resulting hash function\n       is good enough (this is also how Long type is hashed in Java.)\n       Storing 10, 100, 1000 Python strings results in a relatively\n       shallow and uniform tree structure.\n\n       Also it's worth noting that it would be possible to adapt the tree\n       structure to 64 bit hashes, but that would increase memory pressure\n       and provide little to no performance benefits for collections with\n       fewer than billions of key/value pairs.\n\n       Important: do not change this hash reducing function. There are many\n       tests that need an exact tree shape to cover all code paths and\n       we do that by specifying concrete values for test data's `__hash__`.\n       If this function is changed most of the regression tests would\n       become useless.\n    */\n    int32_t xored = (int32_t)(hash & 0xffffffffl) ^ (int32_t)(hash >> 32);\n    return xored == -1 ? -2 : xored;\n#endif\n}\n\nstatic inline uint32_t\nhamt_mask(int32_t hash, uint32_t shift)\n{\n    return (((uint32_t)hash >> shift) & 0x01f);\n}\n\nstatic inline uint32_t\nhamt_bitpos(int32_t hash, uint32_t shift)\n{\n    return (uint32_t)1 << hamt_mask(hash, shift);\n}\n\nstatic inline uint32_t\nhamt_bitindex(uint32_t bitmap, uint32_t bit)\n{\n    return (uint32_t)_Py_popcount32(bitmap & (bit - 1));\n}\n\n\n/////////////////////////////////// Dump Helpers\n#ifdef Py_DEBUG\n\nstatic int\n_hamt_dump_ident(_PyUnicodeWriter *writer, int level)\n{\n    /* Write `'    ' * level` to the `writer` */\n    PyObject *str = NULL;\n    PyObject *num = NULL;\n    PyObject *res = NULL;\n    int ret = -1;\n\n    str = PyUnicode_FromString(\"    \");\n    if (str == NULL) {\n        goto error;\n    }\n\n    num = PyLong_FromLong((long)level);\n    if (num == NULL) {\n        goto error;\n    }\n\n    res = PyNumber_Multiply(str, num);\n    if (res == NULL) {\n        goto error;\n    }\n\n    ret = _PyUnicodeWriter_WriteStr(writer, res);\n\nerror:\n    Py_XDECREF(res);\n    Py_XDECREF(str);\n    Py_XDECREF(num);\n    return ret;\n}\n\nstatic int\n_hamt_dump_format(_PyUnicodeWriter *writer, const char *format, ...)\n{\n    /* A convenient helper combining _PyUnicodeWriter_WriteStr and\n       PyUnicode_FromFormatV.\n    */\n    PyObject* msg;\n    int ret;\n\n    va_list vargs;\n    va_start(vargs, format);\n    msg = PyUnicode_FromFormatV(format, vargs);\n    va_end(vargs);\n\n    if (msg == NULL) {\n        return -1;\n    }\n\n    ret = _PyUnicodeWriter_WriteStr(writer, msg);\n    Py_DECREF(msg);\n    return ret;\n}\n\n#endif  /* Py_DEBUG */\n/////////////////////////////////// Bitmap Node\n\n\nstatic PyHamtNode *\nhamt_node_bitmap_new(Py_ssize_t size)\n{\n    /* Create a new bitmap node of size 'size' */\n\n    PyHamtNode_Bitmap *node;\n    Py_ssize_t i;\n\n    if (size == 0) {\n        /* Since bitmap nodes are immutable, we can cache the instance\n           for size=0 and reuse it whenever we need an empty bitmap node.\n        */\n        return (PyHamtNode *)Py_NewRef(&_Py_SINGLETON(hamt_bitmap_node_empty));\n    }\n\n    assert(size >= 0);\n    assert(size % 2 == 0);\n\n    /* No freelist; allocate a new bitmap node */\n    node = PyObject_GC_NewVar(\n        PyHamtNode_Bitmap, &_PyHamt_BitmapNode_Type, size);\n    if (node == NULL) {\n        return NULL;\n    }\n\n    Py_SET_SIZE(node, size);\n\n    for (i = 0; i < size; i++) {\n        node->b_array[i] = NULL;\n    }\n\n    node->b_bitmap = 0;\n\n    _PyObject_GC_TRACK(node);\n\n    return (PyHamtNode *)node;\n}\n\nstatic inline Py_ssize_t\nhamt_node_bitmap_count(PyHamtNode_Bitmap *node)\n{\n    return Py_SIZE(node) / 2;\n}\n\nstatic PyHamtNode_Bitmap *\nhamt_node_bitmap_clone(PyHamtNode_Bitmap *node)\n{\n    /* Clone a bitmap node; return a new one with the same child notes. */\n\n    PyHamtNode_Bitmap *clone;\n    Py_ssize_t i;\n\n    clone = (PyHamtNode_Bitmap *)hamt_node_bitmap_new(Py_SIZE(node));\n    if (clone == NULL) {\n        return NULL;\n    }\n\n    for (i = 0; i < Py_SIZE(node); i++) {\n        clone->b_array[i] = Py_XNewRef(node->b_array[i]);\n    }\n\n    clone->b_bitmap = node->b_bitmap;\n    return clone;\n}\n\nstatic PyHamtNode_Bitmap *\nhamt_node_bitmap_clone_without(PyHamtNode_Bitmap *o, uint32_t bit)\n{\n    assert(bit & o->b_bitmap);\n    assert(hamt_node_bitmap_count(o) > 1);\n\n    PyHamtNode_Bitmap *new = (PyHamtNode_Bitmap *)hamt_node_bitmap_new(\n        Py_SIZE(o) - 2);\n    if (new == NULL) {\n        return NULL;\n    }\n\n    uint32_t idx = hamt_bitindex(o->b_bitmap, bit);\n    uint32_t key_idx = 2 * idx;\n    uint32_t val_idx = key_idx + 1;\n    uint32_t i;\n\n    for (i = 0; i < key_idx; i++) {\n        new->b_array[i] = Py_XNewRef(o->b_array[i]);\n    }\n\n    assert(Py_SIZE(o) >= 0 && Py_SIZE(o) <= 32);\n    for (i = val_idx + 1; i < (uint32_t)Py_SIZE(o); i++) {\n        new->b_array[i - 2] = Py_XNewRef(o->b_array[i]);\n    }\n\n    new->b_bitmap = o->b_bitmap & ~bit;\n    return new;\n}\n\nstatic PyHamtNode *\nhamt_node_new_bitmap_or_collision(uint32_t shift,\n                                  PyObject *key1, PyObject *val1,\n                                  int32_t key2_hash,\n                                  PyObject *key2, PyObject *val2)\n{\n    /* Helper method.  Creates a new node for key1/val and key2/val2\n       pairs.\n\n       If key1 hash is equal to the hash of key2, a Collision node\n       will be created.  If they are not equal, a Bitmap node is\n       created.\n    */\n\n    int32_t key1_hash = hamt_hash(key1);\n    if (key1_hash == -1) {\n        return NULL;\n    }\n\n    if (key1_hash == key2_hash) {\n        PyHamtNode_Collision *n;\n        n = (PyHamtNode_Collision *)hamt_node_collision_new(key1_hash, 4);\n        if (n == NULL) {\n            return NULL;\n        }\n\n        n->c_array[0] = Py_NewRef(key1);\n        n->c_array[1] = Py_NewRef(val1);\n\n        n->c_array[2] = Py_NewRef(key2);\n        n->c_array[3] = Py_NewRef(val2);\n\n        return (PyHamtNode *)n;\n    }\n    else {\n        int added_leaf = 0;\n        PyHamtNode *n = hamt_node_bitmap_new(0);\n        if (n == NULL) {\n            return NULL;\n        }\n\n        PyHamtNode *n2 = hamt_node_assoc(\n            n, shift, key1_hash, key1, val1, &added_leaf);\n        Py_DECREF(n);\n        if (n2 == NULL) {\n            return NULL;\n        }\n\n        n = hamt_node_assoc(n2, shift, key2_hash, key2, val2, &added_leaf);\n        Py_DECREF(n2);\n        if (n == NULL) {\n            return NULL;\n        }\n\n        return n;\n    }\n}\n\nstatic PyHamtNode *\nhamt_node_bitmap_assoc(PyHamtNode_Bitmap *self,\n                       uint32_t shift, int32_t hash,\n                       PyObject *key, PyObject *val, int* added_leaf)\n{\n    /* assoc operation for bitmap nodes.\n\n       Return: a new node, or self if key/val already is in the\n       collection.\n\n       'added_leaf' is later used in '_PyHamt_Assoc' to determine if\n       `hamt.set(key, val)` increased the size of the collection.\n    */\n\n    uint32_t bit = hamt_bitpos(hash, shift);\n    uint32_t idx = hamt_bitindex(self->b_bitmap, bit);\n\n    /* Bitmap node layout:\n\n    +------+------+------+------+  ---  +------+------+\n    | key1 | val1 | key2 | val2 |  ...  | keyN | valN |\n    +------+------+------+------+  ---  +------+------+\n    where `N < Py_SIZE(node)`.\n\n    The `node->b_bitmap` field is a bitmap.  For a given\n    `(shift, hash)` pair we can determine:\n\n     - If this node has the corresponding key/val slots.\n     - The index of key/val slots.\n    */\n\n    if (self->b_bitmap & bit) {\n        /* The key is set in this node */\n\n        uint32_t key_idx = 2 * idx;\n        uint32_t val_idx = key_idx + 1;\n\n        assert(val_idx < (size_t)Py_SIZE(self));\n\n        PyObject *key_or_null = self->b_array[key_idx];\n        PyObject *val_or_node = self->b_array[val_idx];\n\n        if (key_or_null == NULL) {\n            /* key is NULL.  This means that we have a few keys\n               that have the same (hash, shift) pair. */\n\n            assert(val_or_node != NULL);\n\n            PyHamtNode *sub_node = hamt_node_assoc(\n                (PyHamtNode *)val_or_node,\n                shift + 5, hash, key, val, added_leaf);\n            if (sub_node == NULL) {\n                return NULL;\n            }\n\n            if (val_or_node == (PyObject *)sub_node) {\n                Py_DECREF(sub_node);\n                return (PyHamtNode *)Py_NewRef(self);\n            }\n\n            PyHamtNode_Bitmap *ret = hamt_node_bitmap_clone(self);\n            if (ret == NULL) {\n                return NULL;\n            }\n            Py_SETREF(ret->b_array[val_idx], (PyObject*)sub_node);\n            return (PyHamtNode *)ret;\n        }\n\n        assert(key != NULL);\n        /* key is not NULL.  This means that we have only one other\n           key in this collection that matches our hash for this shift. */\n\n        int comp_err = PyObject_RichCompareBool(key, key_or_null, Py_EQ);\n        if (comp_err < 0) {  /* exception in __eq__ */\n            return NULL;\n        }\n        if (comp_err == 1) {  /* key == key_or_null */\n            if (val == val_or_node) {\n                /* we already have the same key/val pair; return self. */\n                return (PyHamtNode *)Py_NewRef(self);\n            }\n\n            /* We're setting a new value for the key we had before.\n               Make a new bitmap node with a replaced value, and return it. */\n            PyHamtNode_Bitmap *ret = hamt_node_bitmap_clone(self);\n            if (ret == NULL) {\n                return NULL;\n            }\n            Py_SETREF(ret->b_array[val_idx], Py_NewRef(val));\n            return (PyHamtNode *)ret;\n        }\n\n        /* It's a new key, and it has the same index as *one* another key.\n           We have a collision.  We need to create a new node which will\n           combine the existing key and the key we're adding.\n\n           `hamt_node_new_bitmap_or_collision` will either create a new\n           Collision node if the keys have identical hashes, or\n           a new Bitmap node.\n        */\n        PyHamtNode *sub_node = hamt_node_new_bitmap_or_collision(\n            shift + 5,\n            key_or_null, val_or_node,  /* existing key/val */\n            hash,\n            key, val  /* new key/val */\n        );\n        if (sub_node == NULL) {\n            return NULL;\n        }\n\n        PyHamtNode_Bitmap *ret = hamt_node_bitmap_clone(self);\n        if (ret == NULL) {\n            Py_DECREF(sub_node);\n            return NULL;\n        }\n        Py_SETREF(ret->b_array[key_idx], NULL);\n        Py_SETREF(ret->b_array[val_idx], (PyObject *)sub_node);\n\n        *added_leaf = 1;\n        return (PyHamtNode *)ret;\n    }\n    else {\n        /* There was no key before with the same (shift,hash). */\n\n        uint32_t n = (uint32_t)_Py_popcount32(self->b_bitmap);\n\n        if (n >= 16) {\n            /* When we have a situation where we want to store more\n               than 16 nodes at one level of the tree, we no longer\n               want to use the Bitmap node with bitmap encoding.\n\n               Instead we start using an Array node, which has\n               simpler (faster) implementation at the expense of\n               having preallocated 32 pointers for its keys/values\n               pairs.\n\n               Small hamt objects (<30 keys) usually don't have any\n               Array nodes at all.  Between ~30 and ~400 keys hamt\n               objects usually have one Array node, and usually it's\n               a root node.\n            */\n\n            uint32_t jdx = hamt_mask(hash, shift);\n            /* 'jdx' is the index of where the new key should be added\n               in the new Array node we're about to create. */\n\n            PyHamtNode *empty = NULL;\n            PyHamtNode_Array *new_node = NULL;\n            PyHamtNode *res = NULL;\n\n            /* Create a new Array node. */\n            new_node = (PyHamtNode_Array *)hamt_node_array_new(n + 1);\n            if (new_node == NULL) {\n                goto fin;\n            }\n\n            /* Create an empty bitmap node for the next\n               hamt_node_assoc call. */\n            empty = hamt_node_bitmap_new(0);\n            if (empty == NULL) {\n                goto fin;\n            }\n\n            /* Make a new bitmap node for the key/val we're adding.\n               Set that bitmap node to new-array-node[jdx]. */\n            new_node->a_array[jdx] = hamt_node_assoc(\n                empty, shift + 5, hash, key, val, added_leaf);\n            if (new_node->a_array[jdx] == NULL) {\n                goto fin;\n            }\n\n            /* Copy existing key/value pairs from the current Bitmap\n               node to the new Array node we've just created. */\n            Py_ssize_t i, j;\n            for (i = 0, j = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {\n                if (((self->b_bitmap >> i) & 1) != 0) {\n                    /* Ensure we don't accidentally override `jdx` element\n                       we set few lines above.\n                    */\n                    assert(new_node->a_array[i] == NULL);\n\n                    if (self->b_array[j] == NULL) {\n                        new_node->a_array[i] =\n                            (PyHamtNode *)Py_NewRef(self->b_array[j + 1]);\n                    }\n                    else {\n                        int32_t rehash = hamt_hash(self->b_array[j]);\n                        if (rehash == -1) {\n                            goto fin;\n                        }\n\n                        new_node->a_array[i] = hamt_node_assoc(\n                            empty, shift + 5,\n                            rehash,\n                            self->b_array[j],\n                            self->b_array[j + 1],\n                            added_leaf);\n\n                        if (new_node->a_array[i] == NULL) {\n                            goto fin;\n                        }\n                    }\n                    j += 2;\n                }\n            }\n\n            VALIDATE_ARRAY_NODE(new_node)\n\n            /* That's it! */\n            res = (PyHamtNode *)new_node;\n\n        fin:\n            Py_XDECREF(empty);\n            if (res == NULL) {\n                Py_XDECREF(new_node);\n            }\n            return res;\n        }\n        else {\n            /* We have less than 16 keys at this level; let's just\n               create a new bitmap node out of this node with the\n               new key/val pair added. */\n\n            uint32_t key_idx = 2 * idx;\n            uint32_t val_idx = key_idx + 1;\n            uint32_t i;\n\n            *added_leaf = 1;\n\n            /* Allocate new Bitmap node which can have one more key/val\n               pair in addition to what we have already. */\n            PyHamtNode_Bitmap *new_node =\n                (PyHamtNode_Bitmap *)hamt_node_bitmap_new(2 * (n + 1));\n            if (new_node == NULL) {\n                return NULL;\n            }\n\n            /* Copy all keys/values that will be before the new key/value\n               we are adding. */\n            for (i = 0; i < key_idx; i++) {\n                new_node->b_array[i] = Py_XNewRef(self->b_array[i]);\n            }\n\n            /* Set the new key/value to the new Bitmap node. */\n            new_node->b_array[key_idx] = Py_NewRef(key);\n            new_node->b_array[val_idx] = Py_NewRef(val);\n\n            /* Copy all keys/values that will be after the new key/value\n               we are adding. */\n            assert(Py_SIZE(self) >= 0 && Py_SIZE(self) <= 32);\n            for (i = key_idx; i < (uint32_t)Py_SIZE(self); i++) {\n                new_node->b_array[i + 2] = Py_XNewRef(self->b_array[i]);\n            }\n\n            new_node->b_bitmap = self->b_bitmap | bit;\n            return (PyHamtNode *)new_node;\n        }\n    }\n}\n\nstatic hamt_without_t\nhamt_node_bitmap_without(PyHamtNode_Bitmap *self,\n                         uint32_t shift, int32_t hash,\n                         PyObject *key,\n                         PyHamtNode **new_node)\n{\n    uint32_t bit = hamt_bitpos(hash, shift);\n    if ((self->b_bitmap & bit) == 0) {\n        return W_NOT_FOUND;\n    }\n\n    uint32_t idx = hamt_bitindex(self->b_bitmap, bit);\n\n    uint32_t key_idx = 2 * idx;\n    uint32_t val_idx = key_idx + 1;\n\n    PyObject *key_or_null = self->b_array[key_idx];\n    PyObject *val_or_node = self->b_array[val_idx];\n\n    if (key_or_null == NULL) {\n        /* key == NULL means that 'value' is another tree node. */\n\n        PyHamtNode *sub_node = NULL;\n\n        hamt_without_t res = hamt_node_without(\n            (PyHamtNode *)val_or_node,\n            shift + 5, hash, key, &sub_node);\n\n        switch (res) {\n            case W_EMPTY:\n                /* It's impossible for us to receive a W_EMPTY here:\n\n                    - Array nodes are converted to Bitmap nodes when\n                      we delete 16th item from them;\n\n                    - Collision nodes are converted to Bitmap when\n                      there is one item in them;\n\n                    - Bitmap node's without() inlines single-item\n                      sub-nodes.\n\n                   So in no situation we can have a single-item\n                   Bitmap child of another Bitmap node.\n                */\n                Py_UNREACHABLE();\n\n            case W_NEWNODE: {\n                assert(sub_node != NULL);\n\n                if (IS_BITMAP_NODE(sub_node)) {\n                    PyHamtNode_Bitmap *sub_tree = (PyHamtNode_Bitmap *)sub_node;\n                    if (hamt_node_bitmap_count(sub_tree) == 1 &&\n                            sub_tree->b_array[0] != NULL)\n                    {\n                        /* A bitmap node with one key/value pair.  Just\n                           merge it into this node.\n\n                           Note that we don't inline Bitmap nodes that\n                           have a NULL key -- those nodes point to another\n                           tree level, and we cannot simply move tree levels\n                           up or down.\n                        */\n\n                        PyHamtNode_Bitmap *clone = hamt_node_bitmap_clone(self);\n                        if (clone == NULL) {\n                            Py_DECREF(sub_node);\n                            return W_ERROR;\n                        }\n\n                        PyObject *key = sub_tree->b_array[0];\n                        PyObject *val = sub_tree->b_array[1];\n\n                        Py_XSETREF(clone->b_array[key_idx], Py_NewRef(key));\n                        Py_SETREF(clone->b_array[val_idx], Py_NewRef(val));\n\n                        Py_DECREF(sub_tree);\n\n                        *new_node = (PyHamtNode *)clone;\n                        return W_NEWNODE;\n                    }\n                }\n\n#ifdef Py_DEBUG\n                /* Ensure that Collision.without implementation\n                   converts to Bitmap nodes itself.\n                */\n                if (IS_COLLISION_NODE(sub_node)) {\n                    assert(hamt_node_collision_count(\n                            (PyHamtNode_Collision*)sub_node) > 1);\n                }\n#endif\n\n                PyHamtNode_Bitmap *clone = hamt_node_bitmap_clone(self);\n                if (clone == NULL) {\n                    return W_ERROR;\n                }\n\n                Py_SETREF(clone->b_array[val_idx],\n                          (PyObject *)sub_node);  /* borrow */\n\n                *new_node = (PyHamtNode *)clone;\n                return W_NEWNODE;\n            }\n\n            case W_ERROR:\n            case W_NOT_FOUND:\n                assert(sub_node == NULL);\n                return res;\n\n            default:\n                Py_UNREACHABLE();\n        }\n    }\n    else {\n        /* We have a regular key/value pair */\n\n        int cmp = PyObject_RichCompareBool(key_or_null, key, Py_EQ);\n        if (cmp < 0) {\n            return W_ERROR;\n        }\n        if (cmp == 0) {\n            return W_NOT_FOUND;\n        }\n\n        if (hamt_node_bitmap_count(self) == 1) {\n            return W_EMPTY;\n        }\n\n        *new_node = (PyHamtNode *)\n            hamt_node_bitmap_clone_without(self, bit);\n        if (*new_node == NULL) {\n            return W_ERROR;\n        }\n\n        return W_NEWNODE;\n    }\n}\n\nstatic hamt_find_t\nhamt_node_bitmap_find(PyHamtNode_Bitmap *self,\n                      uint32_t shift, int32_t hash,\n                      PyObject *key, PyObject **val)\n{\n    /* Lookup a key in a Bitmap node. */\n\n    uint32_t bit = hamt_bitpos(hash, shift);\n    uint32_t idx;\n    uint32_t key_idx;\n    uint32_t val_idx;\n    PyObject *key_or_null;\n    PyObject *val_or_node;\n    int comp_err;\n\n    if ((self->b_bitmap & bit) == 0) {\n        return F_NOT_FOUND;\n    }\n\n    idx = hamt_bitindex(self->b_bitmap, bit);\n    key_idx = idx * 2;\n    val_idx = key_idx + 1;\n\n    assert(val_idx < (size_t)Py_SIZE(self));\n\n    key_or_null = self->b_array[key_idx];\n    val_or_node = self->b_array[val_idx];\n\n    if (key_or_null == NULL) {\n        /* There are a few keys that have the same hash at the current shift\n           that match our key.  Dispatch the lookup further down the tree. */\n        assert(val_or_node != NULL);\n        return hamt_node_find((PyHamtNode *)val_or_node,\n                              shift + 5, hash, key, val);\n    }\n\n    /* We have only one key -- a potential match.  Let's compare if the\n       key we are looking at is equal to the key we are looking for. */\n    assert(key != NULL);\n    comp_err = PyObject_RichCompareBool(key, key_or_null, Py_EQ);\n    if (comp_err < 0) {  /* exception in __eq__ */\n        return F_ERROR;\n    }\n    if (comp_err == 1) {  /* key == key_or_null */\n        *val = val_or_node;\n        return F_FOUND;\n    }\n\n    return F_NOT_FOUND;\n}\n\nstatic int\nhamt_node_bitmap_traverse(PyHamtNode_Bitmap *self, visitproc visit, void *arg)\n{\n    /* Bitmap's tp_traverse */\n\n    Py_ssize_t i;\n\n    for (i = Py_SIZE(self); --i >= 0; ) {\n        Py_VISIT(self->b_array[i]);\n    }\n\n    return 0;\n}\n\nstatic void\nhamt_node_bitmap_dealloc(PyHamtNode_Bitmap *self)\n{\n    /* Bitmap's tp_dealloc */\n\n    Py_ssize_t len = Py_SIZE(self);\n    Py_ssize_t i;\n\n    if (Py_SIZE(self) == 0) {\n        /* The empty node is statically allocated. */\n        assert(self == &_Py_SINGLETON(hamt_bitmap_node_empty));\n#ifdef Py_DEBUG\n        _Py_FatalRefcountError(\"deallocating the empty hamt node bitmap singleton\");\n#else\n        return;\n#endif\n    }\n\n    PyObject_GC_UnTrack(self);\n    Py_TRASHCAN_BEGIN(self, hamt_node_bitmap_dealloc)\n\n    if (len > 0) {\n        i = len;\n        while (--i >= 0) {\n            Py_XDECREF(self->b_array[i]);\n        }\n    }\n\n    Py_TYPE(self)->tp_free((PyObject *)self);\n    Py_TRASHCAN_END\n}\n\n#ifdef Py_DEBUG\nstatic int\nhamt_node_bitmap_dump(PyHamtNode_Bitmap *node,\n                      _PyUnicodeWriter *writer, int level)\n{\n    /* Debug build: __dump__() method implementation for Bitmap nodes. */\n\n    Py_ssize_t i;\n    PyObject *tmp1;\n    PyObject *tmp2;\n\n    if (_hamt_dump_ident(writer, level + 1)) {\n        goto error;\n    }\n\n    if (_hamt_dump_format(writer, \"BitmapNode(size=%zd count=%zd \",\n                          Py_SIZE(node), Py_SIZE(node) / 2))\n    {\n        goto error;\n    }\n\n    tmp1 = PyLong_FromUnsignedLong(node->b_bitmap);\n    if (tmp1 == NULL) {\n        goto error;\n    }\n    tmp2 = _PyLong_Format(tmp1, 2);\n    Py_DECREF(tmp1);\n    if (tmp2 == NULL) {\n        goto error;\n    }\n    if (_hamt_dump_format(writer, \"bitmap=%S id=%p):\\n\", tmp2, node)) {\n        Py_DECREF(tmp2);\n        goto error;\n    }\n    Py_DECREF(tmp2);\n\n    for (i = 0; i < Py_SIZE(node); i += 2) {\n        PyObject *key_or_null = node->b_array[i];\n        PyObject *val_or_node = node->b_array[i + 1];\n\n        if (_hamt_dump_ident(writer, level + 2)) {\n            goto error;\n        }\n\n        if (key_or_null == NULL) {\n            if (_hamt_dump_format(writer, \"NULL:\\n\")) {\n                goto error;\n            }\n\n            if (hamt_node_dump((PyHamtNode *)val_or_node,\n                               writer, level + 2))\n            {\n                goto error;\n            }\n        }\n        else {\n            if (_hamt_dump_format(writer, \"%R: %R\", key_or_null,\n                                  val_or_node))\n            {\n                goto error;\n            }\n        }\n\n        if (_hamt_dump_format(writer, \"\\n\")) {\n            goto error;\n        }\n    }\n\n    return 0;\nerror:\n    return -1;\n}\n#endif  /* Py_DEBUG */\n\n\n/////////////////////////////////// Collision Node\n\n\nstatic PyHamtNode *\nhamt_node_collision_new(int32_t hash, Py_ssize_t size)\n{\n    /* Create a new Collision node. */\n\n    PyHamtNode_Collision *node;\n    Py_ssize_t i;\n\n    assert(size >= 4);\n    assert(size % 2 == 0);\n\n    node = PyObject_GC_NewVar(\n        PyHamtNode_Collision, &_PyHamt_CollisionNode_Type, size);\n    if (node == NULL) {\n        return NULL;\n    }\n\n    for (i = 0; i < size; i++) {\n        node->c_array[i] = NULL;\n    }\n\n    Py_SET_SIZE(node, size);\n    node->c_hash = hash;\n\n    _PyObject_GC_TRACK(node);\n\n    return (PyHamtNode *)node;\n}\n\nstatic hamt_find_t\nhamt_node_collision_find_index(PyHamtNode_Collision *self, PyObject *key,\n                               Py_ssize_t *idx)\n{\n    /* Lookup `key` in the Collision node `self`.  Set the index of the\n       found key to 'idx'. */\n\n    Py_ssize_t i;\n    PyObject *el;\n\n    for (i = 0; i < Py_SIZE(self); i += 2) {\n        el = self->c_array[i];\n\n        assert(el != NULL);\n        int cmp = PyObject_RichCompareBool(key, el, Py_EQ);\n        if (cmp < 0) {\n            return F_ERROR;\n        }\n        if (cmp == 1) {\n            *idx = i;\n            return F_FOUND;\n        }\n    }\n\n    return F_NOT_FOUND;\n}\n\nstatic PyHamtNode *\nhamt_node_collision_assoc(PyHamtNode_Collision *self,\n                          uint32_t shift, int32_t hash,\n                          PyObject *key, PyObject *val, int* added_leaf)\n{\n    /* Set a new key to this level (currently a Collision node)\n       of the tree. */\n\n    if (hash == self->c_hash) {\n        /* The hash of the 'key' we are adding matches the hash of\n           other keys in this Collision node. */\n\n        Py_ssize_t key_idx = -1;\n        hamt_find_t found;\n        PyHamtNode_Collision *new_node;\n        Py_ssize_t i;\n\n        /* Let's try to lookup the new 'key', maybe we already have it. */\n        found = hamt_node_collision_find_index(self, key, &key_idx);\n        switch (found) {\n            case F_ERROR:\n                /* Exception. */\n                return NULL;\n\n            case F_NOT_FOUND:\n                /* This is a totally new key.  Clone the current node,\n                   add a new key/value to the cloned node. */\n\n                new_node = (PyHamtNode_Collision *)hamt_node_collision_new(\n                    self->c_hash, Py_SIZE(self) + 2);\n                if (new_node == NULL) {\n                    return NULL;\n                }\n\n                for (i = 0; i < Py_SIZE(self); i++) {\n                    new_node->c_array[i] = Py_NewRef(self->c_array[i]);\n                }\n\n                new_node->c_array[i] = Py_NewRef(key);\n                new_node->c_array[i + 1] = Py_NewRef(val);\n\n                *added_leaf = 1;\n                return (PyHamtNode *)new_node;\n\n            case F_FOUND:\n                /* There's a key which is equal to the key we are adding. */\n\n                assert(key_idx >= 0);\n                assert(key_idx < Py_SIZE(self));\n                Py_ssize_t val_idx = key_idx + 1;\n\n                if (self->c_array[val_idx] == val) {\n                    /* We're setting a key/value pair that's already set. */\n                    return (PyHamtNode *)Py_NewRef(self);\n                }\n\n                /* We need to replace old value for the key\n                   with a new value.  Create a new Collision node.*/\n                new_node = (PyHamtNode_Collision *)hamt_node_collision_new(\n                    self->c_hash, Py_SIZE(self));\n                if (new_node == NULL) {\n                    return NULL;\n                }\n\n                /* Copy all elements of the old node to the new one. */\n                for (i = 0; i < Py_SIZE(self); i++) {\n                    new_node->c_array[i] = Py_NewRef(self->c_array[i]);\n                }\n\n                /* Replace the old value with the new value for the our key. */\n                Py_SETREF(new_node->c_array[val_idx], Py_NewRef(val));\n\n                return (PyHamtNode *)new_node;\n\n            default:\n                Py_UNREACHABLE();\n        }\n    }\n    else {\n        /* The hash of the new key is different from the hash that\n           all keys of this Collision node have.\n\n           Create a Bitmap node inplace with two children:\n           key/value pair that we're adding, and the Collision node\n           we're replacing on this tree level.\n        */\n\n        PyHamtNode_Bitmap *new_node;\n        PyHamtNode *assoc_res;\n\n        new_node = (PyHamtNode_Bitmap *)hamt_node_bitmap_new(2);\n        if (new_node == NULL) {\n            return NULL;\n        }\n        new_node->b_bitmap = hamt_bitpos(self->c_hash, shift);\n        new_node->b_array[1] = Py_NewRef(self);\n\n        assoc_res = hamt_node_bitmap_assoc(\n            new_node, shift, hash, key, val, added_leaf);\n        Py_DECREF(new_node);\n        return assoc_res;\n    }\n}\n\nstatic inline Py_ssize_t\nhamt_node_collision_count(PyHamtNode_Collision *node)\n{\n    return Py_SIZE(node) / 2;\n}\n\nstatic hamt_without_t\nhamt_node_collision_without(PyHamtNode_Collision *self,\n                            uint32_t shift, int32_t hash,\n                            PyObject *key,\n                            PyHamtNode **new_node)\n{\n    if (hash != self->c_hash) {\n        return W_NOT_FOUND;\n    }\n\n    Py_ssize_t key_idx = -1;\n    hamt_find_t found = hamt_node_collision_find_index(self, key, &key_idx);\n\n    switch (found) {\n        case F_ERROR:\n            return W_ERROR;\n\n        case F_NOT_FOUND:\n            return W_NOT_FOUND;\n\n        case F_FOUND:\n            assert(key_idx >= 0);\n            assert(key_idx < Py_SIZE(self));\n\n            Py_ssize_t new_count = hamt_node_collision_count(self) - 1;\n\n            if (new_count == 0) {\n                /* The node has only one key/value pair and it's for the\n                   key we're trying to delete.  So a new node will be empty\n                   after the removal.\n                */\n                return W_EMPTY;\n            }\n\n            if (new_count == 1) {\n                /* The node has two keys, and after deletion the\n                   new Collision node would have one.  Collision nodes\n                   with one key shouldn't exist, so convert it to a\n                   Bitmap node.\n                */\n                PyHamtNode_Bitmap *node = (PyHamtNode_Bitmap *)\n                    hamt_node_bitmap_new(2);\n                if (node == NULL) {\n                    return W_ERROR;\n                }\n\n                if (key_idx == 0) {\n                    node->b_array[0] = Py_NewRef(self->c_array[2]);\n                    node->b_array[1] = Py_NewRef(self->c_array[3]);\n                }\n                else {\n                    assert(key_idx == 2);\n                    node->b_array[0] = Py_NewRef(self->c_array[0]);\n                    node->b_array[1] = Py_NewRef(self->c_array[1]);\n                }\n\n                node->b_bitmap = hamt_bitpos(hash, shift);\n\n                *new_node = (PyHamtNode *)node;\n                return W_NEWNODE;\n            }\n\n            /* Allocate a new Collision node with capacity for one\n               less key/value pair */\n            PyHamtNode_Collision *new = (PyHamtNode_Collision *)\n                hamt_node_collision_new(\n                    self->c_hash, Py_SIZE(self) - 2);\n            if (new == NULL) {\n                return W_ERROR;\n            }\n\n            /* Copy all other keys from `self` to `new` */\n            Py_ssize_t i;\n            for (i = 0; i < key_idx; i++) {\n                new->c_array[i] = Py_NewRef(self->c_array[i]);\n            }\n            for (i = key_idx + 2; i < Py_SIZE(self); i++) {\n                new->c_array[i - 2] = Py_NewRef(self->c_array[i]);\n            }\n\n            *new_node = (PyHamtNode*)new;\n            return W_NEWNODE;\n\n        default:\n            Py_UNREACHABLE();\n    }\n}\n\nstatic hamt_find_t\nhamt_node_collision_find(PyHamtNode_Collision *self,\n                         uint32_t shift, int32_t hash,\n                         PyObject *key, PyObject **val)\n{\n    /* Lookup `key` in the Collision node `self`.  Set the value\n       for the found key to 'val'. */\n\n    Py_ssize_t idx = -1;\n    hamt_find_t res;\n\n    res = hamt_node_collision_find_index(self, key, &idx);\n    if (res == F_ERROR || res == F_NOT_FOUND) {\n        return res;\n    }\n\n    assert(idx >= 0);\n    assert(idx + 1 < Py_SIZE(self));\n\n    *val = self->c_array[idx + 1];\n    assert(*val != NULL);\n\n    return F_FOUND;\n}\n\n\nstatic int\nhamt_node_collision_traverse(PyHamtNode_Collision *self,\n                             visitproc visit, void *arg)\n{\n    /* Collision's tp_traverse */\n\n    Py_ssize_t i;\n\n    for (i = Py_SIZE(self); --i >= 0; ) {\n        Py_VISIT(self->c_array[i]);\n    }\n\n    return 0;\n}\n\nstatic void\nhamt_node_collision_dealloc(PyHamtNode_Collision *self)\n{\n    /* Collision's tp_dealloc */\n\n    Py_ssize_t len = Py_SIZE(self);\n\n    PyObject_GC_UnTrack(self);\n    Py_TRASHCAN_BEGIN(self, hamt_node_collision_dealloc)\n\n    if (len > 0) {\n\n        while (--len >= 0) {\n            Py_XDECREF(self->c_array[len]);\n        }\n    }\n\n    Py_TYPE(self)->tp_free((PyObject *)self);\n    Py_TRASHCAN_END\n}\n\n#ifdef Py_DEBUG\nstatic int\nhamt_node_collision_dump(PyHamtNode_Collision *node,\n                         _PyUnicodeWriter *writer, int level)\n{\n    /* Debug build: __dump__() method implementation for Collision nodes. */\n\n    Py_ssize_t i;\n\n    if (_hamt_dump_ident(writer, level + 1)) {\n        goto error;\n    }\n\n    if (_hamt_dump_format(writer, \"CollisionNode(size=%zd id=%p):\\n\",\n                          Py_SIZE(node), node))\n    {\n        goto error;\n    }\n\n    for (i = 0; i < Py_SIZE(node); i += 2) {\n        PyObject *key = node->c_array[i];\n        PyObject *val = node->c_array[i + 1];\n\n        if (_hamt_dump_ident(writer, level + 2)) {\n            goto error;\n        }\n\n        if (_hamt_dump_format(writer, \"%R: %R\\n\", key, val)) {\n            goto error;\n        }\n    }\n\n    return 0;\nerror:\n    return -1;\n}\n#endif  /* Py_DEBUG */\n\n\n/////////////////////////////////// Array Node\n\n\nstatic PyHamtNode *\nhamt_node_array_new(Py_ssize_t count)\n{\n    Py_ssize_t i;\n\n    PyHamtNode_Array *node = PyObject_GC_New(\n        PyHamtNode_Array, &_PyHamt_ArrayNode_Type);\n    if (node == NULL) {\n        return NULL;\n    }\n\n    for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {\n        node->a_array[i] = NULL;\n    }\n\n    node->a_count = count;\n\n    _PyObject_GC_TRACK(node);\n    return (PyHamtNode *)node;\n}\n\nstatic PyHamtNode_Array *\nhamt_node_array_clone(PyHamtNode_Array *node)\n{\n    PyHamtNode_Array *clone;\n    Py_ssize_t i;\n\n    VALIDATE_ARRAY_NODE(node)\n\n    /* Create a new Array node. */\n    clone = (PyHamtNode_Array *)hamt_node_array_new(node->a_count);\n    if (clone == NULL) {\n        return NULL;\n    }\n\n    /* Copy all elements from the current Array node to the new one. */\n    for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {\n        clone->a_array[i] = (PyHamtNode*)Py_XNewRef(node->a_array[i]);\n    }\n\n    VALIDATE_ARRAY_NODE(clone)\n    return clone;\n}\n\nstatic PyHamtNode *\nhamt_node_array_assoc(PyHamtNode_Array *self,\n                      uint32_t shift, int32_t hash,\n                      PyObject *key, PyObject *val, int* added_leaf)\n{\n    /* Set a new key to this level (currently a Collision node)\n       of the tree.\n\n       Array nodes don't store values, they can only point to\n       other nodes.  They are simple arrays of 32 BaseNode pointers/\n     */\n\n    uint32_t idx = hamt_mask(hash, shift);\n    PyHamtNode *node = self->a_array[idx];\n    PyHamtNode *child_node;\n    PyHamtNode_Array *new_node;\n    Py_ssize_t i;\n\n    if (node == NULL) {\n        /* There's no child node for the given hash.  Create a new\n           Bitmap node for this key. */\n\n        PyHamtNode_Bitmap *empty = NULL;\n\n        /* Get an empty Bitmap node to work with. */\n        empty = (PyHamtNode_Bitmap *)hamt_node_bitmap_new(0);\n        if (empty == NULL) {\n            return NULL;\n        }\n\n        /* Set key/val to the newly created empty Bitmap, thus\n           creating a new Bitmap node with our key/value pair. */\n        child_node = hamt_node_bitmap_assoc(\n            empty,\n            shift + 5, hash, key, val, added_leaf);\n        Py_DECREF(empty);\n        if (child_node == NULL) {\n            return NULL;\n        }\n\n        /* Create a new Array node. */\n        new_node = (PyHamtNode_Array *)hamt_node_array_new(self->a_count + 1);\n        if (new_node == NULL) {\n            Py_DECREF(child_node);\n            return NULL;\n        }\n\n        /* Copy all elements from the current Array node to the\n           new one. */\n        for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {\n            new_node->a_array[i] = (PyHamtNode*)Py_XNewRef(self->a_array[i]);\n        }\n\n        assert(new_node->a_array[idx] == NULL);\n        new_node->a_array[idx] = child_node;  /* borrow */\n        VALIDATE_ARRAY_NODE(new_node)\n    }\n    else {\n        /* There's a child node for the given hash.\n           Set the key to it./ */\n        child_node = hamt_node_assoc(\n            node, shift + 5, hash, key, val, added_leaf);\n        if (child_node == NULL) {\n            return NULL;\n        }\n        else if (child_node == (PyHamtNode *)self) {\n            Py_DECREF(child_node);\n            return (PyHamtNode *)self;\n        }\n\n        new_node = hamt_node_array_clone(self);\n        if (new_node == NULL) {\n            Py_DECREF(child_node);\n            return NULL;\n        }\n\n        Py_SETREF(new_node->a_array[idx], child_node);  /* borrow */\n        VALIDATE_ARRAY_NODE(new_node)\n    }\n\n    return (PyHamtNode *)new_node;\n}\n\nstatic hamt_without_t\nhamt_node_array_without(PyHamtNode_Array *self,\n                        uint32_t shift, int32_t hash,\n                        PyObject *key,\n                        PyHamtNode **new_node)\n{\n    uint32_t idx = hamt_mask(hash, shift);\n    PyHamtNode *node = self->a_array[idx];\n\n    if (node == NULL) {\n        return W_NOT_FOUND;\n    }\n\n    PyHamtNode *sub_node = NULL;\n    hamt_without_t res = hamt_node_without(\n        (PyHamtNode *)node,\n        shift + 5, hash, key, &sub_node);\n\n    switch (res) {\n        case W_NOT_FOUND:\n        case W_ERROR:\n            assert(sub_node == NULL);\n            return res;\n\n        case W_NEWNODE: {\n            /* We need to replace a node at the `idx` index.\n               Clone this node and replace.\n            */\n            assert(sub_node != NULL);\n\n            PyHamtNode_Array *clone = hamt_node_array_clone(self);\n            if (clone == NULL) {\n                Py_DECREF(sub_node);\n                return W_ERROR;\n            }\n\n            Py_SETREF(clone->a_array[idx], sub_node);  /* borrow */\n            *new_node = (PyHamtNode*)clone;  /* borrow */\n            return W_NEWNODE;\n        }\n\n        case W_EMPTY: {\n            assert(sub_node == NULL);\n            /* We need to remove a node at the `idx` index.\n               Calculate the size of the replacement Array node.\n            */\n            Py_ssize_t new_count = self->a_count - 1;\n\n            if (new_count == 0) {\n                return W_EMPTY;\n            }\n\n            if (new_count >= 16) {\n                /* We convert Bitmap nodes to Array nodes, when a\n                   Bitmap node needs to store more than 15 key/value\n                   pairs.  So we will create a new Array node if we\n                   the number of key/values after deletion is still\n                   greater than 15.\n                */\n\n                PyHamtNode_Array *new = hamt_node_array_clone(self);\n                if (new == NULL) {\n                    return W_ERROR;\n                }\n                new->a_count = new_count;\n                Py_CLEAR(new->a_array[idx]);\n\n                *new_node = (PyHamtNode*)new;  /* borrow */\n                return W_NEWNODE;\n            }\n\n            /* New Array node would have less than 16 key/value\n               pairs.  We need to create a replacement Bitmap node. */\n\n            Py_ssize_t bitmap_size = new_count * 2;\n            uint32_t bitmap = 0;\n\n            PyHamtNode_Bitmap *new = (PyHamtNode_Bitmap *)\n                hamt_node_bitmap_new(bitmap_size);\n            if (new == NULL) {\n                return W_ERROR;\n            }\n\n            Py_ssize_t new_i = 0;\n            for (uint32_t i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {\n                if (i == idx) {\n                    /* Skip the node we are deleting. */\n                    continue;\n                }\n\n                PyHamtNode *node = self->a_array[i];\n                if (node == NULL) {\n                    /* Skip any missing nodes. */\n                    continue;\n                }\n\n                bitmap |= 1U << i;\n\n                if (IS_BITMAP_NODE(node)) {\n                    PyHamtNode_Bitmap *child = (PyHamtNode_Bitmap *)node;\n\n                    if (hamt_node_bitmap_count(child) == 1 &&\n                            child->b_array[0] != NULL)\n                    {\n                        /* node is a Bitmap with one key/value pair, just\n                           merge it into the new Bitmap node we're building.\n\n                           Note that we don't inline Bitmap nodes that\n                           have a NULL key -- those nodes point to another\n                           tree level, and we cannot simply move tree levels\n                           up or down.\n                        */\n                        PyObject *key = child->b_array[0];\n                        PyObject *val = child->b_array[1];\n\n                        new->b_array[new_i] = Py_NewRef(key);\n                        new->b_array[new_i + 1] = Py_NewRef(val);\n                    }\n                    else {\n                        new->b_array[new_i] = NULL;\n                        new->b_array[new_i + 1] = Py_NewRef(node);\n                    }\n                }\n                else {\n\n#ifdef Py_DEBUG\n                    if (IS_COLLISION_NODE(node)) {\n                        Py_ssize_t child_count = hamt_node_collision_count(\n                            (PyHamtNode_Collision*)node);\n                        assert(child_count > 1);\n                    }\n                    else if (IS_ARRAY_NODE(node)) {\n                        assert(((PyHamtNode_Array*)node)->a_count >= 16);\n                    }\n#endif\n\n                    /* Just copy the node into our new Bitmap */\n                    new->b_array[new_i] = NULL;\n                    new->b_array[new_i + 1] = Py_NewRef(node);\n                }\n\n                new_i += 2;\n            }\n\n            new->b_bitmap = bitmap;\n            *new_node = (PyHamtNode*)new;  /* borrow */\n            return W_NEWNODE;\n        }\n\n        default:\n            Py_UNREACHABLE();\n    }\n}\n\nstatic hamt_find_t\nhamt_node_array_find(PyHamtNode_Array *self,\n                     uint32_t shift, int32_t hash,\n                     PyObject *key, PyObject **val)\n{\n    /* Lookup `key` in the Array node `self`.  Set the value\n       for the found key to 'val'. */\n\n    uint32_t idx = hamt_mask(hash, shift);\n    PyHamtNode *node;\n\n    node = self->a_array[idx];\n    if (node == NULL) {\n        return F_NOT_FOUND;\n    }\n\n    /* Dispatch to the generic hamt_node_find */\n    return hamt_node_find(node, shift + 5, hash, key, val);\n}\n\nstatic int\nhamt_node_array_traverse(PyHamtNode_Array *self,\n                         visitproc visit, void *arg)\n{\n    /* Array's tp_traverse */\n\n    Py_ssize_t i;\n\n    for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {\n        Py_VISIT(self->a_array[i]);\n    }\n\n    return 0;\n}\n\nstatic void\nhamt_node_array_dealloc(PyHamtNode_Array *self)\n{\n    /* Array's tp_dealloc */\n\n    Py_ssize_t i;\n\n    PyObject_GC_UnTrack(self);\n    Py_TRASHCAN_BEGIN(self, hamt_node_array_dealloc)\n\n    for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {\n        Py_XDECREF(self->a_array[i]);\n    }\n\n    Py_TYPE(self)->tp_free((PyObject *)self);\n    Py_TRASHCAN_END\n}\n\n#ifdef Py_DEBUG\nstatic int\nhamt_node_array_dump(PyHamtNode_Array *node,\n                     _PyUnicodeWriter *writer, int level)\n{\n    /* Debug build: __dump__() method implementation for Array nodes. */\n\n    Py_ssize_t i;\n\n    if (_hamt_dump_ident(writer, level + 1)) {\n        goto error;\n    }\n\n    if (_hamt_dump_format(writer, \"ArrayNode(id=%p):\\n\", node)) {\n        goto error;\n    }\n\n    for (i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) {\n        if (node->a_array[i] == NULL) {\n            continue;\n        }\n\n        if (_hamt_dump_ident(writer, level + 2)) {\n            goto error;\n        }\n\n        if (_hamt_dump_format(writer, \"%zd::\\n\", i)) {\n            goto error;\n        }\n\n        if (hamt_node_dump(node->a_array[i], writer, level + 1)) {\n            goto error;\n        }\n\n        if (_hamt_dump_format(writer, \"\\n\")) {\n            goto error;\n        }\n    }\n\n    return 0;\nerror:\n    return -1;\n}\n#endif  /* Py_DEBUG */\n\n\n/////////////////////////////////// Node Dispatch\n\n\nstatic PyHamtNode *\nhamt_node_assoc(PyHamtNode *node,\n                uint32_t shift, int32_t hash,\n                PyObject *key, PyObject *val, int* added_leaf)\n{\n    /* Set key/value to the 'node' starting with the given shift/hash.\n       Return a new node, or the same node if key/value already\n       set.\n\n       added_leaf will be set to 1 if key/value wasn't in the\n       tree before.\n\n       This method automatically dispatches to the suitable\n       hamt_node_{nodetype}_assoc method.\n    */\n\n    if (IS_BITMAP_NODE(node)) {\n        return hamt_node_bitmap_assoc(\n            (PyHamtNode_Bitmap *)node,\n            shift, hash, key, val, added_leaf);\n    }\n    else if (IS_ARRAY_NODE(node)) {\n        return hamt_node_array_assoc(\n            (PyHamtNode_Array *)node,\n            shift, hash, key, val, added_leaf);\n    }\n    else {\n        assert(IS_COLLISION_NODE(node));\n        return hamt_node_collision_assoc(\n            (PyHamtNode_Collision *)node,\n            shift, hash, key, val, added_leaf);\n    }\n}\n\nstatic hamt_without_t\nhamt_node_without(PyHamtNode *node,\n                  uint32_t shift, int32_t hash,\n                  PyObject *key,\n                  PyHamtNode **new_node)\n{\n    if (IS_BITMAP_NODE(node)) {\n        return hamt_node_bitmap_without(\n            (PyHamtNode_Bitmap *)node,\n            shift, hash, key,\n            new_node);\n    }\n    else if (IS_ARRAY_NODE(node)) {\n        return hamt_node_array_without(\n            (PyHamtNode_Array *)node,\n            shift, hash, key,\n            new_node);\n    }\n    else {\n        assert(IS_COLLISION_NODE(node));\n        return hamt_node_collision_without(\n            (PyHamtNode_Collision *)node,\n            shift, hash, key,\n            new_node);\n    }\n}\n\nstatic hamt_find_t\nhamt_node_find(PyHamtNode *node,\n               uint32_t shift, int32_t hash,\n               PyObject *key, PyObject **val)\n{\n    /* Find the key in the node starting with the given shift/hash.\n\n       If a value is found, the result will be set to F_FOUND, and\n       *val will point to the found value object.\n\n       If a value wasn't found, the result will be set to F_NOT_FOUND.\n\n       If an exception occurs during the call, the result will be F_ERROR.\n\n       This method automatically dispatches to the suitable\n       hamt_node_{nodetype}_find method.\n    */\n\n    if (IS_BITMAP_NODE(node)) {\n        return hamt_node_bitmap_find(\n            (PyHamtNode_Bitmap *)node,\n            shift, hash, key, val);\n\n    }\n    else if (IS_ARRAY_NODE(node)) {\n        return hamt_node_array_find(\n            (PyHamtNode_Array *)node,\n            shift, hash, key, val);\n    }\n    else {\n        assert(IS_COLLISION_NODE(node));\n        return hamt_node_collision_find(\n            (PyHamtNode_Collision *)node,\n            shift, hash, key, val);\n    }\n}\n\n#ifdef Py_DEBUG\nstatic int\nhamt_node_dump(PyHamtNode *node,\n               _PyUnicodeWriter *writer, int level)\n{\n    /* Debug build: __dump__() method implementation for a node.\n\n       This method automatically dispatches to the suitable\n       hamt_node_{nodetype})_dump method.\n    */\n\n    if (IS_BITMAP_NODE(node)) {\n        return hamt_node_bitmap_dump(\n            (PyHamtNode_Bitmap *)node, writer, level);\n    }\n    else if (IS_ARRAY_NODE(node)) {\n        return hamt_node_array_dump(\n            (PyHamtNode_Array *)node, writer, level);\n    }\n    else {\n        assert(IS_COLLISION_NODE(node));\n        return hamt_node_collision_dump(\n            (PyHamtNode_Collision *)node, writer, level);\n    }\n}\n#endif  /* Py_DEBUG */\n\n\n/////////////////////////////////// Iterators: Machinery\n\n\nstatic hamt_iter_t\nhamt_iterator_next(PyHamtIteratorState *iter, PyObject **key, PyObject **val);\n\n\nstatic void\nhamt_iterator_init(PyHamtIteratorState *iter, PyHamtNode *root)\n{\n    for (uint32_t i = 0; i < _Py_HAMT_MAX_TREE_DEPTH; i++) {\n        iter->i_nodes[i] = NULL;\n        iter->i_pos[i] = 0;\n    }\n\n    iter->i_level = 0;\n\n    /* Note: we don't incref/decref nodes in i_nodes. */\n    iter->i_nodes[0] = root;\n}\n\nstatic hamt_iter_t\nhamt_iterator_bitmap_next(PyHamtIteratorState *iter,\n                          PyObject **key, PyObject **val)\n{\n    int8_t level = iter->i_level;\n\n    PyHamtNode_Bitmap *node = (PyHamtNode_Bitmap *)(iter->i_nodes[level]);\n    Py_ssize_t pos = iter->i_pos[level];\n\n    if (pos + 1 >= Py_SIZE(node)) {\n#ifdef Py_DEBUG\n        assert(iter->i_level >= 0);\n        iter->i_nodes[iter->i_level] = NULL;\n#endif\n        iter->i_level--;\n        return hamt_iterator_next(iter, key, val);\n    }\n\n    if (node->b_array[pos] == NULL) {\n        iter->i_pos[level] = pos + 2;\n\n        int8_t next_level = level + 1;\n        assert(next_level < _Py_HAMT_MAX_TREE_DEPTH);\n        iter->i_level = next_level;\n        iter->i_pos[next_level] = 0;\n        iter->i_nodes[next_level] = (PyHamtNode *)\n            node->b_array[pos + 1];\n\n        return hamt_iterator_next(iter, key, val);\n    }\n\n    *key = node->b_array[pos];\n    *val = node->b_array[pos + 1];\n    iter->i_pos[level] = pos + 2;\n    return I_ITEM;\n}\n\nstatic hamt_iter_t\nhamt_iterator_collision_next(PyHamtIteratorState *iter,\n                             PyObject **key, PyObject **val)\n{\n    int8_t level = iter->i_level;\n\n    PyHamtNode_Collision *node = (PyHamtNode_Collision *)(iter->i_nodes[level]);\n    Py_ssize_t pos = iter->i_pos[level];\n\n    if (pos + 1 >= Py_SIZE(node)) {\n#ifdef Py_DEBUG\n        assert(iter->i_level >= 0);\n        iter->i_nodes[iter->i_level] = NULL;\n#endif\n        iter->i_level--;\n        return hamt_iterator_next(iter, key, val);\n    }\n\n    *key = node->c_array[pos];\n    *val = node->c_array[pos + 1];\n    iter->i_pos[level] = pos + 2;\n    return I_ITEM;\n}\n\nstatic hamt_iter_t\nhamt_iterator_array_next(PyHamtIteratorState *iter,\n                         PyObject **key, PyObject **val)\n{\n    int8_t level = iter->i_level;\n\n    PyHamtNode_Array *node = (PyHamtNode_Array *)(iter->i_nodes[level]);\n    Py_ssize_t pos = iter->i_pos[level];\n\n    if (pos >= HAMT_ARRAY_NODE_SIZE) {\n#ifdef Py_DEBUG\n        assert(iter->i_level >= 0);\n        iter->i_nodes[iter->i_level] = NULL;\n#endif\n        iter->i_level--;\n        return hamt_iterator_next(iter, key, val);\n    }\n\n    for (Py_ssize_t i = pos; i < HAMT_ARRAY_NODE_SIZE; i++) {\n        if (node->a_array[i] != NULL) {\n            iter->i_pos[level] = i + 1;\n\n            int8_t next_level = level + 1;\n            assert(next_level < _Py_HAMT_MAX_TREE_DEPTH);\n            iter->i_pos[next_level] = 0;\n            iter->i_nodes[next_level] = node->a_array[i];\n            iter->i_level = next_level;\n\n            return hamt_iterator_next(iter, key, val);\n        }\n    }\n\n#ifdef Py_DEBUG\n        assert(iter->i_level >= 0);\n        iter->i_nodes[iter->i_level] = NULL;\n#endif\n\n    iter->i_level--;\n    return hamt_iterator_next(iter, key, val);\n}\n\nstatic hamt_iter_t\nhamt_iterator_next(PyHamtIteratorState *iter, PyObject **key, PyObject **val)\n{\n    if (iter->i_level < 0) {\n        return I_END;\n    }\n\n    assert(iter->i_level < _Py_HAMT_MAX_TREE_DEPTH);\n\n    PyHamtNode *current = iter->i_nodes[iter->i_level];\n\n    if (IS_BITMAP_NODE(current)) {\n        return hamt_iterator_bitmap_next(iter, key, val);\n    }\n    else if (IS_ARRAY_NODE(current)) {\n        return hamt_iterator_array_next(iter, key, val);\n    }\n    else {\n        assert(IS_COLLISION_NODE(current));\n        return hamt_iterator_collision_next(iter, key, val);\n    }\n}\n\n\n/////////////////////////////////// HAMT high-level functions\n\n\nPyHamtObject *\n_PyHamt_Assoc(PyHamtObject *o, PyObject *key, PyObject *val)\n{\n    int32_t key_hash;\n    int added_leaf = 0;\n    PyHamtNode *new_root;\n    PyHamtObject *new_o;\n\n    key_hash = hamt_hash(key);\n    if (key_hash == -1) {\n        return NULL;\n    }\n\n    new_root = hamt_node_assoc(\n        (PyHamtNode *)(o->h_root),\n        0, key_hash, key, val, &added_leaf);\n    if (new_root == NULL) {\n        return NULL;\n    }\n\n    if (new_root == o->h_root) {\n        Py_DECREF(new_root);\n        return (PyHamtObject*)Py_NewRef(o);\n    }\n\n    new_o = hamt_alloc();\n    if (new_o == NULL) {\n        Py_DECREF(new_root);\n        return NULL;\n    }\n\n    new_o->h_root = new_root;  /* borrow */\n    new_o->h_count = added_leaf ? o->h_count + 1 : o->h_count;\n\n    return new_o;\n}\n\nPyHamtObject *\n_PyHamt_Without(PyHamtObject *o, PyObject *key)\n{\n    int32_t key_hash = hamt_hash(key);\n    if (key_hash == -1) {\n        return NULL;\n    }\n\n    PyHamtNode *new_root = NULL;\n\n    hamt_without_t res = hamt_node_without(\n        (PyHamtNode *)(o->h_root),\n        0, key_hash, key,\n        &new_root);\n\n    switch (res) {\n        case W_ERROR:\n            return NULL;\n        case W_EMPTY:\n            return _PyHamt_New();\n        case W_NOT_FOUND:\n            return (PyHamtObject*)Py_NewRef(o);\n        case W_NEWNODE: {\n            assert(new_root != NULL);\n\n            PyHamtObject *new_o = hamt_alloc();\n            if (new_o == NULL) {\n                Py_DECREF(new_root);\n                return NULL;\n            }\n\n            new_o->h_root = new_root;  /* borrow */\n            new_o->h_count = o->h_count - 1;\n            assert(new_o->h_count >= 0);\n            return new_o;\n        }\n        default:\n            Py_UNREACHABLE();\n    }\n}\n\nstatic hamt_find_t\nhamt_find(PyHamtObject *o, PyObject *key, PyObject **val)\n{\n    if (o->h_count == 0) {\n        return F_NOT_FOUND;\n    }\n\n    int32_t key_hash = hamt_hash(key);\n    if (key_hash == -1) {\n        return F_ERROR;\n    }\n\n    return hamt_node_find(o->h_root, 0, key_hash, key, val);\n}\n\n\nint\n_PyHamt_Find(PyHamtObject *o, PyObject *key, PyObject **val)\n{\n    hamt_find_t res = hamt_find(o, key, val);\n    switch (res) {\n        case F_ERROR:\n            return -1;\n        case F_NOT_FOUND:\n            return 0;\n        case F_FOUND:\n            return 1;\n        default:\n            Py_UNREACHABLE();\n    }\n}\n\n\nint\n_PyHamt_Eq(PyHamtObject *v, PyHamtObject *w)\n{\n    if (v == w) {\n        return 1;\n    }\n\n    if (v->h_count != w->h_count) {\n        return 0;\n    }\n\n    PyHamtIteratorState iter;\n    hamt_iter_t iter_res;\n    hamt_find_t find_res;\n    PyObject *v_key;\n    PyObject *v_val;\n    PyObject *w_val;\n\n    hamt_iterator_init(&iter, v->h_root);\n\n    do {\n        iter_res = hamt_iterator_next(&iter, &v_key, &v_val);\n        if (iter_res == I_ITEM) {\n            find_res = hamt_find(w, v_key, &w_val);\n            switch (find_res) {\n                case F_ERROR:\n                    return -1;\n\n                case F_NOT_FOUND:\n                    return 0;\n\n                case F_FOUND: {\n                    int cmp = PyObject_RichCompareBool(v_val, w_val, Py_EQ);\n                    if (cmp < 0) {\n                        return -1;\n                    }\n                    if (cmp == 0) {\n                        return 0;\n                    }\n                }\n            }\n        }\n    } while (iter_res != I_END);\n\n    return 1;\n}\n\nPy_ssize_t\n_PyHamt_Len(PyHamtObject *o)\n{\n    return o->h_count;\n}\n\nstatic PyHamtObject *\nhamt_alloc(void)\n{\n    PyHamtObject *o;\n    o = PyObject_GC_New(PyHamtObject, &_PyHamt_Type);\n    if (o == NULL) {\n        return NULL;\n    }\n    o->h_count = 0;\n    o->h_root = NULL;\n    o->h_weakreflist = NULL;\n    PyObject_GC_Track(o);\n    return o;\n}\n\n#define _empty_hamt \\\n    (&_Py_INTERP_SINGLETON(_PyInterpreterState_Get(), hamt_empty))\n\nPyHamtObject *\n_PyHamt_New(void)\n{\n    /* HAMT is an immutable object so we can easily cache an\n       empty instance. */\n    return (PyHamtObject*)Py_NewRef(_empty_hamt);\n}\n\n#ifdef Py_DEBUG\nstatic PyObject *\nhamt_dump(PyHamtObject *self)\n{\n    _PyUnicodeWriter writer;\n\n    _PyUnicodeWriter_Init(&writer);\n\n    if (_hamt_dump_format(&writer, \"HAMT(len=%zd):\\n\", self->h_count)) {\n        goto error;\n    }\n\n    if (hamt_node_dump(self->h_root, &writer, 0)) {\n        goto error;\n    }\n\n    return _PyUnicodeWriter_Finish(&writer);\n\nerror:\n    _PyUnicodeWriter_Dealloc(&writer);\n    return NULL;\n}\n#endif  /* Py_DEBUG */\n\n\n/////////////////////////////////// Iterators: Shared Iterator Implementation\n\n\nstatic int\nhamt_baseiter_tp_clear(PyHamtIterator *it)\n{\n    Py_CLEAR(it->hi_obj);\n    return 0;\n}\n\nstatic void\nhamt_baseiter_tp_dealloc(PyHamtIterator *it)\n{\n    PyObject_GC_UnTrack(it);\n    (void)hamt_baseiter_tp_clear(it);\n    PyObject_GC_Del(it);\n}\n\nstatic int\nhamt_baseiter_tp_traverse(PyHamtIterator *it, visitproc visit, void *arg)\n{\n    Py_VISIT(it->hi_obj);\n    return 0;\n}\n\nstatic PyObject *\nhamt_baseiter_tp_iternext(PyHamtIterator *it)\n{\n    PyObject *key;\n    PyObject *val;\n    hamt_iter_t res = hamt_iterator_next(&it->hi_iter, &key, &val);\n\n    switch (res) {\n        case I_END:\n            PyErr_SetNone(PyExc_StopIteration);\n            return NULL;\n\n        case I_ITEM: {\n            return (*(it->hi_yield))(key, val);\n        }\n\n        default: {\n            Py_UNREACHABLE();\n        }\n    }\n}\n\nstatic Py_ssize_t\nhamt_baseiter_tp_len(PyHamtIterator *it)\n{\n    return it->hi_obj->h_count;\n}\n\nstatic PyMappingMethods PyHamtIterator_as_mapping = {\n    (lenfunc)hamt_baseiter_tp_len,\n};\n\nstatic PyObject *\nhamt_baseiter_new(PyTypeObject *type, binaryfunc yield, PyHamtObject *o)\n{\n    PyHamtIterator *it = PyObject_GC_New(PyHamtIterator, type);\n    if (it == NULL) {\n        return NULL;\n    }\n\n    it->hi_obj = (PyHamtObject*)Py_NewRef(o);\n    it->hi_yield = yield;\n\n    hamt_iterator_init(&it->hi_iter, o->h_root);\n\n    return (PyObject*)it;\n}\n\n#define ITERATOR_TYPE_SHARED_SLOTS                              \\\n    .tp_basicsize = sizeof(PyHamtIterator),                     \\\n    .tp_itemsize = 0,                                           \\\n    .tp_as_mapping = &PyHamtIterator_as_mapping,                \\\n    .tp_dealloc = (destructor)hamt_baseiter_tp_dealloc,         \\\n    .tp_getattro = PyObject_GenericGetAttr,                     \\\n    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,        \\\n    .tp_traverse = (traverseproc)hamt_baseiter_tp_traverse,     \\\n    .tp_clear = (inquiry)hamt_baseiter_tp_clear,                \\\n    .tp_iter = PyObject_SelfIter,                               \\\n    .tp_iternext = (iternextfunc)hamt_baseiter_tp_iternext,\n\n\n/////////////////////////////////// _PyHamtItems_Type\n\n\nPyTypeObject _PyHamtItems_Type = {\n    PyVarObject_HEAD_INIT(NULL, 0)\n    \"items\",\n    ITERATOR_TYPE_SHARED_SLOTS\n};\n\nstatic PyObject *\nhamt_iter_yield_items(PyObject *key, PyObject *val)\n{\n    return PyTuple_Pack(2, key, val);\n}\n\nPyObject *\n_PyHamt_NewIterItems(PyHamtObject *o)\n{\n    return hamt_baseiter_new(\n        &_PyHamtItems_Type, hamt_iter_yield_items, o);\n}\n\n\n/////////////////////////////////// _PyHamtKeys_Type\n\n\nPyTypeObject _PyHamtKeys_Type = {\n    PyVarObject_HEAD_INIT(NULL, 0)\n    \"keys\",\n    ITERATOR_TYPE_SHARED_SLOTS\n};\n\nstatic PyObject *\nhamt_iter_yield_keys(PyObject *key, PyObject *val)\n{\n    return Py_NewRef(key);\n}\n\nPyObject *\n_PyHamt_NewIterKeys(PyHamtObject *o)\n{\n    return hamt_baseiter_new(\n        &_PyHamtKeys_Type, hamt_iter_yield_keys, o);\n}\n\n\n/////////////////////////////////// _PyHamtValues_Type\n\n\nPyTypeObject _PyHamtValues_Type = {\n    PyVarObject_HEAD_INIT(NULL, 0)\n    \"values\",\n    ITERATOR_TYPE_SHARED_SLOTS\n};\n\nstatic PyObject *\nhamt_iter_yield_values(PyObject *key, PyObject *val)\n{\n    return Py_NewRef(val);\n}\n\nPyObject *\n_PyHamt_NewIterValues(PyHamtObject *o)\n{\n    return hamt_baseiter_new(\n        &_PyHamtValues_Type, hamt_iter_yield_values, o);\n}\n\n\n/////////////////////////////////// _PyHamt_Type\n\n\n#ifdef Py_DEBUG\nstatic PyObject *\nhamt_dump(PyHamtObject *self);\n#endif\n\n\nstatic PyObject *\nhamt_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n{\n    return (PyObject*)_PyHamt_New();\n}\n\nstatic int\nhamt_tp_clear(PyHamtObject *self)\n{\n    Py_CLEAR(self->h_root);\n    return 0;\n}\n\n\nstatic int\nhamt_tp_traverse(PyHamtObject *self, visitproc visit, void *arg)\n{\n    Py_VISIT(self->h_root);\n    return 0;\n}\n\nstatic void\nhamt_tp_dealloc(PyHamtObject *self)\n{\n    if (self == _empty_hamt) {\n        /* The empty one is statically allocated. */\n#ifdef Py_DEBUG\n        _Py_FatalRefcountError(\"deallocating the empty hamt singleton\");\n#else\n        return;\n#endif\n    }\n\n    PyObject_GC_UnTrack(self);\n    if (self->h_weakreflist != NULL) {\n        PyObject_ClearWeakRefs((PyObject*)self);\n    }\n    (void)hamt_tp_clear(self);\n    Py_TYPE(self)->tp_free(self);\n}\n\n\nstatic PyObject *\nhamt_tp_richcompare(PyObject *v, PyObject *w, int op)\n{\n    if (!PyHamt_Check(v) || !PyHamt_Check(w) || (op != Py_EQ && op != Py_NE)) {\n        Py_RETURN_NOTIMPLEMENTED;\n    }\n\n    int res = _PyHamt_Eq((PyHamtObject *)v, (PyHamtObject *)w);\n    if (res < 0) {\n        return NULL;\n    }\n\n    if (op == Py_NE) {\n        res = !res;\n    }\n\n    if (res) {\n        Py_RETURN_TRUE;\n    }\n    else {\n        Py_RETURN_FALSE;\n    }\n}\n\nstatic int\nhamt_tp_contains(PyHamtObject *self, PyObject *key)\n{\n    PyObject *val;\n    return _PyHamt_Find(self, key, &val);\n}\n\nstatic PyObject *\nhamt_tp_subscript(PyHamtObject *self, PyObject *key)\n{\n    PyObject *val;\n    hamt_find_t res = hamt_find(self, key, &val);\n    switch (res) {\n        case F_ERROR:\n            return NULL;\n        case F_FOUND:\n            return Py_NewRef(val);\n        case F_NOT_FOUND:\n            PyErr_SetObject(PyExc_KeyError, key);\n            return NULL;\n        default:\n            Py_UNREACHABLE();\n    }\n}\n\nstatic Py_ssize_t\nhamt_tp_len(PyHamtObject *self)\n{\n    return _PyHamt_Len(self);\n}\n\nstatic PyObject *\nhamt_tp_iter(PyHamtObject *self)\n{\n    return _PyHamt_NewIterKeys(self);\n}\n\nstatic PyObject *\nhamt_py_set(PyHamtObject *self, PyObject *args)\n{\n    PyObject *key;\n    PyObject *val;\n\n    if (!PyArg_UnpackTuple(args, \"set\", 2, 2, &key, &val)) {\n        return NULL;\n    }\n\n    return (PyObject *)_PyHamt_Assoc(self, key, val);\n}\n\nstatic PyObject *\nhamt_py_get(PyHamtObject *self, PyObject *args)\n{\n    PyObject *key;\n    PyObject *def = NULL;\n\n    if (!PyArg_UnpackTuple(args, \"get\", 1, 2, &key, &def)) {\n        return NULL;\n    }\n\n    PyObject *val = NULL;\n    hamt_find_t res = hamt_find(self, key, &val);\n    switch (res) {\n        case F_ERROR:\n            return NULL;\n        case F_FOUND:\n            return Py_NewRef(val);\n        case F_NOT_FOUND:\n            if (def == NULL) {\n                Py_RETURN_NONE;\n            }\n            return Py_NewRef(def);\n        default:\n            Py_UNREACHABLE();\n    }\n}\n\nstatic PyObject *\nhamt_py_delete(PyHamtObject *self, PyObject *key)\n{\n    return (PyObject *)_PyHamt_Without(self, key);\n}\n\nstatic PyObject *\nhamt_py_items(PyHamtObject *self, PyObject *args)\n{\n    return _PyHamt_NewIterItems(self);\n}\n\nstatic PyObject *\nhamt_py_values(PyHamtObject *self, PyObject *args)\n{\n    return _PyHamt_NewIterValues(self);\n}\n\nstatic PyObject *\nhamt_py_keys(PyHamtObject *self, PyObject *Py_UNUSED(args))\n{\n    return _PyHamt_NewIterKeys(self);\n}\n\n#ifdef Py_DEBUG\nstatic PyObject *\nhamt_py_dump(PyHamtObject *self, PyObject *Py_UNUSED(args))\n{\n    return hamt_dump(self);\n}\n#endif\n\n\nstatic PyMethodDef PyHamt_methods[] = {\n    {\"set\", _PyCFunction_CAST(hamt_py_set), METH_VARARGS, NULL},\n    {\"get\", _PyCFunction_CAST(hamt_py_get), METH_VARARGS, NULL},\n    {\"delete\", _PyCFunction_CAST(hamt_py_delete), METH_O, NULL},\n    {\"items\", _PyCFunction_CAST(hamt_py_items), METH_NOARGS, NULL},\n    {\"keys\", _PyCFunction_CAST(hamt_py_keys), METH_NOARGS, NULL},\n    {\"values\", _PyCFunction_CAST(hamt_py_values), METH_NOARGS, NULL},\n#ifdef Py_DEBUG\n    {\"__dump__\", _PyCFunction_CAST(hamt_py_dump), METH_NOARGS, NULL},\n#endif\n    {NULL, NULL}\n};\n\nstatic PySequenceMethods PyHamt_as_sequence = {\n    0,                                /* sq_length */\n    0,                                /* sq_concat */\n    0,                                /* sq_repeat */\n    0,                                /* sq_item */\n    0,                                /* sq_slice */\n    0,                                /* sq_ass_item */\n    0,                                /* sq_ass_slice */\n    (objobjproc)hamt_tp_contains,     /* sq_contains */\n    0,                                /* sq_inplace_concat */\n    0,                                /* sq_inplace_repeat */\n};\n\nstatic PyMappingMethods PyHamt_as_mapping = {\n    (lenfunc)hamt_tp_len,             /* mp_length */\n    (binaryfunc)hamt_tp_subscript,    /* mp_subscript */\n};\n\nPyTypeObject _PyHamt_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"hamt\",\n    sizeof(PyHamtObject),\n    .tp_methods = PyHamt_methods,\n    .tp_as_mapping = &PyHamt_as_mapping,\n    .tp_as_sequence = &PyHamt_as_sequence,\n    .tp_iter = (getiterfunc)hamt_tp_iter,\n    .tp_dealloc = (destructor)hamt_tp_dealloc,\n    .tp_getattro = PyObject_GenericGetAttr,\n    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,\n    .tp_richcompare = hamt_tp_richcompare,\n    .tp_traverse = (traverseproc)hamt_tp_traverse,\n    .tp_clear = (inquiry)hamt_tp_clear,\n    .tp_new = hamt_tp_new,\n    .tp_weaklistoffset = offsetof(PyHamtObject, h_weakreflist),\n    .tp_hash = PyObject_HashNotImplemented,\n};\n\n\n/////////////////////////////////// Tree Node Types\n\n\nPyTypeObject _PyHamt_ArrayNode_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"hamt_array_node\",\n    sizeof(PyHamtNode_Array),\n    0,\n    .tp_dealloc = (destructor)hamt_node_array_dealloc,\n    .tp_getattro = PyObject_GenericGetAttr,\n    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,\n    .tp_traverse = (traverseproc)hamt_node_array_traverse,\n    .tp_free = PyObject_GC_Del,\n    .tp_hash = PyObject_HashNotImplemented,\n};\n\nPyTypeObject _PyHamt_BitmapNode_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"hamt_bitmap_node\",\n    sizeof(PyHamtNode_Bitmap) - sizeof(PyObject *),\n    sizeof(PyObject *),\n    .tp_dealloc = (destructor)hamt_node_bitmap_dealloc,\n    .tp_getattro = PyObject_GenericGetAttr,\n    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,\n    .tp_traverse = (traverseproc)hamt_node_bitmap_traverse,\n    .tp_free = PyObject_GC_Del,\n    .tp_hash = PyObject_HashNotImplemented,\n};\n\nPyTypeObject _PyHamt_CollisionNode_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"hamt_collision_node\",\n    sizeof(PyHamtNode_Collision) - sizeof(PyObject *),\n    sizeof(PyObject *),\n    .tp_dealloc = (destructor)hamt_node_collision_dealloc,\n    .tp_getattro = PyObject_GenericGetAttr,\n    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,\n    .tp_traverse = (traverseproc)hamt_node_collision_traverse,\n    .tp_free = PyObject_GC_Del,\n    .tp_hash = PyObject_HashNotImplemented,\n};\n"
  },
  {
    "path": "HashTable.c",
    "content": "/* The implementation of the hash table (_Py_hashtable_t) is based on the\n   cfuhash project:\n   http://sourceforge.net/projects/libcfu/\n\n   Copyright of cfuhash:\n   ----------------------------------\n   Creation date: 2005-06-24 21:22:40\n   Authors: Don\n   Change log:\n\n   Copyright (c) 2005 Don Owens\n   All rights reserved.\n\n   This code is released under the BSD license:\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions\n   are met:\n\n     * Redistributions of source code must retain the above copyright\n       notice, this list of conditions and the following disclaimer.\n\n     * Redistributions in binary form must reproduce the above\n       copyright notice, this list of conditions and the following\n       disclaimer in the documentation and/or other materials provided\n       with the distribution.\n\n     * Neither the name of the author nor the names of its\n       contributors may be used to endorse or promote products derived\n       from this software without specific prior written permission.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n   OF THE POSSIBILITY OF SUCH DAMAGE.\n   ----------------------------------\n*/\n\n#include \"Python.h\"\n#include \"pycore_hashtable.h\"\n\n#define HASHTABLE_MIN_SIZE 16\n#define HASHTABLE_HIGH 0.50\n#define HASHTABLE_LOW 0.10\n#define HASHTABLE_REHASH_FACTOR 2.0 / (HASHTABLE_LOW + HASHTABLE_HIGH)\n\n#define BUCKETS_HEAD(SLIST) \\\n        ((_Py_hashtable_entry_t *)_Py_SLIST_HEAD(&(SLIST)))\n#define TABLE_HEAD(HT, BUCKET) \\\n        ((_Py_hashtable_entry_t *)_Py_SLIST_HEAD(&(HT)->buckets[BUCKET]))\n#define ENTRY_NEXT(ENTRY) \\\n        ((_Py_hashtable_entry_t *)_Py_SLIST_ITEM_NEXT(ENTRY))\n\n/* Forward declaration */\nstatic int hashtable_rehash(_Py_hashtable_t *ht);\n\nstatic void\n_Py_slist_init(_Py_slist_t *list)\n{\n    list->head = NULL;\n}\n\n\nstatic void\n_Py_slist_prepend(_Py_slist_t *list, _Py_slist_item_t *item)\n{\n    item->next = list->head;\n    list->head = item;\n}\n\n\nstatic void\n_Py_slist_remove(_Py_slist_t *list, _Py_slist_item_t *previous,\n                 _Py_slist_item_t *item)\n{\n    if (previous != NULL)\n        previous->next = item->next;\n    else\n        list->head = item->next;\n}\n\n\nPy_uhash_t\n_Py_hashtable_hash_ptr(const void *key)\n{\n    return (Py_uhash_t)_Py_HashPointerRaw(key);\n}\n\n\nint\n_Py_hashtable_compare_direct(const void *key1, const void *key2)\n{\n    return (key1 == key2);\n}\n\n\n/* makes sure the real size of the buckets array is a power of 2 */\nstatic size_t\nround_size(size_t s)\n{\n    size_t i;\n    if (s < HASHTABLE_MIN_SIZE)\n        return HASHTABLE_MIN_SIZE;\n    i = 1;\n    while (i < s)\n        i <<= 1;\n    return i;\n}\n\n\nsize_t\n_Py_hashtable_size(const _Py_hashtable_t *ht)\n{\n    size_t size = sizeof(_Py_hashtable_t);\n    /* buckets */\n    size += ht->nbuckets * sizeof(_Py_hashtable_entry_t *);\n    /* entries */\n    size += ht->nentries * sizeof(_Py_hashtable_entry_t);\n    return size;\n}\n\n\n_Py_hashtable_entry_t *\n_Py_hashtable_get_entry_generic(_Py_hashtable_t *ht, const void *key)\n{\n    Py_uhash_t key_hash = ht->hash_func(key);\n    size_t index = key_hash & (ht->nbuckets - 1);\n    _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, index);\n    while (1) {\n        if (entry == NULL) {\n            return NULL;\n        }\n        if (entry->key_hash == key_hash && ht->compare_func(key, entry->key)) {\n            break;\n        }\n        entry = ENTRY_NEXT(entry);\n    }\n    return entry;\n}\n\n\n// Specialized for:\n// hash_func == _Py_hashtable_hash_ptr\n// compare_func == _Py_hashtable_compare_direct\nstatic _Py_hashtable_entry_t *\n_Py_hashtable_get_entry_ptr(_Py_hashtable_t *ht, const void *key)\n{\n    Py_uhash_t key_hash = _Py_hashtable_hash_ptr(key);\n    size_t index = key_hash & (ht->nbuckets - 1);\n    _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, index);\n    while (1) {\n        if (entry == NULL) {\n            return NULL;\n        }\n        // Compare directly keys (ignore entry->key_hash)\n        if (entry->key == key) {\n            break;\n        }\n        entry = ENTRY_NEXT(entry);\n    }\n    return entry;\n}\n\n\nvoid*\n_Py_hashtable_steal(_Py_hashtable_t *ht, const void *key)\n{\n    Py_uhash_t key_hash = ht->hash_func(key);\n    size_t index = key_hash & (ht->nbuckets - 1);\n\n    _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, index);\n    _Py_hashtable_entry_t *previous = NULL;\n    while (1) {\n        if (entry == NULL) {\n            // not found\n            return NULL;\n        }\n        if (entry->key_hash == key_hash && ht->compare_func(key, entry->key)) {\n            break;\n        }\n        previous = entry;\n        entry = ENTRY_NEXT(entry);\n    }\n\n    _Py_slist_remove(&ht->buckets[index], (_Py_slist_item_t *)previous,\n                     (_Py_slist_item_t *)entry);\n    ht->nentries--;\n\n    void *value = entry->value;\n    ht->alloc.free(entry);\n\n    if ((float)ht->nentries / (float)ht->nbuckets < HASHTABLE_LOW) {\n        // Ignore failure: error cannot be reported to the caller\n        hashtable_rehash(ht);\n    }\n    return value;\n}\n\n\nint\n_Py_hashtable_set(_Py_hashtable_t *ht, const void *key, void *value)\n{\n    _Py_hashtable_entry_t *entry;\n\n#ifndef NDEBUG\n    /* Don't write the assertion on a single line because it is interesting\n       to know the duplicated entry if the assertion failed. The entry can\n       be read using a debugger. */\n    entry = ht->get_entry_func(ht, key);\n    assert(entry == NULL);\n#endif\n\n\n    entry = ht->alloc.malloc(sizeof(_Py_hashtable_entry_t));\n    if (entry == NULL) {\n        /* memory allocation failed */\n        return -1;\n    }\n\n    entry->key_hash = ht->hash_func(key);\n    entry->key = (void *)key;\n    entry->value = value;\n\n    ht->nentries++;\n    if ((float)ht->nentries / (float)ht->nbuckets > HASHTABLE_HIGH) {\n        if (hashtable_rehash(ht) < 0) {\n            ht->nentries--;\n            ht->alloc.free(entry);\n            return -1;\n        }\n    }\n\n    size_t index = entry->key_hash & (ht->nbuckets - 1);\n    _Py_slist_prepend(&ht->buckets[index], (_Py_slist_item_t*)entry);\n    return 0;\n}\n\n\nvoid*\n_Py_hashtable_get(_Py_hashtable_t *ht, const void *key)\n{\n    _Py_hashtable_entry_t *entry = ht->get_entry_func(ht, key);\n    if (entry != NULL) {\n        return entry->value;\n    }\n    else {\n        return NULL;\n    }\n}\n\n\nint\n_Py_hashtable_foreach(_Py_hashtable_t *ht,\n                      _Py_hashtable_foreach_func func,\n                      void *user_data)\n{\n    for (size_t hv = 0; hv < ht->nbuckets; hv++) {\n        _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, hv);\n        while (entry != NULL) {\n            int res = func(ht, entry->key, entry->value, user_data);\n            if (res) {\n                return res;\n            }\n            entry = ENTRY_NEXT(entry);\n        }\n    }\n    return 0;\n}\n\n\nstatic int\nhashtable_rehash(_Py_hashtable_t *ht)\n{\n    size_t new_size = round_size((size_t)(ht->nentries * HASHTABLE_REHASH_FACTOR));\n    if (new_size == ht->nbuckets) {\n        return 0;\n    }\n\n    size_t buckets_size = new_size * sizeof(ht->buckets[0]);\n    _Py_slist_t *new_buckets = ht->alloc.malloc(buckets_size);\n    if (new_buckets == NULL) {\n        /* memory allocation failed */\n        return -1;\n    }\n    memset(new_buckets, 0, buckets_size);\n\n    for (size_t bucket = 0; bucket < ht->nbuckets; bucket++) {\n        _Py_hashtable_entry_t *entry = BUCKETS_HEAD(ht->buckets[bucket]);\n        while (entry != NULL) {\n            assert(ht->hash_func(entry->key) == entry->key_hash);\n            _Py_hashtable_entry_t *next = ENTRY_NEXT(entry);\n            size_t entry_index = entry->key_hash & (new_size - 1);\n\n            _Py_slist_prepend(&new_buckets[entry_index], (_Py_slist_item_t*)entry);\n\n            entry = next;\n        }\n    }\n\n    ht->alloc.free(ht->buckets);\n    ht->nbuckets = new_size;\n    ht->buckets = new_buckets;\n    return 0;\n}\n\n\n_Py_hashtable_t *\n_Py_hashtable_new_full(_Py_hashtable_hash_func hash_func,\n                       _Py_hashtable_compare_func compare_func,\n                       _Py_hashtable_destroy_func key_destroy_func,\n                       _Py_hashtable_destroy_func value_destroy_func,\n                       _Py_hashtable_allocator_t *allocator)\n{\n    _Py_hashtable_allocator_t alloc;\n    if (allocator == NULL) {\n        alloc.malloc = PyMem_Malloc;\n        alloc.free = PyMem_Free;\n    }\n    else {\n        alloc = *allocator;\n    }\n\n    _Py_hashtable_t *ht = (_Py_hashtable_t *)alloc.malloc(sizeof(_Py_hashtable_t));\n    if (ht == NULL) {\n        return ht;\n    }\n\n    ht->nbuckets = HASHTABLE_MIN_SIZE;\n    ht->nentries = 0;\n\n    size_t buckets_size = ht->nbuckets * sizeof(ht->buckets[0]);\n    ht->buckets = alloc.malloc(buckets_size);\n    if (ht->buckets == NULL) {\n        alloc.free(ht);\n        return NULL;\n    }\n    memset(ht->buckets, 0, buckets_size);\n\n    ht->get_entry_func = _Py_hashtable_get_entry_generic;\n    ht->hash_func = hash_func;\n    ht->compare_func = compare_func;\n    ht->key_destroy_func = key_destroy_func;\n    ht->value_destroy_func = value_destroy_func;\n    ht->alloc = alloc;\n    if (ht->hash_func == _Py_hashtable_hash_ptr\n        && ht->compare_func == _Py_hashtable_compare_direct)\n    {\n        ht->get_entry_func = _Py_hashtable_get_entry_ptr;\n    }\n    return ht;\n}\n\n\n_Py_hashtable_t *\n_Py_hashtable_new(_Py_hashtable_hash_func hash_func,\n                  _Py_hashtable_compare_func compare_func)\n{\n    return _Py_hashtable_new_full(hash_func, compare_func,\n                                  NULL, NULL, NULL);\n}\n\n\nstatic void\n_Py_hashtable_destroy_entry(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry)\n{\n    if (ht->key_destroy_func) {\n        ht->key_destroy_func(entry->key);\n    }\n    if (ht->value_destroy_func) {\n        ht->value_destroy_func(entry->value);\n    }\n    ht->alloc.free(entry);\n}\n\n\nvoid\n_Py_hashtable_clear(_Py_hashtable_t *ht)\n{\n    for (size_t i=0; i < ht->nbuckets; i++) {\n        _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, i);\n        while (entry != NULL) {\n            _Py_hashtable_entry_t *next = ENTRY_NEXT(entry);\n            _Py_hashtable_destroy_entry(ht, entry);\n            entry = next;\n        }\n        _Py_slist_init(&ht->buckets[i]);\n    }\n    ht->nentries = 0;\n    // Ignore failure: clear function is not expected to fail\n    // because of a memory allocation failure.\n    (void)hashtable_rehash(ht);\n}\n\n\nvoid\n_Py_hashtable_destroy(_Py_hashtable_t *ht)\n{\n    for (size_t i = 0; i < ht->nbuckets; i++) {\n        _Py_hashtable_entry_t *entry = TABLE_HEAD(ht, i);\n        while (entry) {\n            _Py_hashtable_entry_t *entry_next = ENTRY_NEXT(entry);\n            _Py_hashtable_destroy_entry(ht, entry);\n            entry = entry_next;\n        }\n    }\n\n    ht->alloc.free(ht->buckets);\n    ht->alloc.free(ht);\n}\n"
  },
  {
    "path": "ImPort.c",
    "content": "/* Module definition and import implementation */\n\n#include \"Python.h\"\n\n#include \"pycore_import.h\"        // _PyImport_BootstrapImp()\n#include \"pycore_initconfig.h\"    // _PyStatus_OK()\n#include \"pycore_interp.h\"        // struct _import_runtime_state\n#include \"pycore_namespace.h\"     // _PyNamespace_Type\n#include \"pycore_pyerrors.h\"      // _PyErr_SetString()\n#include \"pycore_pyhash.h\"        // _Py_KeyedHash()\n#include \"pycore_pylifecycle.h\"\n#include \"pycore_pymem.h\"         // _PyMem_SetDefaultAllocator()\n#include \"pycore_pystate.h\"       // _PyInterpreterState_GET()\n#include \"pycore_sysmodule.h\"     // _PySys_Audit()\n#include \"marshal.h\"              // PyMarshal_ReadObjectFromString()\n#include \"importdl.h\"             // _PyImport_DynLoadFiletab\n#include \"pydtrace.h\"             // PyDTrace_IMPORT_FIND_LOAD_START_ENABLED()\n#include <stdbool.h>              // bool\n\n#ifdef HAVE_FCNTL_H\n#include <fcntl.h>\n#endif\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n/*[clinic input]\nmodule _imp\n[clinic start generated code]*/\n/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9c332475d8686284]*/\n\n#include \"clinic/import.c.h\"\n\n\n/*******************************/\n/* process-global import state */\n/*******************************/\n\n/* This table is defined in config.c: */\nextern struct _inittab _PyImport_Inittab[];\n\n// This is not used after Py_Initialize() is called.\n// (See _PyRuntimeState.imports.inittab.)\nstruct _inittab *PyImport_Inittab = _PyImport_Inittab;\n// When we dynamically allocate a larger table for PyImport_ExtendInittab(),\n// we track the pointer here so we can deallocate it during finalization.\nstatic struct _inittab *inittab_copy = NULL;\n\n\n/*******************************/\n/* runtime-global import state */\n/*******************************/\n\n#define INITTAB _PyRuntime.imports.inittab\n#define LAST_MODULE_INDEX _PyRuntime.imports.last_module_index\n#define EXTENSIONS _PyRuntime.imports.extensions\n\n#define PKGCONTEXT (_PyRuntime.imports.pkgcontext)\n\n\n/*******************************/\n/* interpreter import state */\n/*******************************/\n\n#define MODULES(interp) \\\n    (interp)->imports.modules\n#define MODULES_BY_INDEX(interp) \\\n    (interp)->imports.modules_by_index\n#define IMPORTLIB(interp) \\\n    (interp)->imports.importlib\n#define OVERRIDE_MULTI_INTERP_EXTENSIONS_CHECK(interp) \\\n    (interp)->imports.override_multi_interp_extensions_check\n#define OVERRIDE_FROZEN_MODULES(interp) \\\n    (interp)->imports.override_frozen_modules\n#ifdef HAVE_DLOPEN\n#  define DLOPENFLAGS(interp) \\\n        (interp)->imports.dlopenflags\n#endif\n#define IMPORT_FUNC(interp) \\\n    (interp)->imports.import_func\n\n#define IMPORT_LOCK(interp) \\\n    (interp)->imports.lock.mutex\n#define IMPORT_LOCK_THREAD(interp) \\\n    (interp)->imports.lock.thread\n#define IMPORT_LOCK_LEVEL(interp) \\\n    (interp)->imports.lock.level\n\n#define FIND_AND_LOAD(interp) \\\n    (interp)->imports.find_and_load\n\n\n/*******************/\n/* the import lock */\n/*******************/\n\n/* Locking primitives to prevent parallel imports of the same module\n   in different threads to return with a partially loaded module.\n   These calls are serialized by the global interpreter lock. */\n\nvoid\n_PyImport_AcquireLock(PyInterpreterState *interp)\n{\n    unsigned long me = PyThread_get_thread_ident();\n    if (me == PYTHREAD_INVALID_THREAD_ID)\n        return; /* Too bad */\n    if (IMPORT_LOCK(interp) == NULL) {\n        IMPORT_LOCK(interp) = PyThread_allocate_lock();\n        if (IMPORT_LOCK(interp) == NULL)\n            return;  /* Nothing much we can do. */\n    }\n    if (IMPORT_LOCK_THREAD(interp) == me) {\n        IMPORT_LOCK_LEVEL(interp)++;\n        return;\n    }\n    if (IMPORT_LOCK_THREAD(interp) != PYTHREAD_INVALID_THREAD_ID ||\n        !PyThread_acquire_lock(IMPORT_LOCK(interp), 0))\n    {\n        PyThreadState *tstate = PyEval_SaveThread();\n        PyThread_acquire_lock(IMPORT_LOCK(interp), WAIT_LOCK);\n        PyEval_RestoreThread(tstate);\n    }\n    assert(IMPORT_LOCK_LEVEL(interp) == 0);\n    IMPORT_LOCK_THREAD(interp) = me;\n    IMPORT_LOCK_LEVEL(interp) = 1;\n}\n\nint\n_PyImport_ReleaseLock(PyInterpreterState *interp)\n{\n    unsigned long me = PyThread_get_thread_ident();\n    if (me == PYTHREAD_INVALID_THREAD_ID || IMPORT_LOCK(interp) == NULL)\n        return 0; /* Too bad */\n    if (IMPORT_LOCK_THREAD(interp) != me)\n        return -1;\n    IMPORT_LOCK_LEVEL(interp)--;\n    assert(IMPORT_LOCK_LEVEL(interp) >= 0);\n    if (IMPORT_LOCK_LEVEL(interp) == 0) {\n        IMPORT_LOCK_THREAD(interp) = PYTHREAD_INVALID_THREAD_ID;\n        PyThread_release_lock(IMPORT_LOCK(interp));\n    }\n    return 1;\n}\n\n#ifdef HAVE_FORK\n/* This function is called from PyOS_AfterFork_Child() to ensure that newly\n   created child processes do not share locks with the parent.\n   We now acquire the import lock around fork() calls but on some platforms\n   (Solaris 9 and earlier? see isue7242) that still left us with problems. */\nPyStatus\n_PyImport_ReInitLock(PyInterpreterState *interp)\n{\n    if (IMPORT_LOCK(interp) != NULL) {\n        if (_PyThread_at_fork_reinit(&IMPORT_LOCK(interp)) < 0) {\n            return _PyStatus_ERR(\"failed to create a new lock\");\n        }\n    }\n\n    if (IMPORT_LOCK_LEVEL(interp) > 1) {\n        /* Forked as a side effect of import */\n        unsigned long me = PyThread_get_thread_ident();\n        PyThread_acquire_lock(IMPORT_LOCK(interp), WAIT_LOCK);\n        IMPORT_LOCK_THREAD(interp) = me;\n        IMPORT_LOCK_LEVEL(interp)--;\n    } else {\n        IMPORT_LOCK_THREAD(interp) = PYTHREAD_INVALID_THREAD_ID;\n        IMPORT_LOCK_LEVEL(interp) = 0;\n    }\n    return _PyStatus_OK();\n}\n#endif\n\n\n/***************/\n/* sys.modules */\n/***************/\n\nPyObject *\n_PyImport_InitModules(PyInterpreterState *interp)\n{\n    assert(MODULES(interp) == NULL);\n    MODULES(interp) = PyDict_New();\n    if (MODULES(interp) == NULL) {\n        return NULL;\n    }\n    return MODULES(interp);\n}\n\nPyObject *\n_PyImport_GetModules(PyInterpreterState *interp)\n{\n    return MODULES(interp);\n}\n\nvoid\n_PyImport_ClearModules(PyInterpreterState *interp)\n{\n    Py_SETREF(MODULES(interp), NULL);\n}\n\nPyObject *\nPyImport_GetModuleDict(void)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (MODULES(interp) == NULL) {\n        Py_FatalError(\"interpreter has no modules dictionary\");\n    }\n    return MODULES(interp);\n}\n\n// This is only kept around for extensions that use _Py_IDENTIFIER.\nPyObject *\n_PyImport_GetModuleId(_Py_Identifier *nameid)\n{\n    PyObject *name = _PyUnicode_FromId(nameid); /* borrowed */\n    if (name == NULL) {\n        return NULL;\n    }\n    return PyImport_GetModule(name);\n}\n\nint\n_PyImport_SetModule(PyObject *name, PyObject *m)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    PyObject *modules = MODULES(interp);\n    return PyObject_SetItem(modules, name, m);\n}\n\nint\n_PyImport_SetModuleString(const char *name, PyObject *m)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    PyObject *modules = MODULES(interp);\n    return PyMapping_SetItemString(modules, name, m);\n}\n\nstatic PyObject *\nimport_get_module(PyThreadState *tstate, PyObject *name)\n{\n    PyObject *modules = MODULES(tstate->interp);\n    if (modules == NULL) {\n        _PyErr_SetString(tstate, PyExc_RuntimeError,\n                         \"unable to get sys.modules\");\n        return NULL;\n    }\n\n    PyObject *m;\n    Py_INCREF(modules);\n    if (PyDict_CheckExact(modules)) {\n        m = PyDict_GetItemWithError(modules, name);  /* borrowed */\n        Py_XINCREF(m);\n    }\n    else {\n        m = PyObject_GetItem(modules, name);\n        if (m == NULL && _PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n            _PyErr_Clear(tstate);\n        }\n    }\n    Py_DECREF(modules);\n    return m;\n}\n\nstatic int\nimport_ensure_initialized(PyInterpreterState *interp, PyObject *mod, PyObject *name)\n{\n    PyObject *spec;\n\n    /* Optimization: only call _bootstrap._lock_unlock_module() if\n       __spec__._initializing is true.\n       NOTE: because of this, initializing must be set *before*\n       stuffing the new module in sys.modules.\n    */\n    spec = PyObject_GetAttr(mod, &_Py_ID(__spec__));\n    int busy = _PyModuleSpec_IsInitializing(spec);\n    Py_XDECREF(spec);\n    if (busy) {\n        /* Wait until module is done importing. */\n        PyObject *value = _PyObject_CallMethodOneArg(\n            IMPORTLIB(interp), &_Py_ID(_lock_unlock_module), name);\n        if (value == NULL) {\n            return -1;\n        }\n        Py_DECREF(value);\n    }\n    return 0;\n}\n\nstatic void remove_importlib_frames(PyThreadState *tstate);\n\nPyObject *\nPyImport_GetModule(PyObject *name)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *mod;\n\n    mod = import_get_module(tstate, name);\n    if (mod != NULL && mod != Py_None) {\n        if (import_ensure_initialized(tstate->interp, mod, name) < 0) {\n            Py_DECREF(mod);\n            remove_importlib_frames(tstate);\n            return NULL;\n        }\n    }\n    return mod;\n}\n\n/* Get the module object corresponding to a module name.\n   First check the modules dictionary if there's one there,\n   if not, create a new one and insert it in the modules dictionary. */\n\nstatic PyObject *\nimport_add_module(PyThreadState *tstate, PyObject *name)\n{\n    PyObject *modules = MODULES(tstate->interp);\n    if (modules == NULL) {\n        _PyErr_SetString(tstate, PyExc_RuntimeError,\n                         \"no import module dictionary\");\n        return NULL;\n    }\n\n    PyObject *m;\n    if (PyDict_CheckExact(modules)) {\n        m = Py_XNewRef(PyDict_GetItemWithError(modules, name));\n    }\n    else {\n        m = PyObject_GetItem(modules, name);\n        // For backward-compatibility we copy the behavior\n        // of PyDict_GetItemWithError().\n        if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n            _PyErr_Clear(tstate);\n        }\n    }\n    if (_PyErr_Occurred(tstate)) {\n        return NULL;\n    }\n    if (m != NULL && PyModule_Check(m)) {\n        return m;\n    }\n    Py_XDECREF(m);\n    m = PyModule_NewObject(name);\n    if (m == NULL)\n        return NULL;\n    if (PyObject_SetItem(modules, name, m) != 0) {\n        Py_DECREF(m);\n        return NULL;\n    }\n\n    return m;\n}\n\nPyObject *\nPyImport_AddModuleObject(PyObject *name)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *mod = import_add_module(tstate, name);\n    if (mod) {\n        PyObject *ref = PyWeakref_NewRef(mod, NULL);\n        Py_DECREF(mod);\n        if (ref == NULL) {\n            return NULL;\n        }\n        mod = PyWeakref_GetObject(ref);\n        Py_DECREF(ref);\n    }\n    return mod; /* borrowed reference */\n}\n\n\nPyObject *\nPyImport_AddModule(const char *name)\n{\n    PyObject *nameobj = PyUnicode_FromString(name);\n    if (nameobj == NULL) {\n        return NULL;\n    }\n    PyObject *module = PyImport_AddModuleObject(nameobj);\n    Py_DECREF(nameobj);\n    return module;\n}\n\n\n/* Remove name from sys.modules, if it's there.\n * Can be called with an exception raised.\n * If fail to remove name a new exception will be chained with the old\n * exception, otherwise the old exception is preserved.\n */\nstatic void\nremove_module(PyThreadState *tstate, PyObject *name)\n{\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n\n    PyObject *modules = MODULES(tstate->interp);\n    if (PyDict_CheckExact(modules)) {\n        PyObject *mod = _PyDict_Pop(modules, name, Py_None);\n        Py_XDECREF(mod);\n    }\n    else if (PyMapping_DelItem(modules, name) < 0) {\n        if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {\n            _PyErr_Clear(tstate);\n        }\n    }\n\n    _PyErr_ChainExceptions1(exc);\n}\n\n\n/************************************/\n/* per-interpreter modules-by-index */\n/************************************/\n\nPy_ssize_t\n_PyImport_GetNextModuleIndex(void)\n{\n    PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK);\n    LAST_MODULE_INDEX++;\n    Py_ssize_t index = LAST_MODULE_INDEX;\n    PyThread_release_lock(EXTENSIONS.mutex);\n    return index;\n}\n\nstatic const char *\n_modules_by_index_check(PyInterpreterState *interp, Py_ssize_t index)\n{\n    if (index == 0) {\n        return \"invalid module index\";\n    }\n    if (MODULES_BY_INDEX(interp) == NULL) {\n        return \"Interpreters module-list not accessible.\";\n    }\n    if (index > PyList_GET_SIZE(MODULES_BY_INDEX(interp))) {\n        return \"Module index out of bounds.\";\n    }\n    return NULL;\n}\n\nstatic PyObject *\n_modules_by_index_get(PyInterpreterState *interp, PyModuleDef *def)\n{\n    Py_ssize_t index = def->m_base.m_index;\n    if (_modules_by_index_check(interp, index) != NULL) {\n        return NULL;\n    }\n    PyObject *res = PyList_GET_ITEM(MODULES_BY_INDEX(interp), index);\n    return res==Py_None ? NULL : res;\n}\n\nstatic int\n_modules_by_index_set(PyInterpreterState *interp,\n                      PyModuleDef *def, PyObject *module)\n{\n    assert(def != NULL);\n    assert(def->m_slots == NULL);\n    assert(def->m_base.m_index > 0);\n\n    if (MODULES_BY_INDEX(interp) == NULL) {\n        MODULES_BY_INDEX(interp) = PyList_New(0);\n        if (MODULES_BY_INDEX(interp) == NULL) {\n            return -1;\n        }\n    }\n\n    Py_ssize_t index = def->m_base.m_index;\n    while (PyList_GET_SIZE(MODULES_BY_INDEX(interp)) <= index) {\n        if (PyList_Append(MODULES_BY_INDEX(interp), Py_None) < 0) {\n            return -1;\n        }\n    }\n\n    return PyList_SetItem(MODULES_BY_INDEX(interp), index, Py_NewRef(module));\n}\n\nstatic int\n_modules_by_index_clear_one(PyInterpreterState *interp, PyModuleDef *def)\n{\n    Py_ssize_t index = def->m_base.m_index;\n    const char *err = _modules_by_index_check(interp, index);\n    if (err != NULL) {\n        Py_FatalError(err);\n        return -1;\n    }\n    return PyList_SetItem(MODULES_BY_INDEX(interp), index, Py_NewRef(Py_None));\n}\n\n\nPyObject*\nPyState_FindModule(PyModuleDef* module)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (module->m_slots) {\n        return NULL;\n    }\n    return _modules_by_index_get(interp, module);\n}\n\n/* _PyState_AddModule() has been completely removed from the C-API\n   (and was removed from the limited API in 3.6).  However, we're\n   playing it safe and keeping it around for any stable ABI extensions\n   built against 3.2-3.5. */\nint\n_PyState_AddModule(PyThreadState *tstate, PyObject* module, PyModuleDef* def)\n{\n    if (!def) {\n        assert(_PyErr_Occurred(tstate));\n        return -1;\n    }\n    if (def->m_slots) {\n        _PyErr_SetString(tstate,\n                         PyExc_SystemError,\n                         \"PyState_AddModule called on module with slots\");\n        return -1;\n    }\n    return _modules_by_index_set(tstate->interp, def, module);\n}\n\nint\nPyState_AddModule(PyObject* module, PyModuleDef* def)\n{\n    if (!def) {\n        Py_FatalError(\"module definition is NULL\");\n        return -1;\n    }\n\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (def->m_slots) {\n        _PyErr_SetString(tstate,\n                         PyExc_SystemError,\n                         \"PyState_AddModule called on module with slots\");\n        return -1;\n    }\n\n    PyInterpreterState *interp = tstate->interp;\n    Py_ssize_t index = def->m_base.m_index;\n    if (MODULES_BY_INDEX(interp) &&\n        index < PyList_GET_SIZE(MODULES_BY_INDEX(interp)) &&\n        module == PyList_GET_ITEM(MODULES_BY_INDEX(interp), index))\n    {\n        _Py_FatalErrorFormat(__func__, \"module %p already added\", module);\n        return -1;\n    }\n\n    return _modules_by_index_set(interp, def, module);\n}\n\nint\nPyState_RemoveModule(PyModuleDef* def)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (def->m_slots) {\n        _PyErr_SetString(tstate,\n                         PyExc_SystemError,\n                         \"PyState_RemoveModule called on module with slots\");\n        return -1;\n    }\n    return _modules_by_index_clear_one(tstate->interp, def);\n}\n\n\n// Used by finalize_modules()\nvoid\n_PyImport_ClearModulesByIndex(PyInterpreterState *interp)\n{\n    if (!MODULES_BY_INDEX(interp)) {\n        return;\n    }\n\n    Py_ssize_t i;\n    for (i = 0; i < PyList_GET_SIZE(MODULES_BY_INDEX(interp)); i++) {\n        PyObject *m = PyList_GET_ITEM(MODULES_BY_INDEX(interp), i);\n        if (PyModule_Check(m)) {\n            /* cleanup the saved copy of module dicts */\n            PyModuleDef *md = PyModule_GetDef(m);\n            if (md) {\n                Py_CLEAR(md->m_base.m_copy);\n            }\n        }\n    }\n\n    /* Setting modules_by_index to NULL could be dangerous, so we\n       clear the list instead. */\n    if (PyList_SetSlice(MODULES_BY_INDEX(interp),\n                        0, PyList_GET_SIZE(MODULES_BY_INDEX(interp)),\n                        NULL)) {\n        PyErr_WriteUnraisable(MODULES_BY_INDEX(interp));\n    }\n}\n\n\n/*********************/\n/* extension modules */\n/*********************/\n\n/*\n    It may help to have a big picture view of what happens\n    when an extension is loaded.  This includes when it is imported\n    for the first time.\n\n    Here's a summary, using importlib._boostrap._load() as a starting point.\n\n    1.  importlib._bootstrap._load()\n    2.    _load():  acquire import lock\n    3.    _load() -> importlib._bootstrap._load_unlocked()\n    4.      _load_unlocked() -> importlib._bootstrap.module_from_spec()\n    5.        module_from_spec() -> ExtensionFileLoader.create_module()\n    6.          create_module() -> _imp.create_dynamic()\n                    (see below)\n    7.        module_from_spec() -> importlib._bootstrap._init_module_attrs()\n    8.      _load_unlocked():  sys.modules[name] = module\n    9.      _load_unlocked() -> ExtensionFileLoader.exec_module()\n    10.       exec_module() -> _imp.exec_dynamic()\n                  (see below)\n    11.   _load():  release import lock\n\n\n    ...for single-phase init modules, where m_size == -1:\n\n    (6). first time  (not found in _PyRuntime.imports.extensions):\n       1.  _imp_create_dynamic_impl() -> import_find_extension()\n       2.  _imp_create_dynamic_impl() -> _PyImport_LoadDynamicModuleWithSpec()\n       3.    _PyImport_LoadDynamicModuleWithSpec():  load <module init func>\n       4.    _PyImport_LoadDynamicModuleWithSpec():  call <module init func>\n       5.      <module init func> -> PyModule_Create() -> PyModule_Create2() -> PyModule_CreateInitialized()\n       6.        PyModule_CreateInitialized() -> PyModule_New()\n       7.        PyModule_CreateInitialized():  allocate mod->md_state\n       8.        PyModule_CreateInitialized() -> PyModule_AddFunctions()\n       9.        PyModule_CreateInitialized() -> PyModule_SetDocString()\n       10.       PyModule_CreateInitialized():  set mod->md_def\n       11.     <module init func>:  initialize the module\n       12.   _PyImport_LoadDynamicModuleWithSpec() -> _PyImport_CheckSubinterpIncompatibleExtensionAllowed()\n       13.   _PyImport_LoadDynamicModuleWithSpec():  set def->m_base.m_init\n       14.   _PyImport_LoadDynamicModuleWithSpec():  set __file__\n       15.   _PyImport_LoadDynamicModuleWithSpec() -> _PyImport_FixupExtensionObject()\n       16.     _PyImport_FixupExtensionObject():  add it to interp->imports.modules_by_index\n       17.     _PyImport_FixupExtensionObject():  copy __dict__ into def->m_base.m_copy\n       18.     _PyImport_FixupExtensionObject():  add it to _PyRuntime.imports.extensions\n\n    (6). subsequent times  (found in _PyRuntime.imports.extensions):\n       1. _imp_create_dynamic_impl() -> import_find_extension()\n       2.   import_find_extension() -> import_add_module()\n       3.     if name in sys.modules:  use that module\n       4.     else:\n                1. import_add_module() -> PyModule_NewObject()\n                2. import_add_module():  set it on sys.modules\n       5.   import_find_extension():  copy the \"m_copy\" dict into __dict__\n       6. _imp_create_dynamic_impl() -> _PyImport_CheckSubinterpIncompatibleExtensionAllowed()\n\n    (10). (every time):\n       1. noop\n\n\n    ...for single-phase init modules, where m_size >= 0:\n\n    (6). not main interpreter and never loaded there - every time  (not found in _PyRuntime.imports.extensions):\n       1-16. (same as for m_size == -1)\n\n    (6). main interpreter - first time  (not found in _PyRuntime.imports.extensions):\n       1-16. (same as for m_size == -1)\n       17.     _PyImport_FixupExtensionObject():  add it to _PyRuntime.imports.extensions\n\n    (6). previously loaded in main interpreter  (found in _PyRuntime.imports.extensions):\n       1. _imp_create_dynamic_impl() -> import_find_extension()\n       2.   import_find_extension():  call def->m_base.m_init\n       3.   import_find_extension():  add the module to sys.modules\n\n    (10). every time:\n       1. noop\n\n\n    ...for multi-phase init modules:\n\n    (6). every time:\n       1.  _imp_create_dynamic_impl() -> import_find_extension()  (not found)\n       2.  _imp_create_dynamic_impl() -> _PyImport_LoadDynamicModuleWithSpec()\n       3.    _PyImport_LoadDynamicModuleWithSpec():  load module init func\n       4.    _PyImport_LoadDynamicModuleWithSpec():  call module init func\n       5.    _PyImport_LoadDynamicModuleWithSpec() -> PyModule_FromDefAndSpec()\n       6.      PyModule_FromDefAndSpec(): gather/check moduledef slots\n       7.      if there's a Py_mod_create slot:\n                 1. PyModule_FromDefAndSpec():  call its function\n       8.      else:\n                 1. PyModule_FromDefAndSpec() -> PyModule_NewObject()\n       9:      PyModule_FromDefAndSpec():  set mod->md_def\n       10.     PyModule_FromDefAndSpec() -> _add_methods_to_object()\n       11.     PyModule_FromDefAndSpec() -> PyModule_SetDocString()\n\n    (10). every time:\n       1. _imp_exec_dynamic_impl() -> exec_builtin_or_dynamic()\n       2.   if mod->md_state == NULL (including if m_size == 0):\n            1. exec_builtin_or_dynamic() -> PyModule_ExecDef()\n            2.   PyModule_ExecDef():  allocate mod->md_state\n            3.   if there's a Py_mod_exec slot:\n                 1. PyModule_ExecDef():  call its function\n */\n\n\n/* Make sure name is fully qualified.\n\n   This is a bit of a hack: when the shared library is loaded,\n   the module name is \"package.module\", but the module calls\n   PyModule_Create*() with just \"module\" for the name.  The shared\n   library loader squirrels away the true name of the module in\n   _PyRuntime.imports.pkgcontext, and PyModule_Create*() will\n   substitute this (if the name actually matches).\n*/\nconst char *\n_PyImport_ResolveNameWithPackageContext(const char *name)\n{\n    PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK);\n    if (PKGCONTEXT != NULL) {\n        const char *p = strrchr(PKGCONTEXT, '.');\n        if (p != NULL && strcmp(name, p+1) == 0) {\n            name = PKGCONTEXT;\n            PKGCONTEXT = NULL;\n        }\n    }\n    PyThread_release_lock(EXTENSIONS.mutex);\n    return name;\n}\n\nconst char *\n_PyImport_SwapPackageContext(const char *newcontext)\n{\n    PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK);\n    const char *oldcontext = PKGCONTEXT;\n    PKGCONTEXT = newcontext;\n    PyThread_release_lock(EXTENSIONS.mutex);\n    return oldcontext;\n}\n\n#ifdef HAVE_DLOPEN\nint\n_PyImport_GetDLOpenFlags(PyInterpreterState *interp)\n{\n    return DLOPENFLAGS(interp);\n}\n\nvoid\n_PyImport_SetDLOpenFlags(PyInterpreterState *interp, int new_val)\n{\n    DLOPENFLAGS(interp) = new_val;\n}\n#endif  // HAVE_DLOPEN\n\n\n/* Common implementation for _imp.exec_dynamic and _imp.exec_builtin */\nstatic int\nexec_builtin_or_dynamic(PyObject *mod) {\n    PyModuleDef *def;\n    void *state;\n\n    if (!PyModule_Check(mod)) {\n        return 0;\n    }\n\n    def = PyModule_GetDef(mod);\n    if (def == NULL) {\n        return 0;\n    }\n\n    state = PyModule_GetState(mod);\n    if (state) {\n        /* Already initialized; skip reload */\n        return 0;\n    }\n\n    return PyModule_ExecDef(mod, def);\n}\n\n\nstatic int clear_singlephase_extension(PyInterpreterState *interp,\n                                       PyObject *name, PyObject *filename);\n\n// Currently, this is only used for testing.\n// (See _testinternalcapi.clear_extension().)\nint\n_PyImport_ClearExtension(PyObject *name, PyObject *filename)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n\n    /* Clearing a module's C globals is up to the module. */\n    if (clear_singlephase_extension(interp, name, filename) < 0) {\n        return -1;\n    }\n\n    // In the future we'll probably also make sure the extension's\n    // file handle (and DL handle) is closed (requires saving it).\n\n    return 0;\n}\n\n\n/*******************/\n\n#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)\n#include <emscripten.h>\nEM_JS(PyObject*, _PyImport_InitFunc_TrampolineCall, (PyModInitFunction func), {\n    return wasmTable.get(func)();\n});\n#endif // __EMSCRIPTEN__ && PY_CALL_TRAMPOLINE\n\n\n/*****************************/\n/* single-phase init modules */\n/*****************************/\n\n/*\nWe support a number of kinds of single-phase init builtin/extension modules:\n\n* \"basic\"\n    * no module state (PyModuleDef.m_size == -1)\n    * does not support repeated init (we use PyModuleDef.m_base.m_copy)\n    * may have process-global state\n    * the module's def is cached in _PyRuntime.imports.extensions,\n      by (name, filename)\n* \"reinit\"\n    * no module state (PyModuleDef.m_size == 0)\n    * supports repeated init (m_copy is never used)\n    * should not have any process-global state\n    * its def is never cached in _PyRuntime.imports.extensions\n      (except, currently, under the main interpreter, for some reason)\n* \"with state\"  (almost the same as reinit)\n    * has module state (PyModuleDef.m_size > 0)\n    * supports repeated init (m_copy is never used)\n    * should not have any process-global state\n    * its def is never cached in _PyRuntime.imports.extensions\n      (except, currently, under the main interpreter, for some reason)\n\nThere are also variants within those classes:\n\n* two or more modules share a PyModuleDef\n    * a module's init func uses another module's PyModuleDef\n    * a module's init func calls another's module's init func\n    * a module's init \"func\" is actually a variable statically initialized\n      to another module's init func\n* two or modules share \"methods\"\n    * a module's init func copies another module's PyModuleDef\n      (with a different name)\n* (basic-only) two or modules share process-global state\n\nIn the first case, where modules share a PyModuleDef, the following\nnotable weirdness happens:\n\n* the module's __name__ matches the def, not the requested name\n* the last module (with the same def) to be imported for the first time wins\n    * returned by PyState_Find_Module() (via interp->modules_by_index)\n    * (non-basic-only) its init func is used when re-loading any of them\n      (via the def's m_init)\n    * (basic-only) the copy of its __dict__ is used when re-loading any of them\n      (via the def's m_copy)\n\nHowever, the following happens as expected:\n\n* a new module object (with its own __dict__) is created for each request\n* the module's __spec__ has the requested name\n* the loaded module is cached in sys.modules under the requested name\n* the m_index field of the shared def is not changed,\n  so at least PyState_FindModule() will always look in the same place\n\nFor \"basic\" modules there are other quirks:\n\n* (whether sharing a def or not) when loaded the first time,\n  m_copy is set before _init_module_attrs() is called\n  in importlib._bootstrap.module_from_spec(),\n  so when the module is re-loaded, the previous value\n  for __wpec__ (and others) is reset, possibly unexpectedly.\n\nGenerally, when multiple interpreters are involved, some of the above\ngets even messier.\n*/\n\nstatic inline void\nextensions_lock_acquire(void)\n{\n    PyThread_acquire_lock(_PyRuntime.imports.extensions.mutex, WAIT_LOCK);\n}\n\nstatic inline void\nextensions_lock_release(void)\n{\n    PyThread_release_lock(_PyRuntime.imports.extensions.mutex);\n}\n\n/* Magic for extension modules (built-in as well as dynamically\n   loaded).  To prevent initializing an extension module more than\n   once, we keep a static dictionary 'extensions' keyed by the tuple\n   (module name, module name)  (for built-in modules) or by\n   (filename, module name) (for dynamically loaded modules), containing these\n   modules.  A copy of the module's dictionary is stored by calling\n   _PyImport_FixupExtensionObject() immediately after the module initialization\n   function succeeds.  A copy can be retrieved from there by calling\n   import_find_extension().\n\n   Modules which do support multiple initialization set their m_size\n   field to a non-negative number (indicating the size of the\n   module-specific state). They are still recorded in the extensions\n   dictionary, to avoid loading shared libraries twice.\n*/\n\nstatic void\n_extensions_cache_init(void)\n{\n    /* The runtime (i.e. main interpreter) must be initializing,\n       so we don't need to worry about the lock. */\n    _PyThreadState_InitDetached(&EXTENSIONS.main_tstate,\n                                _PyInterpreterState_Main());\n}\n\nstatic PyModuleDef *\n_extensions_cache_get(PyObject *filename, PyObject *name)\n{\n    PyModuleDef *def = NULL;\n    extensions_lock_acquire();\n\n    PyObject *key = PyTuple_Pack(2, filename, name);\n    if (key == NULL) {\n        goto finally;\n    }\n\n    PyObject *extensions = EXTENSIONS.dict;\n    if (extensions == NULL) {\n        goto finally;\n    }\n    def = (PyModuleDef *)PyDict_GetItemWithError(extensions, key);\n\nfinally:\n    Py_XDECREF(key);\n    extensions_lock_release();\n    return def;\n}\n\nstatic int\n_extensions_cache_set(PyObject *filename, PyObject *name, PyModuleDef *def)\n{\n    int res = -1;\n    PyThreadState *oldts = NULL;\n    extensions_lock_acquire();\n\n    /* Swap to the main interpreter, if necessary.  This matters if\n       the dict hasn't been created yet or if the item isn't in the\n       dict yet.  In both cases we must ensure the relevant objects\n       are created using the main interpreter. */\n    PyThreadState *main_tstate = &EXTENSIONS.main_tstate;\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (!_Py_IsMainInterpreter(interp)) {\n        _PyThreadState_BindDetached(main_tstate);\n        oldts = _PyThreadState_Swap(interp->runtime, main_tstate);\n        assert(!_Py_IsMainInterpreter(oldts->interp));\n\n        /* Make sure the name and filename objects are owned\n           by the main interpreter. */\n        name = PyUnicode_InternFromString(PyUnicode_AsUTF8(name));\n        assert(name != NULL);\n        filename = PyUnicode_InternFromString(PyUnicode_AsUTF8(filename));\n        assert(filename != NULL);\n    }\n\n    PyObject *key = PyTuple_Pack(2, filename, name);\n    if (key == NULL) {\n        goto finally;\n    }\n\n    PyObject *extensions = EXTENSIONS.dict;\n    if (extensions == NULL) {\n        extensions = PyDict_New();\n        if (extensions == NULL) {\n            goto finally;\n        }\n        EXTENSIONS.dict = extensions;\n    }\n\n    PyModuleDef *actual = (PyModuleDef *)PyDict_GetItemWithError(extensions, key);\n    if (PyErr_Occurred()) {\n        goto finally;\n    }\n    else if (actual != NULL) {\n        /* We expect it to be static, so it must be the same pointer. */\n        assert(def == actual);\n        res = 0;\n        goto finally;\n    }\n\n    /* This might trigger a resize, which is why we must switch\n       to the main interpreter. */\n    res = PyDict_SetItem(extensions, key, (PyObject *)def);\n    if (res < 0) {\n        res = -1;\n        goto finally;\n    }\n    res = 0;\n\nfinally:\n    Py_XDECREF(key);\n    if (oldts != NULL) {\n        _PyThreadState_Swap(interp->runtime, oldts);\n        _PyThreadState_UnbindDetached(main_tstate);\n        Py_DECREF(name);\n        Py_DECREF(filename);\n    }\n    extensions_lock_release();\n    return res;\n}\n\nstatic int\n_extensions_cache_delete(PyObject *filename, PyObject *name)\n{\n    int res = -1;\n    PyThreadState *oldts = NULL;\n    extensions_lock_acquire();\n\n    PyObject *key = PyTuple_Pack(2, filename, name);\n    if (key == NULL) {\n        goto finally;\n    }\n\n    PyObject *extensions = EXTENSIONS.dict;\n    if (extensions == NULL) {\n        res = 0;\n        goto finally;\n    }\n\n    PyModuleDef *actual = (PyModuleDef *)PyDict_GetItemWithError(extensions, key);\n    if (PyErr_Occurred()) {\n        goto finally;\n    }\n    else if (actual == NULL) {\n        /* It was already removed or never added. */\n        res = 0;\n        goto finally;\n    }\n\n    /* Swap to the main interpreter, if necessary. */\n    PyThreadState *main_tstate = &EXTENSIONS.main_tstate;\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (!_Py_IsMainInterpreter(interp)) {\n        _PyThreadState_BindDetached(main_tstate);\n        oldts = _PyThreadState_Swap(interp->runtime, main_tstate);\n        assert(!_Py_IsMainInterpreter(oldts->interp));\n    }\n\n    if (PyDict_DelItem(extensions, key) < 0) {\n        goto finally;\n    }\n    res = 0;\n\nfinally:\n    if (oldts != NULL) {\n        _PyThreadState_Swap(interp->runtime, oldts);\n        _PyThreadState_UnbindDetached(main_tstate);\n    }\n    Py_XDECREF(key);\n    extensions_lock_release();\n    return res;\n}\n\nstatic void\n_extensions_cache_clear_all(void)\n{\n    /* The runtime (i.e. main interpreter) must be finalizing,\n       so we don't need to worry about the lock. */\n    // XXX assert(_Py_IsMainInterpreter(_PyInterpreterState_GET()));\n    Py_CLEAR(EXTENSIONS.dict);\n    _PyThreadState_ClearDetached(&EXTENSIONS.main_tstate);\n}\n\n\nstatic bool\ncheck_multi_interp_extensions(PyInterpreterState *interp)\n{\n    int override = OVERRIDE_MULTI_INTERP_EXTENSIONS_CHECK(interp);\n    if (override < 0) {\n        return false;\n    }\n    else if (override > 0) {\n        return true;\n    }\n    else if (_PyInterpreterState_HasFeature(\n                interp, Py_RTFLAGS_MULTI_INTERP_EXTENSIONS)) {\n        return true;\n    }\n    return false;\n}\n\nint\n_PyImport_CheckSubinterpIncompatibleExtensionAllowed(const char *name)\n{\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    if (check_multi_interp_extensions(interp)) {\n        assert(!_Py_IsMainInterpreter(interp));\n        PyErr_Format(PyExc_ImportError,\n                     \"module %s does not support loading in subinterpreters\",\n                     name);\n        return -1;\n    }\n    return 0;\n}\n\nstatic PyObject *\nget_core_module_dict(PyInterpreterState *interp,\n                     PyObject *name, PyObject *filename)\n{\n    /* Only builtin modules are core. */\n    if (filename == name) {\n        assert(!PyErr_Occurred());\n        if (PyUnicode_CompareWithASCIIString(name, \"sys\") == 0) {\n            return interp->sysdict_copy;\n        }\n        assert(!PyErr_Occurred());\n        if (PyUnicode_CompareWithASCIIString(name, \"builtins\") == 0) {\n            return interp->builtins_copy;\n        }\n        assert(!PyErr_Occurred());\n    }\n    return NULL;\n}\n\nstatic inline int\nis_core_module(PyInterpreterState *interp, PyObject *name, PyObject *filename)\n{\n    /* This might be called before the core dict copies are in place,\n       so we can't rely on get_core_module_dict() here. */\n    if (filename == name) {\n        if (PyUnicode_CompareWithASCIIString(name, \"sys\") == 0) {\n            return 1;\n        }\n        if (PyUnicode_CompareWithASCIIString(name, \"builtins\") == 0) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\nstatic int\nfix_up_extension(PyObject *mod, PyObject *name, PyObject *filename)\n{\n    if (mod == NULL || !PyModule_Check(mod)) {\n        PyErr_BadInternalCall();\n        return -1;\n    }\n\n    struct PyModuleDef *def = PyModule_GetDef(mod);\n    if (!def) {\n        PyErr_BadInternalCall();\n        return -1;\n    }\n\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (_modules_by_index_set(tstate->interp, def, mod) < 0) {\n        return -1;\n    }\n\n    // bpo-44050: Extensions and def->m_base.m_copy can be updated\n    // when the extension module doesn't support sub-interpreters.\n    if (def->m_size == -1) {\n        if (!is_core_module(tstate->interp, name, filename)) {\n            assert(PyUnicode_CompareWithASCIIString(name, \"sys\") != 0);\n            assert(PyUnicode_CompareWithASCIIString(name, \"builtins\") != 0);\n            if (def->m_base.m_copy) {\n                /* Somebody already imported the module,\n                   likely under a different name.\n                   XXX this should really not happen. */\n                Py_CLEAR(def->m_base.m_copy);\n            }\n            PyObject *dict = PyModule_GetDict(mod);\n            if (dict == NULL) {\n                return -1;\n            }\n            def->m_base.m_copy = PyDict_Copy(dict);\n            if (def->m_base.m_copy == NULL) {\n                return -1;\n            }\n        }\n    }\n\n    // XXX Why special-case the main interpreter?\n    if (_Py_IsMainInterpreter(tstate->interp) || def->m_size == -1) {\n        if (_extensions_cache_set(filename, name, def) < 0) {\n            return -1;\n        }\n    }\n\n    return 0;\n}\n\nint\n_PyImport_FixupExtensionObject(PyObject *mod, PyObject *name,\n                               PyObject *filename, PyObject *modules)\n{\n    if (PyObject_SetItem(modules, name, mod) < 0) {\n        return -1;\n    }\n    if (fix_up_extension(mod, name, filename) < 0) {\n        PyMapping_DelItem(modules, name);\n        return -1;\n    }\n    return 0;\n}\n\n\nstatic PyObject *\nimport_find_extension(PyThreadState *tstate, PyObject *name,\n                      PyObject *filename)\n{\n    /* Only single-phase init modules will be in the cache. */\n    PyModuleDef *def = _extensions_cache_get(filename, name);\n    if (def == NULL) {\n        return NULL;\n    }\n\n    PyObject *mod, *mdict;\n    PyObject *modules = MODULES(tstate->interp);\n\n    if (def->m_size == -1) {\n        PyObject *m_copy = def->m_base.m_copy;\n        /* Module does not support repeated initialization */\n        if (m_copy == NULL) {\n            m_copy = get_core_module_dict(tstate->interp, name, filename);\n            if (m_copy == NULL) {\n                return NULL;\n            }\n        }\n        mod = import_add_module(tstate, name);\n        if (mod == NULL) {\n            return NULL;\n        }\n        mdict = PyModule_GetDict(mod);\n        if (mdict == NULL) {\n            Py_DECREF(mod);\n            return NULL;\n        }\n        if (PyDict_Update(mdict, m_copy)) {\n            Py_DECREF(mod);\n            return NULL;\n        }\n    }\n    else {\n        if (def->m_base.m_init == NULL)\n            return NULL;\n        mod = _PyImport_InitFunc_TrampolineCall(def->m_base.m_init);\n        if (mod == NULL)\n            return NULL;\n        if (PyObject_SetItem(modules, name, mod) == -1) {\n            Py_DECREF(mod);\n            return NULL;\n        }\n    }\n    if (_modules_by_index_set(tstate->interp, def, mod) < 0) {\n        PyMapping_DelItem(modules, name);\n        Py_DECREF(mod);\n        return NULL;\n    }\n\n    int verbose = _PyInterpreterState_GetConfig(tstate->interp)->verbose;\n    if (verbose) {\n        PySys_FormatStderr(\"import %U # previously loaded (%R)\\n\",\n                           name, filename);\n    }\n    return mod;\n}\n\nstatic int\nclear_singlephase_extension(PyInterpreterState *interp,\n                            PyObject *name, PyObject *filename)\n{\n    PyModuleDef *def = _extensions_cache_get(filename, name);\n    if (def == NULL) {\n        if (PyErr_Occurred()) {\n            return -1;\n        }\n        return 0;\n    }\n\n    /* Clear data set when the module was initially loaded. */\n    def->m_base.m_init = NULL;\n    Py_CLEAR(def->m_base.m_copy);\n    // We leave m_index alone since there's no reason to reset it.\n\n    /* Clear the PyState_*Module() cache entry. */\n    if (_modules_by_index_check(interp, def->m_base.m_index) == NULL) {\n        if (_modules_by_index_clear_one(interp, def) < 0) {\n            return -1;\n        }\n    }\n\n    /* Clear the cached module def. */\n    if (_extensions_cache_delete(filename, name) < 0) {\n        return -1;\n    }\n\n    return 0;\n}\n\n\n/*******************/\n/* builtin modules */\n/*******************/\n\nint\n_PyImport_FixupBuiltin(PyObject *mod, const char *name, PyObject *modules)\n{\n    int res = -1;\n    PyObject *nameobj;\n    nameobj = PyUnicode_InternFromString(name);\n    if (nameobj == NULL) {\n        return -1;\n    }\n    if (PyObject_SetItem(modules, nameobj, mod) < 0) {\n        goto finally;\n    }\n    if (fix_up_extension(mod, nameobj, nameobj) < 0) {\n        PyMapping_DelItem(modules, nameobj);\n        goto finally;\n    }\n    res = 0;\n\nfinally:\n    Py_DECREF(nameobj);\n    return res;\n}\n\n/* Helper to test for built-in module */\n\nstatic int\nis_builtin(PyObject *name)\n{\n    int i;\n    struct _inittab *inittab = INITTAB;\n    for (i = 0; inittab[i].name != NULL; i++) {\n        if (_PyUnicode_EqualToASCIIString(name, inittab[i].name)) {\n            if (inittab[i].initfunc == NULL)\n                return -1;\n            else\n                return 1;\n        }\n    }\n    return 0;\n}\n\nstatic PyObject*\ncreate_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)\n{\n    PyObject *mod = import_find_extension(tstate, name, name);\n    if (mod || _PyErr_Occurred(tstate)) {\n        return mod;\n    }\n\n    PyObject *modules = MODULES(tstate->interp);\n    for (struct _inittab *p = INITTAB; p->name != NULL; p++) {\n        if (_PyUnicode_EqualToASCIIString(name, p->name)) {\n            if (p->initfunc == NULL) {\n                /* Cannot re-init internal module (\"sys\" or \"builtins\") */\n                mod = PyImport_AddModuleObject(name);\n                return Py_XNewRef(mod);\n            }\n            mod = _PyImport_InitFunc_TrampolineCall(*p->initfunc);\n            if (mod == NULL) {\n                return NULL;\n            }\n\n            if (PyObject_TypeCheck(mod, &PyModuleDef_Type)) {\n                return PyModule_FromDefAndSpec((PyModuleDef*)mod, spec);\n            }\n            else {\n                /* Remember pointer to module init function. */\n                PyModuleDef *def = PyModule_GetDef(mod);\n                if (def == NULL) {\n                    return NULL;\n                }\n\n                def->m_base.m_init = p->initfunc;\n                if (_PyImport_FixupExtensionObject(mod, name, name,\n                                                   modules) < 0) {\n                    return NULL;\n                }\n                return mod;\n            }\n        }\n    }\n\n    // not found\n    Py_RETURN_NONE;\n}\n\n\n/*****************************/\n/* the builtin modules table */\n/*****************************/\n\n/* API for embedding applications that want to add their own entries\n   to the table of built-in modules.  This should normally be called\n   *before* Py_Initialize().  When the table resize fails, -1 is\n   returned and the existing table is unchanged.\n\n   After a similar function by Just van Rossum. */\n\nint\nPyImport_ExtendInittab(struct _inittab *newtab)\n{\n    struct _inittab *p;\n    size_t i, n;\n    int res = 0;\n\n    if (INITTAB != NULL) {\n        Py_FatalError(\"PyImport_ExtendInittab() may not be called after Py_Initialize()\");\n    }\n\n    /* Count the number of entries in both tables */\n    for (n = 0; newtab[n].name != NULL; n++)\n        ;\n    if (n == 0)\n        return 0; /* Nothing to do */\n    for (i = 0; PyImport_Inittab[i].name != NULL; i++)\n        ;\n\n    /* Force default raw memory allocator to get a known allocator to be able\n       to release the memory in _PyImport_Fini2() */\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    /* Allocate new memory for the combined table */\n    p = NULL;\n    if (i + n <= SIZE_MAX / sizeof(struct _inittab) - 1) {\n        size_t size = sizeof(struct _inittab) * (i + n + 1);\n        p = PyMem_RawRealloc(inittab_copy, size);\n    }\n    if (p == NULL) {\n        res = -1;\n        goto done;\n    }\n\n    /* Copy the tables into the new memory at the first call\n       to PyImport_ExtendInittab(). */\n    if (inittab_copy != PyImport_Inittab) {\n        memcpy(p, PyImport_Inittab, (i+1) * sizeof(struct _inittab));\n    }\n    memcpy(p + i, newtab, (n + 1) * sizeof(struct _inittab));\n    PyImport_Inittab = inittab_copy = p;\n\ndone:\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n    return res;\n}\n\n/* Shorthand to add a single entry given a name and a function */\n\nint\nPyImport_AppendInittab(const char *name, PyObject* (*initfunc)(void))\n{\n    struct _inittab newtab[2];\n\n    if (INITTAB != NULL) {\n        Py_FatalError(\"PyImport_AppendInittab() may not be called after Py_Initialize()\");\n    }\n\n    memset(newtab, '\\0', sizeof newtab);\n\n    newtab[0].name = name;\n    newtab[0].initfunc = initfunc;\n\n    return PyImport_ExtendInittab(newtab);\n}\n\n\n/* the internal table */\n\nstatic int\ninit_builtin_modules_table(void)\n{\n    size_t size;\n    for (size = 0; PyImport_Inittab[size].name != NULL; size++)\n        ;\n    size++;\n\n    /* Make the copy. */\n    struct _inittab *copied = PyMem_RawMalloc(size * sizeof(struct _inittab));\n    if (copied == NULL) {\n        return -1;\n    }\n    memcpy(copied, PyImport_Inittab, size * sizeof(struct _inittab));\n    INITTAB = copied;\n    return 0;\n}\n\nstatic void\nfini_builtin_modules_table(void)\n{\n    struct _inittab *inittab = INITTAB;\n    INITTAB = NULL;\n    PyMem_RawFree(inittab);\n}\n\nPyObject *\n_PyImport_GetBuiltinModuleNames(void)\n{\n    PyObject *list = PyList_New(0);\n    if (list == NULL) {\n        return NULL;\n    }\n    struct _inittab *inittab = INITTAB;\n    for (Py_ssize_t i = 0; inittab[i].name != NULL; i++) {\n        PyObject *name = PyUnicode_FromString(inittab[i].name);\n        if (name == NULL) {\n            Py_DECREF(list);\n            return NULL;\n        }\n        if (PyList_Append(list, name) < 0) {\n            Py_DECREF(name);\n            Py_DECREF(list);\n            return NULL;\n        }\n        Py_DECREF(name);\n    }\n    return list;\n}\n\n\n/********************/\n/* the magic number */\n/********************/\n\n/* Helper for pythonrun.c -- return magic number and tag. */\n\nlong\nPyImport_GetMagicNumber(void)\n{\n    long res;\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    PyObject *external, *pyc_magic;\n\n    external = PyObject_GetAttrString(IMPORTLIB(interp), \"_bootstrap_external\");\n    if (external == NULL)\n        return -1;\n    pyc_magic = PyObject_GetAttrString(external, \"_RAW_MAGIC_NUMBER\");\n    Py_DECREF(external);\n    if (pyc_magic == NULL)\n        return -1;\n    res = PyLong_AsLong(pyc_magic);\n    Py_DECREF(pyc_magic);\n    return res;\n}\n\n\nextern const char * _PySys_ImplCacheTag;\n\nconst char *\nPyImport_GetMagicTag(void)\n{\n    return _PySys_ImplCacheTag;\n}\n\n\n/*********************************/\n/* a Python module's code object */\n/*********************************/\n\n/* Execute a code object in a module and return the module object\n * WITH INCREMENTED REFERENCE COUNT.  If an error occurs, name is\n * removed from sys.modules, to avoid leaving damaged module objects\n * in sys.modules.  The caller may wish to restore the original\n * module object (if any) in this case; PyImport_ReloadModule is an\n * example.\n *\n * Note that PyImport_ExecCodeModuleWithPathnames() is the preferred, richer\n * interface.  The other two exist primarily for backward compatibility.\n */\nPyObject *\nPyImport_ExecCodeModule(const char *name, PyObject *co)\n{\n    return PyImport_ExecCodeModuleWithPathnames(\n        name, co, (char *)NULL, (char *)NULL);\n}\n\nPyObject *\nPyImport_ExecCodeModuleEx(const char *name, PyObject *co, const char *pathname)\n{\n    return PyImport_ExecCodeModuleWithPathnames(\n        name, co, pathname, (char *)NULL);\n}\n\nPyObject *\nPyImport_ExecCodeModuleWithPathnames(const char *name, PyObject *co,\n                                     const char *pathname,\n                                     const char *cpathname)\n{\n    PyObject *m = NULL;\n    PyObject *nameobj, *pathobj = NULL, *cpathobj = NULL, *external= NULL;\n\n    nameobj = PyUnicode_FromString(name);\n    if (nameobj == NULL)\n        return NULL;\n\n    if (cpathname != NULL) {\n        cpathobj = PyUnicode_DecodeFSDefault(cpathname);\n        if (cpathobj == NULL)\n            goto error;\n    }\n    else\n        cpathobj = NULL;\n\n    if (pathname != NULL) {\n        pathobj = PyUnicode_DecodeFSDefault(pathname);\n        if (pathobj == NULL)\n            goto error;\n    }\n    else if (cpathobj != NULL) {\n        PyInterpreterState *interp = _PyInterpreterState_GET();\n\n        if (interp == NULL) {\n            Py_FatalError(\"no current interpreter\");\n        }\n\n        external= PyObject_GetAttrString(IMPORTLIB(interp),\n                                         \"_bootstrap_external\");\n        if (external != NULL) {\n            pathobj = _PyObject_CallMethodOneArg(\n                external, &_Py_ID(_get_sourcefile), cpathobj);\n            Py_DECREF(external);\n        }\n        if (pathobj == NULL)\n            PyErr_Clear();\n    }\n    else\n        pathobj = NULL;\n\n    m = PyImport_ExecCodeModuleObject(nameobj, co, pathobj, cpathobj);\nerror:\n    Py_DECREF(nameobj);\n    Py_XDECREF(pathobj);\n    Py_XDECREF(cpathobj);\n    return m;\n}\n\nstatic PyObject *\nmodule_dict_for_exec(PyThreadState *tstate, PyObject *name)\n{\n    PyObject *m, *d;\n\n    m = import_add_module(tstate, name);\n    if (m == NULL)\n        return NULL;\n    /* If the module is being reloaded, we get the old module back\n       and re-use its dict to exec the new code. */\n    d = PyModule_GetDict(m);\n    int r = PyDict_Contains(d, &_Py_ID(__builtins__));\n    if (r == 0) {\n        r = PyDict_SetItem(d, &_Py_ID(__builtins__), PyEval_GetBuiltins());\n    }\n    if (r < 0) {\n        remove_module(tstate, name);\n        Py_DECREF(m);\n        return NULL;\n    }\n\n    Py_INCREF(d);\n    Py_DECREF(m);\n    return d;\n}\n\nstatic PyObject *\nexec_code_in_module(PyThreadState *tstate, PyObject *name,\n                    PyObject *module_dict, PyObject *code_object)\n{\n    PyObject *v, *m;\n\n    v = PyEval_EvalCode(code_object, module_dict, module_dict);\n    if (v == NULL) {\n        remove_module(tstate, name);\n        return NULL;\n    }\n    Py_DECREF(v);\n\n    m = import_get_module(tstate, name);\n    if (m == NULL && !_PyErr_Occurred(tstate)) {\n        _PyErr_Format(tstate, PyExc_ImportError,\n                      \"Loaded module %R not found in sys.modules\",\n                      name);\n    }\n\n    return m;\n}\n\nPyObject*\nPyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname,\n                              PyObject *cpathname)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *d, *external, *res;\n\n    d = module_dict_for_exec(tstate, name);\n    if (d == NULL) {\n        return NULL;\n    }\n\n    if (pathname == NULL) {\n        pathname = ((PyCodeObject *)co)->co_filename;\n    }\n    external = PyObject_GetAttrString(IMPORTLIB(tstate->interp),\n                                      \"_bootstrap_external\");\n    if (external == NULL) {\n        Py_DECREF(d);\n        return NULL;\n    }\n    res = PyObject_CallMethodObjArgs(external, &_Py_ID(_fix_up_module),\n                                     d, name, pathname, cpathname, NULL);\n    Py_DECREF(external);\n    if (res != NULL) {\n        Py_DECREF(res);\n        res = exec_code_in_module(tstate, name, d, co);\n    }\n    Py_DECREF(d);\n    return res;\n}\n\n\nstatic void\nupdate_code_filenames(PyCodeObject *co, PyObject *oldname, PyObject *newname)\n{\n    PyObject *constants, *tmp;\n    Py_ssize_t i, n;\n\n    if (PyUnicode_Compare(co->co_filename, oldname))\n        return;\n\n    Py_XSETREF(co->co_filename, Py_NewRef(newname));\n\n    constants = co->co_consts;\n    n = PyTuple_GET_SIZE(constants);\n    for (i = 0; i < n; i++) {\n        tmp = PyTuple_GET_ITEM(constants, i);\n        if (PyCode_Check(tmp))\n            update_code_filenames((PyCodeObject *)tmp,\n                                  oldname, newname);\n    }\n}\n\nstatic void\nupdate_compiled_module(PyCodeObject *co, PyObject *newname)\n{\n    PyObject *oldname;\n\n    if (PyUnicode_Compare(co->co_filename, newname) == 0)\n        return;\n\n    oldname = co->co_filename;\n    Py_INCREF(oldname);\n    update_code_filenames(co, oldname, newname);\n    Py_DECREF(oldname);\n}\n\n\n/******************/\n/* frozen modules */\n/******************/\n\n/* Return true if the name is an alias.  In that case, \"alias\" is set\n   to the original module name.  If it is an alias but the original\n   module isn't known then \"alias\" is set to NULL while true is returned. */\nstatic bool\nresolve_module_alias(const char *name, const struct _module_alias *aliases,\n                     const char **alias)\n{\n    const struct _module_alias *entry;\n    for (entry = aliases; ; entry++) {\n        if (entry->name == NULL) {\n            /* It isn't an alias. */\n            return false;\n        }\n        if (strcmp(name, entry->name) == 0) {\n            if (alias != NULL) {\n                *alias = entry->orig;\n            }\n            return true;\n        }\n    }\n}\n\nstatic bool\nuse_frozen(void)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    int override = OVERRIDE_FROZEN_MODULES(interp);\n    if (override > 0) {\n        return true;\n    }\n    else if (override < 0) {\n        return false;\n    }\n    else {\n        return interp->config.use_frozen_modules;\n    }\n}\n\nstatic PyObject *\nlist_frozen_module_names(void)\n{\n    PyObject *names = PyList_New(0);\n    if (names == NULL) {\n        return NULL;\n    }\n    bool enabled = use_frozen();\n    const struct _frozen *p;\n#define ADD_MODULE(name) \\\n    do { \\\n        PyObject *nameobj = PyUnicode_FromString(name); \\\n        if (nameobj == NULL) { \\\n            goto error; \\\n        } \\\n        int res = PyList_Append(names, nameobj); \\\n        Py_DECREF(nameobj); \\\n        if (res != 0) { \\\n            goto error; \\\n        } \\\n    } while(0)\n    // We always use the bootstrap modules.\n    for (p = _PyImport_FrozenBootstrap; ; p++) {\n        if (p->name == NULL) {\n            break;\n        }\n        ADD_MODULE(p->name);\n    }\n    // Frozen stdlib modules may be disabled.\n    for (p = _PyImport_FrozenStdlib; ; p++) {\n        if (p->name == NULL) {\n            break;\n        }\n        if (enabled) {\n            ADD_MODULE(p->name);\n        }\n    }\n    for (p = _PyImport_FrozenTest; ; p++) {\n        if (p->name == NULL) {\n            break;\n        }\n        if (enabled) {\n            ADD_MODULE(p->name);\n        }\n    }\n#undef ADD_MODULE\n    // Add any custom modules.\n    if (PyImport_FrozenModules != NULL) {\n        for (p = PyImport_FrozenModules; ; p++) {\n            if (p->name == NULL) {\n                break;\n            }\n            PyObject *nameobj = PyUnicode_FromString(p->name);\n            if (nameobj == NULL) {\n                goto error;\n            }\n            int found = PySequence_Contains(names, nameobj);\n            if (found < 0) {\n                Py_DECREF(nameobj);\n                goto error;\n            }\n            else if (found) {\n                Py_DECREF(nameobj);\n            }\n            else {\n                int res = PyList_Append(names, nameobj);\n                Py_DECREF(nameobj);\n                if (res != 0) {\n                    goto error;\n                }\n            }\n        }\n    }\n    return names;\n\nerror:\n    Py_DECREF(names);\n    return NULL;\n}\n\ntypedef enum {\n    FROZEN_OKAY,\n    FROZEN_BAD_NAME,    // The given module name wasn't valid.\n    FROZEN_NOT_FOUND,   // It wasn't in PyImport_FrozenModules.\n    FROZEN_DISABLED,    // -X frozen_modules=off (and not essential)\n    FROZEN_EXCLUDED,    /* The PyImport_FrozenModules entry has NULL \"code\"\n                           (module is present but marked as unimportable, stops search). */\n    FROZEN_INVALID,     /* The PyImport_FrozenModules entry is bogus\n                           (eg. does not contain executable code). */\n} frozen_status;\n\nstatic inline void\nset_frozen_error(frozen_status status, PyObject *modname)\n{\n    const char *err = NULL;\n    switch (status) {\n        case FROZEN_BAD_NAME:\n        case FROZEN_NOT_FOUND:\n            err = \"No such frozen object named %R\";\n            break;\n        case FROZEN_DISABLED:\n            err = \"Frozen modules are disabled and the frozen object named %R is not essential\";\n            break;\n        case FROZEN_EXCLUDED:\n            err = \"Excluded frozen object named %R\";\n            break;\n        case FROZEN_INVALID:\n            err = \"Frozen object named %R is invalid\";\n            break;\n        case FROZEN_OKAY:\n            // There was no error.\n            break;\n        default:\n            Py_UNREACHABLE();\n    }\n    if (err != NULL) {\n        PyObject *msg = PyUnicode_FromFormat(err, modname);\n        if (msg == NULL) {\n            PyErr_Clear();\n        }\n        PyErr_SetImportError(msg, modname, NULL);\n        Py_XDECREF(msg);\n    }\n}\n\nstatic const struct _frozen *\nlook_up_frozen(const char *name)\n{\n    const struct _frozen *p;\n    // We always use the bootstrap modules.\n    for (p = _PyImport_FrozenBootstrap; ; p++) {\n        if (p->name == NULL) {\n            // We hit the end-of-list sentinel value.\n            break;\n        }\n        if (strcmp(name, p->name) == 0) {\n            return p;\n        }\n    }\n    // Prefer custom modules, if any.  Frozen stdlib modules can be\n    // disabled here by setting \"code\" to NULL in the array entry.\n    if (PyImport_FrozenModules != NULL) {\n        for (p = PyImport_FrozenModules; ; p++) {\n            if (p->name == NULL) {\n                break;\n            }\n            if (strcmp(name, p->name) == 0) {\n                return p;\n            }\n        }\n    }\n    // Frozen stdlib modules may be disabled.\n    if (use_frozen()) {\n        for (p = _PyImport_FrozenStdlib; ; p++) {\n            if (p->name == NULL) {\n                break;\n            }\n            if (strcmp(name, p->name) == 0) {\n                return p;\n            }\n        }\n        for (p = _PyImport_FrozenTest; ; p++) {\n            if (p->name == NULL) {\n                break;\n            }\n            if (strcmp(name, p->name) == 0) {\n                return p;\n            }\n        }\n    }\n    return NULL;\n}\n\nstruct frozen_info {\n    PyObject *nameobj;\n    const char *data;\n    PyObject *(*get_code)(void);\n    Py_ssize_t size;\n    bool is_package;\n    bool is_alias;\n    const char *origname;\n};\n\nstatic frozen_status\nfind_frozen(PyObject *nameobj, struct frozen_info *info)\n{\n    if (info != NULL) {\n        memset(info, 0, sizeof(*info));\n    }\n\n    if (nameobj == NULL || nameobj == Py_None) {\n        return FROZEN_BAD_NAME;\n    }\n    const char *name = PyUnicode_AsUTF8(nameobj);\n    if (name == NULL) {\n        // Note that this function previously used\n        // _PyUnicode_EqualToASCIIString().  We clear the error here\n        // (instead of propagating it) to match the earlier behavior\n        // more closely.\n        PyErr_Clear();\n        return FROZEN_BAD_NAME;\n    }\n\n    const struct _frozen *p = look_up_frozen(name);\n    if (p == NULL) {\n        return FROZEN_NOT_FOUND;\n    }\n    if (info != NULL) {\n        info->nameobj = nameobj;  // borrowed\n        info->data = (const char *)p->code;\n        info->get_code = p->get_code;\n        info->size = p->size;\n        info->is_package = p->is_package;\n        if (p->size < 0) {\n            // backward compatibility with negative size values\n            info->size = -(p->size);\n            info->is_package = true;\n        }\n        info->origname = name;\n        info->is_alias = resolve_module_alias(name, _PyImport_FrozenAliases,\n                                              &info->origname);\n    }\n    if (p->code == NULL && p->size == 0 && p->get_code != NULL) {\n        /* It is only deepfrozen. */\n        return FROZEN_OKAY;\n    }\n    if (p->code == NULL) {\n        /* It is frozen but marked as un-importable. */\n        return FROZEN_EXCLUDED;\n    }\n    if (p->code[0] == '\\0' || p->size == 0) {\n        /* Does not contain executable code. */\n        return FROZEN_INVALID;\n    }\n    return FROZEN_OKAY;\n}\n\nstatic PyObject *\nunmarshal_frozen_code(PyInterpreterState *interp, struct frozen_info *info)\n{\n    if (info->get_code && _Py_IsMainInterpreter(interp)) {\n        PyObject *code = info->get_code();\n        assert(code != NULL);\n        return code;\n    }\n    PyObject *co = PyMarshal_ReadObjectFromString(info->data, info->size);\n    if (co == NULL) {\n        /* Does not contain executable code. */\n        set_frozen_error(FROZEN_INVALID, info->nameobj);\n        return NULL;\n    }\n    if (!PyCode_Check(co)) {\n        // We stick with TypeError for backward compatibility.\n        PyErr_Format(PyExc_TypeError,\n                     \"frozen object %R is not a code object\",\n                     info->nameobj);\n        Py_DECREF(co);\n        return NULL;\n    }\n    return co;\n}\n\n\n/* Initialize a frozen module.\n   Return 1 for success, 0 if the module is not found, and -1 with\n   an exception set if the initialization failed.\n   This function is also used from frozenmain.c */\n\nint\nPyImport_ImportFrozenModuleObject(PyObject *name)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *co, *m, *d = NULL;\n    int err;\n\n    struct frozen_info info;\n    frozen_status status = find_frozen(name, &info);\n    if (status == FROZEN_NOT_FOUND || status == FROZEN_DISABLED) {\n        return 0;\n    }\n    else if (status == FROZEN_BAD_NAME) {\n        return 0;\n    }\n    else if (status != FROZEN_OKAY) {\n        set_frozen_error(status, name);\n        return -1;\n    }\n    co = unmarshal_frozen_code(tstate->interp, &info);\n    if (co == NULL) {\n        return -1;\n    }\n    if (info.is_package) {\n        /* Set __path__ to the empty list */\n        PyObject *l;\n        m = import_add_module(tstate, name);\n        if (m == NULL)\n            goto err_return;\n        d = PyModule_GetDict(m);\n        l = PyList_New(0);\n        if (l == NULL) {\n            Py_DECREF(m);\n            goto err_return;\n        }\n        err = PyDict_SetItemString(d, \"__path__\", l);\n        Py_DECREF(l);\n        Py_DECREF(m);\n        if (err != 0)\n            goto err_return;\n    }\n    d = module_dict_for_exec(tstate, name);\n    if (d == NULL) {\n        goto err_return;\n    }\n    m = exec_code_in_module(tstate, name, d, co);\n    if (m == NULL) {\n        goto err_return;\n    }\n    Py_DECREF(m);\n    /* Set __origname__ (consumed in FrozenImporter._setup_module()). */\n    PyObject *origname;\n    if (info.origname) {\n        origname = PyUnicode_FromString(info.origname);\n        if (origname == NULL) {\n            goto err_return;\n        }\n    }\n    else {\n        origname = Py_NewRef(Py_None);\n    }\n    err = PyDict_SetItemString(d, \"__origname__\", origname);\n    Py_DECREF(origname);\n    if (err != 0) {\n        goto err_return;\n    }\n    Py_DECREF(d);\n    Py_DECREF(co);\n    return 1;\n\nerr_return:\n    Py_XDECREF(d);\n    Py_DECREF(co);\n    return -1;\n}\n\nint\nPyImport_ImportFrozenModule(const char *name)\n{\n    PyObject *nameobj;\n    int ret;\n    nameobj = PyUnicode_InternFromString(name);\n    if (nameobj == NULL)\n        return -1;\n    ret = PyImport_ImportFrozenModuleObject(nameobj);\n    Py_DECREF(nameobj);\n    return ret;\n}\n\n\n/*************/\n/* importlib */\n/*************/\n\n/* Import the _imp extension by calling manually _imp.create_builtin() and\n   _imp.exec_builtin() since importlib is not initialized yet. Initializing\n   importlib requires the _imp module: this function fix the bootstrap issue.\n */\nstatic PyObject*\nbootstrap_imp(PyThreadState *tstate)\n{\n    PyObject *name = PyUnicode_FromString(\"_imp\");\n    if (name == NULL) {\n        return NULL;\n    }\n\n    // Mock a ModuleSpec object just good enough for PyModule_FromDefAndSpec():\n    // an object with just a name attribute.\n    //\n    // _imp.__spec__ is overridden by importlib._bootstrap._instal() anyway.\n    PyObject *attrs = Py_BuildValue(\"{sO}\", \"name\", name);\n    if (attrs == NULL) {\n        goto error;\n    }\n    PyObject *spec = _PyNamespace_New(attrs);\n    Py_DECREF(attrs);\n    if (spec == NULL) {\n        goto error;\n    }\n\n    // Create the _imp module from its definition.\n    PyObject *mod = create_builtin(tstate, name, spec);\n    Py_CLEAR(name);\n    Py_DECREF(spec);\n    if (mod == NULL) {\n        goto error;\n    }\n    assert(mod != Py_None);  // not found\n\n    // Execute the _imp module: call imp_module_exec().\n    if (exec_builtin_or_dynamic(mod) < 0) {\n        Py_DECREF(mod);\n        goto error;\n    }\n    return mod;\n\nerror:\n    Py_XDECREF(name);\n    return NULL;\n}\n\n/* Global initializations.  Can be undone by Py_FinalizeEx().  Don't\n   call this twice without an intervening Py_FinalizeEx() call.  When\n   initializations fail, a fatal error is issued and the function does\n   not return.  On return, the first thread and interpreter state have\n   been created.\n\n   Locking: you must hold the interpreter lock while calling this.\n   (If the lock has not yet been initialized, that's equivalent to\n   having the lock, but you cannot use multiple threads.)\n\n*/\nstatic int\ninit_importlib(PyThreadState *tstate, PyObject *sysmod)\n{\n    assert(!_PyErr_Occurred(tstate));\n\n    PyInterpreterState *interp = tstate->interp;\n    int verbose = _PyInterpreterState_GetConfig(interp)->verbose;\n\n    // Import _importlib through its frozen version, _frozen_importlib.\n    if (verbose) {\n        PySys_FormatStderr(\"import _frozen_importlib # frozen\\n\");\n    }\n    if (PyImport_ImportFrozenModule(\"_frozen_importlib\") <= 0) {\n        return -1;\n    }\n    PyObject *importlib = PyImport_AddModule(\"_frozen_importlib\"); // borrowed\n    if (importlib == NULL) {\n        return -1;\n    }\n    IMPORTLIB(interp) = Py_NewRef(importlib);\n\n    // Import the _imp module\n    if (verbose) {\n        PySys_FormatStderr(\"import _imp # builtin\\n\");\n    }\n    PyObject *imp_mod = bootstrap_imp(tstate);\n    if (imp_mod == NULL) {\n        return -1;\n    }\n    if (_PyImport_SetModuleString(\"_imp\", imp_mod) < 0) {\n        Py_DECREF(imp_mod);\n        return -1;\n    }\n\n    // Install importlib as the implementation of import\n    PyObject *value = PyObject_CallMethod(importlib, \"_install\",\n                                          \"OO\", sysmod, imp_mod);\n    Py_DECREF(imp_mod);\n    if (value == NULL) {\n        return -1;\n    }\n    Py_DECREF(value);\n\n    assert(!_PyErr_Occurred(tstate));\n    return 0;\n}\n\n\nstatic int\ninit_importlib_external(PyInterpreterState *interp)\n{\n    PyObject *value;\n    value = PyObject_CallMethod(IMPORTLIB(interp),\n                                \"_install_external_importers\", \"\");\n    if (value == NULL) {\n        return -1;\n    }\n    Py_DECREF(value);\n    return 0;\n}\n\nPyObject *\n_PyImport_GetImportlibLoader(PyInterpreterState *interp,\n                             const char *loader_name)\n{\n    return PyObject_GetAttrString(IMPORTLIB(interp), loader_name);\n}\n\nPyObject *\n_PyImport_GetImportlibExternalLoader(PyInterpreterState *interp,\n                                     const char *loader_name)\n{\n    PyObject *bootstrap = PyObject_GetAttrString(IMPORTLIB(interp),\n                                                 \"_bootstrap_external\");\n    if (bootstrap == NULL) {\n        return NULL;\n    }\n\n    PyObject *loader_type = PyObject_GetAttrString(bootstrap, loader_name);\n    Py_DECREF(bootstrap);\n    return loader_type;\n}\n\nPyObject *\n_PyImport_BlessMyLoader(PyInterpreterState *interp, PyObject *module_globals)\n{\n    PyObject *external = PyObject_GetAttrString(IMPORTLIB(interp),\n                                                \"_bootstrap_external\");\n    if (external == NULL) {\n        return NULL;\n    }\n\n    PyObject *loader = PyObject_CallMethod(external, \"_bless_my_loader\",\n                                           \"O\", module_globals, NULL);\n    Py_DECREF(external);\n    return loader;\n}\n\nPyObject *\n_PyImport_ImportlibModuleRepr(PyInterpreterState *interp, PyObject *m)\n{\n    return PyObject_CallMethod(IMPORTLIB(interp), \"_module_repr\", \"O\", m);\n}\n\n\n/*******************/\n\n/* Return a finder object for a sys.path/pkg.__path__ item 'p',\n   possibly by fetching it from the path_importer_cache dict. If it\n   wasn't yet cached, traverse path_hooks until a hook is found\n   that can handle the path item. Return None if no hook could;\n   this tells our caller that the path based finder could not find\n   a finder for this path item. Cache the result in\n   path_importer_cache. */\n\nstatic PyObject *\nget_path_importer(PyThreadState *tstate, PyObject *path_importer_cache,\n                  PyObject *path_hooks, PyObject *p)\n{\n    PyObject *importer;\n    Py_ssize_t j, nhooks;\n\n    /* These conditions are the caller's responsibility: */\n    assert(PyList_Check(path_hooks));\n    assert(PyDict_Check(path_importer_cache));\n\n    nhooks = PyList_Size(path_hooks);\n    if (nhooks < 0)\n        return NULL; /* Shouldn't happen */\n\n    importer = PyDict_GetItemWithError(path_importer_cache, p);\n    if (importer != NULL || _PyErr_Occurred(tstate)) {\n        return Py_XNewRef(importer);\n    }\n\n    /* set path_importer_cache[p] to None to avoid recursion */\n    if (PyDict_SetItem(path_importer_cache, p, Py_None) != 0)\n        return NULL;\n\n    for (j = 0; j < nhooks; j++) {\n        PyObject *hook = PyList_GetItem(path_hooks, j);\n        if (hook == NULL)\n            return NULL;\n        importer = PyObject_CallOneArg(hook, p);\n        if (importer != NULL)\n            break;\n\n        if (!_PyErr_ExceptionMatches(tstate, PyExc_ImportError)) {\n            return NULL;\n        }\n        _PyErr_Clear(tstate);\n    }\n    if (importer == NULL) {\n        Py_RETURN_NONE;\n    }\n    if (PyDict_SetItem(path_importer_cache, p, importer) < 0) {\n        Py_DECREF(importer);\n        return NULL;\n    }\n    return importer;\n}\n\nPyObject *\nPyImport_GetImporter(PyObject *path)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *path_importer_cache = PySys_GetObject(\"path_importer_cache\");\n    PyObject *path_hooks = PySys_GetObject(\"path_hooks\");\n    if (path_importer_cache == NULL || path_hooks == NULL) {\n        return NULL;\n    }\n    return get_path_importer(tstate, path_importer_cache, path_hooks, path);\n}\n\n\n/*********************/\n/* importing modules */\n/*********************/\n\nint\n_PyImport_InitDefaultImportFunc(PyInterpreterState *interp)\n{\n    // Get the __import__ function\n    PyObject *import_func = _PyDict_GetItemStringWithError(interp->builtins,\n                                                           \"__import__\");\n    if (import_func == NULL) {\n        return -1;\n    }\n    IMPORT_FUNC(interp) = Py_NewRef(import_func);\n    return 0;\n}\n\nint\n_PyImport_IsDefaultImportFunc(PyInterpreterState *interp, PyObject *func)\n{\n    return func == IMPORT_FUNC(interp);\n}\n\n\n/* Import a module, either built-in, frozen, or external, and return\n   its module object WITH INCREMENTED REFERENCE COUNT */\n\nPyObject *\nPyImport_ImportModule(const char *name)\n{\n    PyObject *pname;\n    PyObject *result;\n\n    pname = PyUnicode_FromString(name);\n    if (pname == NULL)\n        return NULL;\n    result = PyImport_Import(pname);\n    Py_DECREF(pname);\n    return result;\n}\n\n\n/* Import a module without blocking\n *\n * At first it tries to fetch the module from sys.modules. If the module was\n * never loaded before it loads it with PyImport_ImportModule() unless another\n * thread holds the import lock. In the latter case the function raises an\n * ImportError instead of blocking.\n *\n * Returns the module object with incremented ref count.\n */\nPyObject *\nPyImport_ImportModuleNoBlock(const char *name)\n{\n    return PyImport_ImportModule(name);\n}\n\n\n/* Remove importlib frames from the traceback,\n * except in Verbose mode. */\nstatic void\nremove_importlib_frames(PyThreadState *tstate)\n{\n    const char *importlib_filename = \"<frozen importlib._bootstrap>\";\n    const char *external_filename = \"<frozen importlib._bootstrap_external>\";\n    const char *remove_frames = \"_call_with_frames_removed\";\n    int always_trim = 0;\n    int in_importlib = 0;\n    PyObject **prev_link, **outer_link = NULL;\n    PyObject *base_tb = NULL;\n\n    /* Synopsis: if it's an ImportError, we trim all importlib chunks\n       from the traceback. We always trim chunks\n       which end with a call to \"_call_with_frames_removed\". */\n\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    if (exc == NULL || _PyInterpreterState_GetConfig(tstate->interp)->verbose) {\n        goto done;\n    }\n\n    if (PyType_IsSubtype(Py_TYPE(exc), (PyTypeObject *) PyExc_ImportError)) {\n        always_trim = 1;\n    }\n\n    assert(PyExceptionInstance_Check(exc));\n    base_tb = PyException_GetTraceback(exc);\n    prev_link = &base_tb;\n    PyObject *tb = base_tb;\n    while (tb != NULL) {\n        assert(PyTraceBack_Check(tb));\n        PyTracebackObject *traceback = (PyTracebackObject *)tb;\n        PyObject *next = (PyObject *) traceback->tb_next;\n        PyFrameObject *frame = traceback->tb_frame;\n        PyCodeObject *code = PyFrame_GetCode(frame);\n        int now_in_importlib;\n\n        now_in_importlib = _PyUnicode_EqualToASCIIString(code->co_filename, importlib_filename) ||\n                           _PyUnicode_EqualToASCIIString(code->co_filename, external_filename);\n        if (now_in_importlib && !in_importlib) {\n            /* This is the link to this chunk of importlib tracebacks */\n            outer_link = prev_link;\n        }\n        in_importlib = now_in_importlib;\n\n        if (in_importlib &&\n            (always_trim ||\n             _PyUnicode_EqualToASCIIString(code->co_name, remove_frames))) {\n            Py_XSETREF(*outer_link, Py_XNewRef(next));\n            prev_link = outer_link;\n        }\n        else {\n            prev_link = (PyObject **) &traceback->tb_next;\n        }\n        Py_DECREF(code);\n        tb = next;\n    }\n    if (base_tb == NULL) {\n        base_tb = Py_None;\n        Py_INCREF(Py_None);\n    }\n    PyException_SetTraceback(exc, base_tb);\ndone:\n    Py_XDECREF(base_tb);\n    _PyErr_SetRaisedException(tstate, exc);\n}\n\n\nstatic PyObject *\nresolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level)\n{\n    PyObject *abs_name;\n    PyObject *package = NULL;\n    PyObject *spec;\n    Py_ssize_t last_dot;\n    PyObject *base;\n    int level_up;\n\n    if (globals == NULL) {\n        _PyErr_SetString(tstate, PyExc_KeyError, \"'__name__' not in globals\");\n        goto error;\n    }\n    if (!PyDict_Check(globals)) {\n        _PyErr_SetString(tstate, PyExc_TypeError, \"globals must be a dict\");\n        goto error;\n    }\n    package = PyDict_GetItemWithError(globals, &_Py_ID(__package__));\n    if (package == Py_None) {\n        package = NULL;\n    }\n    else if (package == NULL && _PyErr_Occurred(tstate)) {\n        goto error;\n    }\n    spec = PyDict_GetItemWithError(globals, &_Py_ID(__spec__));\n    if (spec == NULL && _PyErr_Occurred(tstate)) {\n        goto error;\n    }\n\n    if (package != NULL) {\n        Py_INCREF(package);\n        if (!PyUnicode_Check(package)) {\n            _PyErr_SetString(tstate, PyExc_TypeError,\n                             \"package must be a string\");\n            goto error;\n        }\n        else if (spec != NULL && spec != Py_None) {\n            int equal;\n            PyObject *parent = PyObject_GetAttr(spec, &_Py_ID(parent));\n            if (parent == NULL) {\n                goto error;\n            }\n\n            equal = PyObject_RichCompareBool(package, parent, Py_EQ);\n            Py_DECREF(parent);\n            if (equal < 0) {\n                goto error;\n            }\n            else if (equal == 0) {\n                if (PyErr_WarnEx(PyExc_DeprecationWarning,\n                        \"__package__ != __spec__.parent\", 1) < 0) {\n                    goto error;\n                }\n            }\n        }\n    }\n    else if (spec != NULL && spec != Py_None) {\n        package = PyObject_GetAttr(spec, &_Py_ID(parent));\n        if (package == NULL) {\n            goto error;\n        }\n        else if (!PyUnicode_Check(package)) {\n            _PyErr_SetString(tstate, PyExc_TypeError,\n                             \"__spec__.parent must be a string\");\n            goto error;\n        }\n    }\n    else {\n        if (PyErr_WarnEx(PyExc_ImportWarning,\n                    \"can't resolve package from __spec__ or __package__, \"\n                    \"falling back on __name__ and __path__\", 1) < 0) {\n            goto error;\n        }\n\n        package = PyDict_GetItemWithError(globals, &_Py_ID(__name__));\n        if (package == NULL) {\n            if (!_PyErr_Occurred(tstate)) {\n                _PyErr_SetString(tstate, PyExc_KeyError,\n                                 \"'__name__' not in globals\");\n            }\n            goto error;\n        }\n\n        Py_INCREF(package);\n        if (!PyUnicode_Check(package)) {\n            _PyErr_SetString(tstate, PyExc_TypeError,\n                             \"__name__ must be a string\");\n            goto error;\n        }\n\n        int haspath = PyDict_Contains(globals, &_Py_ID(__path__));\n        if (haspath < 0) {\n            goto error;\n        }\n        if (!haspath) {\n            Py_ssize_t dot;\n\n            dot = PyUnicode_FindChar(package, '.',\n                                        0, PyUnicode_GET_LENGTH(package), -1);\n            if (dot == -2) {\n                goto error;\n            }\n            else if (dot == -1) {\n                goto no_parent_error;\n            }\n            PyObject *substr = PyUnicode_Substring(package, 0, dot);\n            if (substr == NULL) {\n                goto error;\n            }\n            Py_SETREF(package, substr);\n        }\n    }\n\n    last_dot = PyUnicode_GET_LENGTH(package);\n    if (last_dot == 0) {\n        goto no_parent_error;\n    }\n\n    for (level_up = 1; level_up < level; level_up += 1) {\n        last_dot = PyUnicode_FindChar(package, '.', 0, last_dot, -1);\n        if (last_dot == -2) {\n            goto error;\n        }\n        else if (last_dot == -1) {\n            _PyErr_SetString(tstate, PyExc_ImportError,\n                             \"attempted relative import beyond top-level \"\n                             \"package\");\n            goto error;\n        }\n    }\n\n    base = PyUnicode_Substring(package, 0, last_dot);\n    Py_DECREF(package);\n    if (base == NULL || PyUnicode_GET_LENGTH(name) == 0) {\n        return base;\n    }\n\n    abs_name = PyUnicode_FromFormat(\"%U.%U\", base, name);\n    Py_DECREF(base);\n    return abs_name;\n\n  no_parent_error:\n    _PyErr_SetString(tstate, PyExc_ImportError,\n                     \"attempted relative import \"\n                     \"with no known parent package\");\n\n  error:\n    Py_XDECREF(package);\n    return NULL;\n}\n\nstatic PyObject *\nimport_find_and_load(PyThreadState *tstate, PyObject *abs_name)\n{\n    PyObject *mod = NULL;\n    PyInterpreterState *interp = tstate->interp;\n    int import_time = _PyInterpreterState_GetConfig(interp)->import_time;\n#define import_level FIND_AND_LOAD(interp).import_level\n#define accumulated FIND_AND_LOAD(interp).accumulated\n\n    _PyTime_t t1 = 0, accumulated_copy = accumulated;\n\n    PyObject *sys_path = PySys_GetObject(\"path\");\n    PyObject *sys_meta_path = PySys_GetObject(\"meta_path\");\n    PyObject *sys_path_hooks = PySys_GetObject(\"path_hooks\");\n    if (_PySys_Audit(tstate, \"import\", \"OOOOO\",\n                     abs_name, Py_None, sys_path ? sys_path : Py_None,\n                     sys_meta_path ? sys_meta_path : Py_None,\n                     sys_path_hooks ? sys_path_hooks : Py_None) < 0) {\n        return NULL;\n    }\n\n\n    /* XOptions is initialized after first some imports.\n     * So we can't have negative cache before completed initialization.\n     * Anyway, importlib._find_and_load is much slower than\n     * _PyDict_GetItemIdWithError().\n     */\n    if (import_time) {\n#define header FIND_AND_LOAD(interp).header\n        if (header) {\n            fputs(\"import time: self [us] | cumulative | imported package\\n\",\n                  stderr);\n            header = 0;\n        }\n#undef header\n\n        import_level++;\n        t1 = _PyTime_GetPerfCounter();\n        accumulated = 0;\n    }\n\n    if (PyDTrace_IMPORT_FIND_LOAD_START_ENABLED())\n        PyDTrace_IMPORT_FIND_LOAD_START(PyUnicode_AsUTF8(abs_name));\n\n    mod = PyObject_CallMethodObjArgs(IMPORTLIB(interp), &_Py_ID(_find_and_load),\n                                     abs_name, IMPORT_FUNC(interp), NULL);\n\n    if (PyDTrace_IMPORT_FIND_LOAD_DONE_ENABLED())\n        PyDTrace_IMPORT_FIND_LOAD_DONE(PyUnicode_AsUTF8(abs_name),\n                                       mod != NULL);\n\n    if (import_time) {\n        _PyTime_t cum = _PyTime_GetPerfCounter() - t1;\n\n        import_level--;\n        fprintf(stderr, \"import time: %9ld | %10ld | %*s%s\\n\",\n                (long)_PyTime_AsMicroseconds(cum - accumulated, _PyTime_ROUND_CEILING),\n                (long)_PyTime_AsMicroseconds(cum, _PyTime_ROUND_CEILING),\n                import_level*2, \"\", PyUnicode_AsUTF8(abs_name));\n\n        accumulated = accumulated_copy + cum;\n    }\n\n    return mod;\n#undef import_level\n#undef accumulated\n}\n\nPyObject *\nPyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,\n                                 PyObject *locals, PyObject *fromlist,\n                                 int level)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *abs_name = NULL;\n    PyObject *final_mod = NULL;\n    PyObject *mod = NULL;\n    PyObject *package = NULL;\n    PyInterpreterState *interp = tstate->interp;\n    int has_from;\n\n    if (name == NULL) {\n        _PyErr_SetString(tstate, PyExc_ValueError, \"Empty module name\");\n        goto error;\n    }\n\n    /* The below code is importlib.__import__() & _gcd_import(), ported to C\n       for added performance. */\n\n    if (!PyUnicode_Check(name)) {\n        _PyErr_SetString(tstate, PyExc_TypeError,\n                         \"module name must be a string\");\n        goto error;\n    }\n    if (level < 0) {\n        _PyErr_SetString(tstate, PyExc_ValueError, \"level must be >= 0\");\n        goto error;\n    }\n\n    if (level > 0) {\n        abs_name = resolve_name(tstate, name, globals, level);\n        if (abs_name == NULL)\n            goto error;\n    }\n    else {  /* level == 0 */\n        if (PyUnicode_GET_LENGTH(name) == 0) {\n            _PyErr_SetString(tstate, PyExc_ValueError, \"Empty module name\");\n            goto error;\n        }\n        abs_name = Py_NewRef(name);\n    }\n\n    mod = import_get_module(tstate, abs_name);\n    if (mod == NULL && _PyErr_Occurred(tstate)) {\n        goto error;\n    }\n\n    if (mod != NULL && mod != Py_None) {\n        if (import_ensure_initialized(tstate->interp, mod, abs_name) < 0) {\n            goto error;\n        }\n    }\n    else {\n        Py_XDECREF(mod);\n        mod = import_find_and_load(tstate, abs_name);\n        if (mod == NULL) {\n            goto error;\n        }\n    }\n\n    has_from = 0;\n    if (fromlist != NULL && fromlist != Py_None) {\n        has_from = PyObject_IsTrue(fromlist);\n        if (has_from < 0)\n            goto error;\n    }\n    if (!has_from) {\n        Py_ssize_t len = PyUnicode_GET_LENGTH(name);\n        if (level == 0 || len > 0) {\n            Py_ssize_t dot;\n\n            dot = PyUnicode_FindChar(name, '.', 0, len, 1);\n            if (dot == -2) {\n                goto error;\n            }\n\n            if (dot == -1) {\n                /* No dot in module name, simple exit */\n                final_mod = Py_NewRef(mod);\n                goto error;\n            }\n\n            if (level == 0) {\n                PyObject *front = PyUnicode_Substring(name, 0, dot);\n                if (front == NULL) {\n                    goto error;\n                }\n\n                final_mod = PyImport_ImportModuleLevelObject(front, NULL, NULL, NULL, 0);\n                Py_DECREF(front);\n            }\n            else {\n                Py_ssize_t cut_off = len - dot;\n                Py_ssize_t abs_name_len = PyUnicode_GET_LENGTH(abs_name);\n                PyObject *to_return = PyUnicode_Substring(abs_name, 0,\n                                                        abs_name_len - cut_off);\n                if (to_return == NULL) {\n                    goto error;\n                }\n\n                final_mod = import_get_module(tstate, to_return);\n                Py_DECREF(to_return);\n                if (final_mod == NULL) {\n                    if (!_PyErr_Occurred(tstate)) {\n                        _PyErr_Format(tstate, PyExc_KeyError,\n                                      \"%R not in sys.modules as expected\",\n                                      to_return);\n                    }\n                    goto error;\n                }\n            }\n        }\n        else {\n            final_mod = Py_NewRef(mod);\n        }\n    }\n    else {\n        PyObject *path;\n        if (_PyObject_LookupAttr(mod, &_Py_ID(__path__), &path) < 0) {\n            goto error;\n        }\n        if (path) {\n            Py_DECREF(path);\n            final_mod = PyObject_CallMethodObjArgs(\n                        IMPORTLIB(interp), &_Py_ID(_handle_fromlist),\n                        mod, fromlist, IMPORT_FUNC(interp), NULL);\n        }\n        else {\n            final_mod = Py_NewRef(mod);\n        }\n    }\n\n  error:\n    Py_XDECREF(abs_name);\n    Py_XDECREF(mod);\n    Py_XDECREF(package);\n    if (final_mod == NULL) {\n        remove_importlib_frames(tstate);\n    }\n    return final_mod;\n}\n\nPyObject *\nPyImport_ImportModuleLevel(const char *name, PyObject *globals, PyObject *locals,\n                           PyObject *fromlist, int level)\n{\n    PyObject *nameobj, *mod;\n    nameobj = PyUnicode_FromString(name);\n    if (nameobj == NULL)\n        return NULL;\n    mod = PyImport_ImportModuleLevelObject(nameobj, globals, locals,\n                                           fromlist, level);\n    Py_DECREF(nameobj);\n    return mod;\n}\n\n\n/* Re-import a module of any kind and return its module object, WITH\n   INCREMENTED REFERENCE COUNT */\n\nPyObject *\nPyImport_ReloadModule(PyObject *m)\n{\n    PyObject *reloaded_module = NULL;\n    PyObject *importlib = PyImport_GetModule(&_Py_ID(importlib));\n    if (importlib == NULL) {\n        if (PyErr_Occurred()) {\n            return NULL;\n        }\n\n        importlib = PyImport_ImportModule(\"importlib\");\n        if (importlib == NULL) {\n            return NULL;\n        }\n    }\n\n    reloaded_module = PyObject_CallMethodOneArg(importlib, &_Py_ID(reload), m);\n    Py_DECREF(importlib);\n    return reloaded_module;\n}\n\n\n/* Higher-level import emulator which emulates the \"import\" statement\n   more accurately -- it invokes the __import__() function from the\n   builtins of the current globals.  This means that the import is\n   done using whatever import hooks are installed in the current\n   environment.\n   A dummy list [\"__doc__\"] is passed as the 4th argument so that\n   e.g. PyImport_Import(PyUnicode_FromString(\"win32com.client.gencache\"))\n   will return <module \"gencache\"> instead of <module \"win32com\">. */\n\nPyObject *\nPyImport_Import(PyObject *module_name)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *globals = NULL;\n    PyObject *import = NULL;\n    PyObject *builtins = NULL;\n    PyObject *r = NULL;\n\n    PyObject *from_list = PyList_New(0);\n    if (from_list == NULL) {\n        goto err;\n    }\n\n    /* Get the builtins from current globals */\n    globals = PyEval_GetGlobals();\n    if (globals != NULL) {\n        Py_INCREF(globals);\n        builtins = PyObject_GetItem(globals, &_Py_ID(__builtins__));\n        if (builtins == NULL)\n            goto err;\n    }\n    else {\n        /* No globals -- use standard builtins, and fake globals */\n        builtins = PyImport_ImportModuleLevel(\"builtins\",\n                                              NULL, NULL, NULL, 0);\n        if (builtins == NULL) {\n            goto err;\n        }\n        globals = Py_BuildValue(\"{OO}\", &_Py_ID(__builtins__), builtins);\n        if (globals == NULL)\n            goto err;\n    }\n\n    /* Get the __import__ function from the builtins */\n    if (PyDict_Check(builtins)) {\n        import = PyObject_GetItem(builtins, &_Py_ID(__import__));\n        if (import == NULL) {\n            _PyErr_SetObject(tstate, PyExc_KeyError, &_Py_ID(__import__));\n        }\n    }\n    else\n        import = PyObject_GetAttr(builtins, &_Py_ID(__import__));\n    if (import == NULL)\n        goto err;\n\n    /* Call the __import__ function with the proper argument list\n       Always use absolute import here.\n       Calling for side-effect of import. */\n    r = PyObject_CallFunction(import, \"OOOOi\", module_name, globals,\n                              globals, from_list, 0, NULL);\n    if (r == NULL)\n        goto err;\n    Py_DECREF(r);\n\n    r = import_get_module(tstate, module_name);\n    if (r == NULL && !_PyErr_Occurred(tstate)) {\n        _PyErr_SetObject(tstate, PyExc_KeyError, module_name);\n    }\n\n  err:\n    Py_XDECREF(globals);\n    Py_XDECREF(builtins);\n    Py_XDECREF(import);\n    Py_XDECREF(from_list);\n\n    return r;\n}\n\n\n/*********************/\n/* runtime lifecycle */\n/*********************/\n\nPyStatus\n_PyImport_Init(void)\n{\n    if (INITTAB != NULL) {\n        return _PyStatus_ERR(\"global import state already initialized\");\n    }\n\n    PyStatus status = _PyStatus_OK();\n\n    /* Force default raw memory allocator to get a known allocator to be able\n       to release the memory in _PyImport_Fini() */\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    if (init_builtin_modules_table() != 0) {\n        status = PyStatus_NoMemory();\n        goto done;\n    }\n\ndone:\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n    return status;\n}\n\nvoid\n_PyImport_Fini(void)\n{\n    /* Destroy the database used by _PyImport_{Fixup,Find}Extension */\n    _extensions_cache_clear_all();\n\n    /* Use the same memory allocator as _PyImport_Init(). */\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    /* Free memory allocated by _PyImport_Init() */\n    fini_builtin_modules_table();\n\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n}\n\nvoid\n_PyImport_Fini2(void)\n{\n    /* Use the same memory allocator than PyImport_ExtendInittab(). */\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    // Reset PyImport_Inittab\n    PyImport_Inittab = _PyImport_Inittab;\n\n    /* Free memory allocated by PyImport_ExtendInittab() */\n    PyMem_RawFree(inittab_copy);\n    inittab_copy = NULL;\n\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n}\n\n\n/*************************/\n/* interpreter lifecycle */\n/*************************/\n\nPyStatus\n_PyImport_InitCore(PyThreadState *tstate, PyObject *sysmod, int importlib)\n{\n    if (_Py_IsMainInterpreter(tstate->interp)) {\n        _extensions_cache_init();\n    }\n\n    // XXX Initialize here: interp->modules and interp->import_func.\n    // XXX Initialize here: sys.modules and sys.meta_path.\n\n    if (importlib) {\n        /* This call sets up builtin and frozen import support */\n        if (init_importlib(tstate, sysmod) < 0) {\n            return _PyStatus_ERR(\"failed to initialize importlib\");\n        }\n    }\n\n    return _PyStatus_OK();\n}\n\n/* In some corner cases it is important to be sure that the import\n   machinery has been initialized (or not cleaned up yet).  For\n   example, see issue #4236 and PyModule_Create2(). */\n\nint\n_PyImport_IsInitialized(PyInterpreterState *interp)\n{\n    if (MODULES(interp) == NULL)\n        return 0;\n    return 1;\n}\n\n/* Clear the direct per-interpreter import state, if not cleared already. */\nvoid\n_PyImport_ClearCore(PyInterpreterState *interp)\n{\n    /* interp->modules should have been cleaned up and cleared already\n       by _PyImport_FiniCore(). */\n    Py_CLEAR(MODULES(interp));\n    Py_CLEAR(MODULES_BY_INDEX(interp));\n    Py_CLEAR(IMPORTLIB(interp));\n    Py_CLEAR(IMPORT_FUNC(interp));\n}\n\nvoid\n_PyImport_FiniCore(PyInterpreterState *interp)\n{\n    int verbose = _PyInterpreterState_GetConfig(interp)->verbose;\n\n    if (_PySys_ClearAttrString(interp, \"meta_path\", verbose) < 0) {\n        PyErr_WriteUnraisable(NULL);\n    }\n\n    // XXX Pull in most of finalize_modules() in pylifecycle.c.\n\n    if (_PySys_ClearAttrString(interp, \"modules\", verbose) < 0) {\n        PyErr_WriteUnraisable(NULL);\n    }\n\n    if (IMPORT_LOCK(interp) != NULL) {\n        PyThread_free_lock(IMPORT_LOCK(interp));\n        IMPORT_LOCK(interp) = NULL;\n    }\n\n    _PyImport_ClearCore(interp);\n}\n\n// XXX Add something like _PyImport_Disable() for use early in interp fini?\n\n\n/* \"external\" imports */\n\nstatic int\ninit_zipimport(PyThreadState *tstate, int verbose)\n{\n    PyObject *path_hooks = PySys_GetObject(\"path_hooks\");\n    if (path_hooks == NULL) {\n        _PyErr_SetString(tstate, PyExc_RuntimeError,\n                         \"unable to get sys.path_hooks\");\n        return -1;\n    }\n\n    if (verbose) {\n        PySys_WriteStderr(\"# installing zipimport hook\\n\");\n    }\n\n    PyObject *zipimporter = _PyImport_GetModuleAttrString(\"zipimport\", \"zipimporter\");\n    if (zipimporter == NULL) {\n        _PyErr_Clear(tstate); /* No zipimporter object -- okay */\n        if (verbose) {\n            PySys_WriteStderr(\"# can't import zipimport.zipimporter\\n\");\n        }\n    }\n    else {\n        /* sys.path_hooks.insert(0, zipimporter) */\n        int err = PyList_Insert(path_hooks, 0, zipimporter);\n        Py_DECREF(zipimporter);\n        if (err < 0) {\n            return -1;\n        }\n        if (verbose) {\n            PySys_WriteStderr(\"# installed zipimport hook\\n\");\n        }\n    }\n\n    return 0;\n}\n\nPyStatus\n_PyImport_InitExternal(PyThreadState *tstate)\n{\n    int verbose = _PyInterpreterState_GetConfig(tstate->interp)->verbose;\n\n    // XXX Initialize here: sys.path_hooks and sys.path_importer_cache.\n\n    if (init_importlib_external(tstate->interp) != 0) {\n        _PyErr_Print(tstate);\n        return _PyStatus_ERR(\"external importer setup failed\");\n    }\n\n    if (init_zipimport(tstate, verbose) != 0) {\n        PyErr_Print();\n        return _PyStatus_ERR(\"initializing zipimport failed\");\n    }\n\n    return _PyStatus_OK();\n}\n\nvoid\n_PyImport_FiniExternal(PyInterpreterState *interp)\n{\n    int verbose = _PyInterpreterState_GetConfig(interp)->verbose;\n\n    // XXX Uninstall importlib metapath importers here?\n\n    if (_PySys_ClearAttrString(interp, \"path_importer_cache\", verbose) < 0) {\n        PyErr_WriteUnraisable(NULL);\n    }\n    if (_PySys_ClearAttrString(interp, \"path_hooks\", verbose) < 0) {\n        PyErr_WriteUnraisable(NULL);\n    }\n}\n\n\n/******************/\n/* module helpers */\n/******************/\n\nPyObject *\n_PyImport_GetModuleAttr(PyObject *modname, PyObject *attrname)\n{\n    PyObject *mod = PyImport_Import(modname);\n    if (mod == NULL) {\n        return NULL;\n    }\n    PyObject *result = PyObject_GetAttr(mod, attrname);\n    Py_DECREF(mod);\n    return result;\n}\n\nPyObject *\n_PyImport_GetModuleAttrString(const char *modname, const char *attrname)\n{\n    PyObject *pmodname = PyUnicode_FromString(modname);\n    if (pmodname == NULL) {\n        return NULL;\n    }\n    PyObject *pattrname = PyUnicode_FromString(attrname);\n    if (pattrname == NULL) {\n        Py_DECREF(pmodname);\n        return NULL;\n    }\n    PyObject *result = _PyImport_GetModuleAttr(pmodname, pattrname);\n    Py_DECREF(pattrname);\n    Py_DECREF(pmodname);\n    return result;\n}\n\n\n/**************/\n/* the module */\n/**************/\n\n/*[clinic input]\n_imp.lock_held\n\nReturn True if the import lock is currently held, else False.\n\nOn platforms without threads, return False.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_lock_held_impl(PyObject *module)\n/*[clinic end generated code: output=8b89384b5e1963fc input=9b088f9b217d9bdf]*/\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    return PyBool_FromLong(\n            IMPORT_LOCK_THREAD(interp) != PYTHREAD_INVALID_THREAD_ID);\n}\n\n/*[clinic input]\n_imp.acquire_lock\n\nAcquires the interpreter's import lock for the current thread.\n\nThis lock should be used by import hooks to ensure thread-safety when importing\nmodules. On platforms without threads, this function does nothing.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_acquire_lock_impl(PyObject *module)\n/*[clinic end generated code: output=1aff58cb0ee1b026 input=4a2d4381866d5fdc]*/\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    _PyImport_AcquireLock(interp);\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\n_imp.release_lock\n\nRelease the interpreter's import lock.\n\nOn platforms without threads, this function does nothing.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_release_lock_impl(PyObject *module)\n/*[clinic end generated code: output=7faab6d0be178b0a input=934fb11516dd778b]*/\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (_PyImport_ReleaseLock(interp) < 0) {\n        PyErr_SetString(PyExc_RuntimeError,\n                        \"not holding the import lock\");\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\n\n/*[clinic input]\n_imp._fix_co_filename\n\n    code: object(type=\"PyCodeObject *\", subclass_of=\"&PyCode_Type\")\n        Code object to change.\n\n    path: unicode\n        File path to use.\n    /\n\nChanges code.co_filename to specify the passed-in file path.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp__fix_co_filename_impl(PyObject *module, PyCodeObject *code,\n                           PyObject *path)\n/*[clinic end generated code: output=1d002f100235587d input=895ba50e78b82f05]*/\n\n{\n    update_compiled_module(code, path);\n\n    Py_RETURN_NONE;\n}\n\n\n/*[clinic input]\n_imp.create_builtin\n\n    spec: object\n    /\n\nCreate an extension module.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_create_builtin(PyObject *module, PyObject *spec)\n/*[clinic end generated code: output=ace7ff22271e6f39 input=37f966f890384e47]*/\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    PyObject *name = PyObject_GetAttrString(spec, \"name\");\n    if (name == NULL) {\n        return NULL;\n    }\n\n    if (!PyUnicode_Check(name)) {\n        PyErr_Format(PyExc_TypeError,\n                     \"name must be string, not %.200s\",\n                     Py_TYPE(name)->tp_name);\n        Py_DECREF(name);\n        return NULL;\n    }\n\n    PyObject *mod = create_builtin(tstate, name, spec);\n    Py_DECREF(name);\n    return mod;\n}\n\n\n/*[clinic input]\n_imp.extension_suffixes\n\nReturns the list of file suffixes used to identify extension modules.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_extension_suffixes_impl(PyObject *module)\n/*[clinic end generated code: output=0bf346e25a8f0cd3 input=ecdeeecfcb6f839e]*/\n{\n    PyObject *list;\n\n    list = PyList_New(0);\n    if (list == NULL)\n        return NULL;\n#ifdef HAVE_DYNAMIC_LOADING\n    const char *suffix;\n    unsigned int index = 0;\n\n    while ((suffix = _PyImport_DynLoadFiletab[index])) {\n        PyObject *item = PyUnicode_FromString(suffix);\n        if (item == NULL) {\n            Py_DECREF(list);\n            return NULL;\n        }\n        if (PyList_Append(list, item) < 0) {\n            Py_DECREF(list);\n            Py_DECREF(item);\n            return NULL;\n        }\n        Py_DECREF(item);\n        index += 1;\n    }\n#endif\n    return list;\n}\n\n/*[clinic input]\n_imp.init_frozen\n\n    name: unicode\n    /\n\nInitializes a frozen module.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_init_frozen_impl(PyObject *module, PyObject *name)\n/*[clinic end generated code: output=fc0511ed869fd69c input=13019adfc04f3fb3]*/\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    int ret;\n\n    ret = PyImport_ImportFrozenModuleObject(name);\n    if (ret < 0)\n        return NULL;\n    if (ret == 0) {\n        Py_RETURN_NONE;\n    }\n    return import_add_module(tstate, name);\n}\n\n/*[clinic input]\n_imp.find_frozen\n\n    name: unicode\n    /\n    *\n    withdata: bool = False\n\nReturn info about the corresponding frozen module (if there is one) or None.\n\nThe returned info (a 2-tuple):\n\n * data         the raw marshalled bytes\n * is_package   whether or not it is a package\n * origname     the originally frozen module's name, or None if not\n                a stdlib module (this will usually be the same as\n                the module's current name)\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_find_frozen_impl(PyObject *module, PyObject *name, int withdata)\n/*[clinic end generated code: output=8c1c3c7f925397a5 input=22a8847c201542fd]*/\n{\n    struct frozen_info info;\n    frozen_status status = find_frozen(name, &info);\n    if (status == FROZEN_NOT_FOUND || status == FROZEN_DISABLED) {\n        Py_RETURN_NONE;\n    }\n    else if (status == FROZEN_BAD_NAME) {\n        Py_RETURN_NONE;\n    }\n    else if (status != FROZEN_OKAY) {\n        set_frozen_error(status, name);\n        return NULL;\n    }\n\n    PyObject *data = NULL;\n    if (withdata) {\n        data = PyMemoryView_FromMemory((char *)info.data, info.size, PyBUF_READ);\n        if (data == NULL) {\n            return NULL;\n        }\n    }\n\n    PyObject *origname = NULL;\n    if (info.origname != NULL && info.origname[0] != '\\0') {\n        origname = PyUnicode_FromString(info.origname);\n        if (origname == NULL) {\n            Py_DECREF(data);\n            return NULL;\n        }\n    }\n\n    PyObject *result = PyTuple_Pack(3, data ? data : Py_None,\n                                    info.is_package ? Py_True : Py_False,\n                                    origname ? origname : Py_None);\n    Py_XDECREF(origname);\n    Py_XDECREF(data);\n    return result;\n}\n\n/*[clinic input]\n_imp.get_frozen_object\n\n    name: unicode\n    data as dataobj: object = None\n    /\n\nCreate a code object for a frozen module.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_get_frozen_object_impl(PyObject *module, PyObject *name,\n                            PyObject *dataobj)\n/*[clinic end generated code: output=54368a673a35e745 input=034bdb88f6460b7b]*/\n{\n    struct frozen_info info = {0};\n    Py_buffer buf = {0};\n    if (PyObject_CheckBuffer(dataobj)) {\n        if (PyObject_GetBuffer(dataobj, &buf, PyBUF_READ) != 0) {\n            return NULL;\n        }\n        info.data = (const char *)buf.buf;\n        info.size = buf.len;\n    }\n    else if (dataobj != Py_None) {\n        _PyArg_BadArgument(\"get_frozen_object\", \"argument 2\", \"bytes\", dataobj);\n        return NULL;\n    }\n    else {\n        frozen_status status = find_frozen(name, &info);\n        if (status != FROZEN_OKAY) {\n            set_frozen_error(status, name);\n            return NULL;\n        }\n    }\n\n    if (info.nameobj == NULL) {\n        info.nameobj = name;\n    }\n    if (info.size == 0 && info.get_code == NULL) {\n        /* Does not contain executable code. */\n        set_frozen_error(FROZEN_INVALID, name);\n        return NULL;\n    }\n\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    PyObject *codeobj = unmarshal_frozen_code(interp, &info);\n    if (dataobj != Py_None) {\n        PyBuffer_Release(&buf);\n    }\n    return codeobj;\n}\n\n/*[clinic input]\n_imp.is_frozen_package\n\n    name: unicode\n    /\n\nReturns True if the module name is of a frozen package.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_is_frozen_package_impl(PyObject *module, PyObject *name)\n/*[clinic end generated code: output=e70cbdb45784a1c9 input=81b6cdecd080fbb8]*/\n{\n    struct frozen_info info;\n    frozen_status status = find_frozen(name, &info);\n    if (status != FROZEN_OKAY && status != FROZEN_EXCLUDED) {\n        set_frozen_error(status, name);\n        return NULL;\n    }\n    return PyBool_FromLong(info.is_package);\n}\n\n/*[clinic input]\n_imp.is_builtin\n\n    name: unicode\n    /\n\nReturns True if the module name corresponds to a built-in module.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_is_builtin_impl(PyObject *module, PyObject *name)\n/*[clinic end generated code: output=3bfd1162e2d3be82 input=86befdac021dd1c7]*/\n{\n    return PyLong_FromLong(is_builtin(name));\n}\n\n/*[clinic input]\n_imp.is_frozen\n\n    name: unicode\n    /\n\nReturns True if the module name corresponds to a frozen module.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_is_frozen_impl(PyObject *module, PyObject *name)\n/*[clinic end generated code: output=01f408f5ec0f2577 input=7301dbca1897d66b]*/\n{\n    struct frozen_info info;\n    frozen_status status = find_frozen(name, &info);\n    if (status != FROZEN_OKAY) {\n        Py_RETURN_FALSE;\n    }\n    Py_RETURN_TRUE;\n}\n\n/*[clinic input]\n_imp._frozen_module_names\n\nReturns the list of available frozen modules.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp__frozen_module_names_impl(PyObject *module)\n/*[clinic end generated code: output=80609ef6256310a8 input=76237fbfa94460d2]*/\n{\n    return list_frozen_module_names();\n}\n\n/*[clinic input]\n_imp._override_frozen_modules_for_tests\n\n    override: int\n    /\n\n(internal-only) Override PyConfig.use_frozen_modules.\n\n(-1: \"off\", 1: \"on\", 0: no override)\nSee frozen_modules() in Lib/test/support/import_helper.py.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp__override_frozen_modules_for_tests_impl(PyObject *module, int override)\n/*[clinic end generated code: output=36d5cb1594160811 input=8f1f95a3ef21aec3]*/\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    OVERRIDE_FROZEN_MODULES(interp) = override;\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\n_imp._override_multi_interp_extensions_check\n\n    override: int\n    /\n\n(internal-only) Override PyInterpreterConfig.check_multi_interp_extensions.\n\n(-1: \"never\", 1: \"always\", 0: no override)\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp__override_multi_interp_extensions_check_impl(PyObject *module,\n                                                  int override)\n/*[clinic end generated code: output=3ff043af52bbf280 input=e086a2ea181f92ae]*/\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (_Py_IsMainInterpreter(interp)) {\n        PyErr_SetString(PyExc_RuntimeError,\n                        \"_imp._override_multi_interp_extensions_check() \"\n                        \"cannot be used in the main interpreter\");\n        return NULL;\n    }\n    int oldvalue = OVERRIDE_MULTI_INTERP_EXTENSIONS_CHECK(interp);\n    OVERRIDE_MULTI_INTERP_EXTENSIONS_CHECK(interp) = override;\n    return PyLong_FromLong(oldvalue);\n}\n\n#ifdef HAVE_DYNAMIC_LOADING\n\n/*[clinic input]\n_imp.create_dynamic\n\n    spec: object\n    file: object = NULL\n    /\n\nCreate an extension module.\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)\n/*[clinic end generated code: output=83249b827a4fde77 input=c31b954f4cf4e09d]*/\n{\n    PyObject *mod, *name, *path;\n    FILE *fp;\n\n    name = PyObject_GetAttrString(spec, \"name\");\n    if (name == NULL) {\n        return NULL;\n    }\n\n    path = PyObject_GetAttrString(spec, \"origin\");\n    if (path == NULL) {\n        Py_DECREF(name);\n        return NULL;\n    }\n\n    PyThreadState *tstate = _PyThreadState_GET();\n    mod = import_find_extension(tstate, name, path);\n    if (mod != NULL) {\n        const char *name_buf = PyUnicode_AsUTF8(name);\n        assert(name_buf != NULL);\n        if (_PyImport_CheckSubinterpIncompatibleExtensionAllowed(name_buf) < 0) {\n            Py_DECREF(mod);\n            mod = NULL;\n        }\n        goto finally;\n    }\n    else if (PyErr_Occurred()) {\n        goto finally;\n    }\n\n    if (file != NULL) {\n        fp = _Py_fopen_obj(path, \"r\");\n        if (fp == NULL) {\n            goto finally;\n        }\n    }\n    else\n        fp = NULL;\n\n    mod = _PyImport_LoadDynamicModuleWithSpec(spec, fp);\n\n    if (fp)\n        fclose(fp);\n\nfinally:\n    Py_DECREF(name);\n    Py_DECREF(path);\n    return mod;\n}\n\n/*[clinic input]\n_imp.exec_dynamic -> int\n\n    mod: object\n    /\n\nInitialize an extension module.\n[clinic start generated code]*/\n\nstatic int\n_imp_exec_dynamic_impl(PyObject *module, PyObject *mod)\n/*[clinic end generated code: output=f5720ac7b465877d input=9fdbfcb250280d3a]*/\n{\n    return exec_builtin_or_dynamic(mod);\n}\n\n\n#endif /* HAVE_DYNAMIC_LOADING */\n\n/*[clinic input]\n_imp.exec_builtin -> int\n\n    mod: object\n    /\n\nInitialize a built-in module.\n[clinic start generated code]*/\n\nstatic int\n_imp_exec_builtin_impl(PyObject *module, PyObject *mod)\n/*[clinic end generated code: output=0262447b240c038e input=7beed5a2f12a60ca]*/\n{\n    return exec_builtin_or_dynamic(mod);\n}\n\n/*[clinic input]\n_imp.source_hash\n\n    key: long\n    source: Py_buffer\n[clinic start generated code]*/\n\nstatic PyObject *\n_imp_source_hash_impl(PyObject *module, long key, Py_buffer *source)\n/*[clinic end generated code: output=edb292448cf399ea input=9aaad1e590089789]*/\n{\n    union {\n        uint64_t x;\n        char data[sizeof(uint64_t)];\n    } hash;\n    hash.x = _Py_KeyedHash((uint64_t)key, source->buf, source->len);\n#if !PY_LITTLE_ENDIAN\n    // Force to little-endian. There really ought to be a succinct standard way\n    // to do this.\n    for (size_t i = 0; i < sizeof(hash.data)/2; i++) {\n        char tmp = hash.data[i];\n        hash.data[i] = hash.data[sizeof(hash.data) - i - 1];\n        hash.data[sizeof(hash.data) - i - 1] = tmp;\n    }\n#endif\n    return PyBytes_FromStringAndSize(hash.data, sizeof(hash.data));\n}\n\n\nPyDoc_STRVAR(doc_imp,\n\"(Extremely) low-level import machinery bits as used by importlib.\");\n\nstatic PyMethodDef imp_methods[] = {\n    _IMP_EXTENSION_SUFFIXES_METHODDEF\n    _IMP_LOCK_HELD_METHODDEF\n    _IMP_ACQUIRE_LOCK_METHODDEF\n    _IMP_RELEASE_LOCK_METHODDEF\n    _IMP_FIND_FROZEN_METHODDEF\n    _IMP_GET_FROZEN_OBJECT_METHODDEF\n    _IMP_IS_FROZEN_PACKAGE_METHODDEF\n    _IMP_CREATE_BUILTIN_METHODDEF\n    _IMP_INIT_FROZEN_METHODDEF\n    _IMP_IS_BUILTIN_METHODDEF\n    _IMP_IS_FROZEN_METHODDEF\n    _IMP__FROZEN_MODULE_NAMES_METHODDEF\n    _IMP__OVERRIDE_FROZEN_MODULES_FOR_TESTS_METHODDEF\n    _IMP__OVERRIDE_MULTI_INTERP_EXTENSIONS_CHECK_METHODDEF\n    _IMP_CREATE_DYNAMIC_METHODDEF\n    _IMP_EXEC_DYNAMIC_METHODDEF\n    _IMP_EXEC_BUILTIN_METHODDEF\n    _IMP__FIX_CO_FILENAME_METHODDEF\n    _IMP_SOURCE_HASH_METHODDEF\n    {NULL, NULL}  /* sentinel */\n};\n\n\nstatic int\nimp_module_exec(PyObject *module)\n{\n    const wchar_t *mode = _Py_GetConfig()->check_hash_pycs_mode;\n    PyObject *pyc_mode = PyUnicode_FromWideChar(mode, -1);\n    if (pyc_mode == NULL) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(module, \"check_hash_based_pycs\", pyc_mode) < 0) {\n        Py_DECREF(pyc_mode);\n        return -1;\n    }\n    Py_DECREF(pyc_mode);\n\n    return 0;\n}\n\n\nstatic PyModuleDef_Slot imp_slots[] = {\n    {Py_mod_exec, imp_module_exec},\n    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},\n    {0, NULL}\n};\n\nstatic struct PyModuleDef imp_module = {\n    PyModuleDef_HEAD_INIT,\n    .m_name = \"_imp\",\n    .m_doc = doc_imp,\n    .m_size = 0,\n    .m_methods = imp_methods,\n    .m_slots = imp_slots,\n};\n\nPyMODINIT_FUNC\nPyInit__imp(void)\n{\n    return PyModuleDef_Init(&imp_module);\n}\n\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "ImPortdl.c",
    "content": "\n/* Support for dynamic loading of extension modules */\n\n#include \"Python.h\"\n#include \"pycore_call.h\"\n#include \"pycore_import.h\"\n#include \"pycore_pystate.h\"\n#include \"pycore_runtime.h\"\n\n/* ./configure sets HAVE_DYNAMIC_LOADING if dynamic loading of modules is\n   supported on this platform. configure will then compile and link in one\n   of the dynload_*.c files, as appropriate. We will call a function in\n   those modules to get a function pointer to the module's init function.\n*/\n#ifdef HAVE_DYNAMIC_LOADING\n\n#include \"importdl.h\"\n\n#ifdef MS_WINDOWS\nextern dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,\n                                                     const char *shortname,\n                                                     PyObject *pathname,\n                                                     FILE *fp);\n#else\nextern dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix,\n                                              const char *shortname,\n                                              const char *pathname, FILE *fp);\n#endif\n\nstatic const char * const ascii_only_prefix = \"PyInit\";\nstatic const char * const nonascii_prefix = \"PyInitU\";\n\n/* Get the variable part of a module's export symbol name.\n * Returns a bytes instance. For non-ASCII-named modules, the name is\n * encoded as per PEP 489.\n * The hook_prefix pointer is set to either ascii_only_prefix or\n * nonascii_prefix, as appropriate.\n */\nstatic PyObject *\nget_encoded_name(PyObject *name, const char **hook_prefix) {\n    PyObject *tmp;\n    PyObject *encoded = NULL;\n    PyObject *modname = NULL;\n    Py_ssize_t name_len, lastdot;\n\n    /* Get the short name (substring after last dot) */\n    name_len = PyUnicode_GetLength(name);\n    if (name_len < 0) {\n        return NULL;\n    }\n    lastdot = PyUnicode_FindChar(name, '.', 0, name_len, -1);\n    if (lastdot < -1) {\n        return NULL;\n    } else if (lastdot >= 0) {\n        tmp = PyUnicode_Substring(name, lastdot + 1, name_len);\n        if (tmp == NULL)\n            return NULL;\n        name = tmp;\n        /* \"name\" now holds a new reference to the substring */\n    } else {\n        Py_INCREF(name);\n    }\n\n    /* Encode to ASCII or Punycode, as needed */\n    encoded = PyUnicode_AsEncodedString(name, \"ascii\", NULL);\n    if (encoded != NULL) {\n        *hook_prefix = ascii_only_prefix;\n    } else {\n        if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {\n            PyErr_Clear();\n            encoded = PyUnicode_AsEncodedString(name, \"punycode\", NULL);\n            if (encoded == NULL) {\n                goto error;\n            }\n            *hook_prefix = nonascii_prefix;\n        } else {\n            goto error;\n        }\n    }\n\n    /* Replace '-' by '_' */\n    modname = _PyObject_CallMethod(encoded, &_Py_ID(replace), \"cc\", '-', '_');\n    if (modname == NULL)\n        goto error;\n\n    Py_DECREF(name);\n    Py_DECREF(encoded);\n    return modname;\nerror:\n    Py_DECREF(name);\n    Py_XDECREF(encoded);\n    return NULL;\n}\n\nPyObject *\n_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp)\n{\n#ifndef MS_WINDOWS\n    PyObject *pathbytes = NULL;\n#endif\n    PyObject *name_unicode = NULL, *name = NULL, *path = NULL, *m = NULL;\n    const char *name_buf, *hook_prefix;\n    const char *oldcontext, *newcontext;\n    dl_funcptr exportfunc;\n    PyModuleDef *def;\n    PyModInitFunction p0;\n\n    name_unicode = PyObject_GetAttrString(spec, \"name\");\n    if (name_unicode == NULL) {\n        return NULL;\n    }\n    if (!PyUnicode_Check(name_unicode)) {\n        PyErr_SetString(PyExc_TypeError,\n                        \"spec.name must be a string\");\n        goto error;\n    }\n    newcontext = PyUnicode_AsUTF8(name_unicode);\n    if (newcontext == NULL) {\n        goto error;\n    }\n\n    name = get_encoded_name(name_unicode, &hook_prefix);\n    if (name == NULL) {\n        goto error;\n    }\n    name_buf = PyBytes_AS_STRING(name);\n\n    path = PyObject_GetAttrString(spec, \"origin\");\n    if (path == NULL)\n        goto error;\n\n    if (PySys_Audit(\"import\", \"OOOOO\", name_unicode, path,\n                    Py_None, Py_None, Py_None) < 0) {\n        goto error;\n    }\n\n#ifdef MS_WINDOWS\n    exportfunc = _PyImport_FindSharedFuncptrWindows(hook_prefix, name_buf,\n                                                    path, fp);\n#else\n    pathbytes = PyUnicode_EncodeFSDefault(path);\n    if (pathbytes == NULL)\n        goto error;\n    exportfunc = _PyImport_FindSharedFuncptr(hook_prefix, name_buf,\n                                             PyBytes_AS_STRING(pathbytes),\n                                             fp);\n    Py_DECREF(pathbytes);\n#endif\n\n    if (exportfunc == NULL) {\n        if (!PyErr_Occurred()) {\n            PyObject *msg;\n            msg = PyUnicode_FromFormat(\n                \"dynamic module does not define \"\n                \"module export function (%s_%s)\",\n                hook_prefix, name_buf);\n            if (msg == NULL)\n                goto error;\n            PyErr_SetImportError(msg, name_unicode, path);\n            Py_DECREF(msg);\n        }\n        goto error;\n    }\n\n    p0 = (PyModInitFunction)exportfunc;\n\n    /* Package context is needed for single-phase init */\n    oldcontext = _PyImport_SwapPackageContext(newcontext);\n    m = _PyImport_InitFunc_TrampolineCall(p0);\n    _PyImport_SwapPackageContext(oldcontext);\n\n    if (m == NULL) {\n        if (!PyErr_Occurred()) {\n            PyErr_Format(\n                PyExc_SystemError,\n                \"initialization of %s failed without raising an exception\",\n                name_buf);\n        }\n        goto error;\n    } else if (PyErr_Occurred()) {\n        _PyErr_FormatFromCause(\n            PyExc_SystemError,\n            \"initialization of %s raised unreported exception\",\n            name_buf);\n        m = NULL;\n        goto error;\n    }\n    if (Py_IS_TYPE(m, NULL)) {\n        /* This can happen when a PyModuleDef is returned without calling\n         * PyModuleDef_Init on it\n         */\n        PyErr_Format(PyExc_SystemError,\n                     \"init function of %s returned uninitialized object\",\n                     name_buf);\n        m = NULL; /* prevent segfault in DECREF */\n        goto error;\n    }\n    if (PyObject_TypeCheck(m, &PyModuleDef_Type)) {\n        Py_DECREF(name_unicode);\n        Py_DECREF(name);\n        Py_DECREF(path);\n        return PyModule_FromDefAndSpec((PyModuleDef*)m, spec);\n    }\n\n    /* Fall back to single-phase init mechanism */\n\n    if (_PyImport_CheckSubinterpIncompatibleExtensionAllowed(name_buf) < 0) {\n        goto error;\n    }\n\n    if (hook_prefix == nonascii_prefix) {\n        /* don't allow legacy init for non-ASCII module names */\n        PyErr_Format(\n            PyExc_SystemError,\n            \"initialization of %s did not return PyModuleDef\",\n            name_buf);\n        goto error;\n    }\n\n    /* Remember pointer to module init function. */\n    def = PyModule_GetDef(m);\n    if (def == NULL) {\n        PyErr_Format(PyExc_SystemError,\n                     \"initialization of %s did not return an extension \"\n                     \"module\", name_buf);\n        goto error;\n    }\n    def->m_base.m_init = p0;\n\n    /* Remember the filename as the __file__ attribute */\n    if (PyModule_AddObjectRef(m, \"__file__\", path) < 0) {\n        PyErr_Clear(); /* Not important enough to report */\n    }\n\n    PyObject *modules = PyImport_GetModuleDict();\n    if (_PyImport_FixupExtensionObject(m, name_unicode, path, modules) < 0)\n        goto error;\n\n    Py_DECREF(name_unicode);\n    Py_DECREF(name);\n    Py_DECREF(path);\n\n    return m;\n\nerror:\n    Py_DECREF(name_unicode);\n    Py_XDECREF(name);\n    Py_XDECREF(path);\n    Py_XDECREF(m);\n    return NULL;\n}\n\n#endif /* HAVE_DYNAMIC_LOADING */\n"
  },
  {
    "path": "ImPortdl.h",
    "content": "#ifndef Py_IMPORTDL_H\n#define Py_IMPORTDL_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\nextern const char *_PyImport_DynLoadFiletab[];\n\nextern PyObject *_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *);\n\ntypedef PyObject *(*PyModInitFunction)(void);\n\n#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)\nextern PyObject *_PyImport_InitFunc_TrampolineCall(PyModInitFunction func);\n#else\n#define _PyImport_InitFunc_TrampolineCall(func) (func)()\n#endif\n\n/* Max length of module suffix searched for -- accommodates \"module.slb\" */\n#define MAXSUFFIXSIZE 12\n\n#ifdef MS_WINDOWS\n#include <windows.h>\ntypedef FARPROC dl_funcptr;\n#else\ntypedef void (*dl_funcptr)(void);\n#endif\n\n\n#ifdef __cplusplus\n}\n#endif\n#endif /* !Py_IMPORTDL_H */\n"
  },
  {
    "path": "InTrinSics.c",
    "content": "\n#define _PY_INTERPRETER\n\n#include \"Python.h\"\n#include \"pycore_frame.h\"\n#include \"pycore_function.h\"\n#include \"pycore_runtime.h\"\n#include \"pycore_global_objects.h\"\n#include \"pycore_intrinsics.h\"\n#include \"pycore_pyerrors.h\"\n#include \"pycore_typevarobject.h\"\n\n\n/******** Unary functions ********/\n\nstatic PyObject *\nno_intrinsic(PyThreadState* tstate, PyObject *unused)\n{\n    _PyErr_SetString(tstate, PyExc_SystemError, \"invalid intrinsic function\");\n    return NULL;\n}\n\nstatic PyObject *\nprint_expr(PyThreadState* tstate, PyObject *value)\n{\n    PyObject *hook = _PySys_GetAttr(tstate, &_Py_ID(displayhook));\n    // Can't use ERROR_IF here.\n    if (hook == NULL) {\n        _PyErr_SetString(tstate, PyExc_RuntimeError,\n                            \"lost sys.displayhook\");\n        return NULL;\n    }\n    return PyObject_CallOneArg(hook, value);\n}\n\nstatic int\nimport_all_from(PyThreadState *tstate, PyObject *locals, PyObject *v)\n{\n    PyObject *all, *dict, *name, *value;\n    int skip_leading_underscores = 0;\n    int pos, err;\n\n    if (_PyObject_LookupAttr(v, &_Py_ID(__all__), &all) < 0) {\n        return -1; /* Unexpected error */\n    }\n    if (all == NULL) {\n        if (_PyObject_LookupAttr(v, &_Py_ID(__dict__), &dict) < 0) {\n            return -1;\n        }\n        if (dict == NULL) {\n            _PyErr_SetString(tstate, PyExc_ImportError,\n                    \"from-import-* object has no __dict__ and no __all__\");\n            return -1;\n        }\n        all = PyMapping_Keys(dict);\n        Py_DECREF(dict);\n        if (all == NULL)\n            return -1;\n        skip_leading_underscores = 1;\n    }\n\n    for (pos = 0, err = 0; ; pos++) {\n        name = PySequence_GetItem(all, pos);\n        if (name == NULL) {\n            if (!_PyErr_ExceptionMatches(tstate, PyExc_IndexError)) {\n                err = -1;\n            }\n            else {\n                _PyErr_Clear(tstate);\n            }\n            break;\n        }\n        if (!PyUnicode_Check(name)) {\n            PyObject *modname = PyObject_GetAttr(v, &_Py_ID(__name__));\n            if (modname == NULL) {\n                Py_DECREF(name);\n                err = -1;\n                break;\n            }\n            if (!PyUnicode_Check(modname)) {\n                _PyErr_Format(tstate, PyExc_TypeError,\n                              \"module __name__ must be a string, not %.100s\",\n                              Py_TYPE(modname)->tp_name);\n            }\n            else {\n                _PyErr_Format(tstate, PyExc_TypeError,\n                              \"%s in %U.%s must be str, not %.100s\",\n                              skip_leading_underscores ? \"Key\" : \"Item\",\n                              modname,\n                              skip_leading_underscores ? \"__dict__\" : \"__all__\",\n                              Py_TYPE(name)->tp_name);\n            }\n            Py_DECREF(modname);\n            Py_DECREF(name);\n            err = -1;\n            break;\n        }\n        if (skip_leading_underscores) {\n            if (PyUnicode_READ_CHAR(name, 0) == '_') {\n                Py_DECREF(name);\n                continue;\n            }\n        }\n        value = PyObject_GetAttr(v, name);\n        if (value == NULL)\n            err = -1;\n        else if (PyDict_CheckExact(locals))\n            err = PyDict_SetItem(locals, name, value);\n        else\n            err = PyObject_SetItem(locals, name, value);\n        Py_DECREF(name);\n        Py_XDECREF(value);\n        if (err < 0)\n            break;\n    }\n    Py_DECREF(all);\n    return err;\n}\n\nstatic PyObject *\nimport_star(PyThreadState* tstate, PyObject *from)\n{\n    _PyInterpreterFrame *frame = tstate->cframe->current_frame;\n    if (_PyFrame_FastToLocalsWithError(frame) < 0) {\n        return NULL;\n    }\n\n    PyObject *locals = frame->f_locals;\n    if (locals == NULL) {\n        _PyErr_SetString(tstate, PyExc_SystemError,\n                            \"no locals found during 'import *'\");\n        return NULL;\n    }\n    int err = import_all_from(tstate, locals, from);\n    _PyFrame_LocalsToFast(frame, 0);\n    if (err < 0) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\nstatic PyObject *\nstopiteration_error(PyThreadState* tstate, PyObject *exc)\n{\n    _PyInterpreterFrame *frame = tstate->cframe->current_frame;\n    assert(frame->owner == FRAME_OWNED_BY_GENERATOR);\n    assert(PyExceptionInstance_Check(exc));\n    const char *msg = NULL;\n    if (PyErr_GivenExceptionMatches(exc, PyExc_StopIteration)) {\n        msg = \"generator raised StopIteration\";\n        if (frame->f_code->co_flags & CO_ASYNC_GENERATOR) {\n            msg = \"async generator raised StopIteration\";\n        }\n        else if (frame->f_code->co_flags & CO_COROUTINE) {\n            msg = \"coroutine raised StopIteration\";\n        }\n    }\n    else if ((frame->f_code->co_flags & CO_ASYNC_GENERATOR) &&\n            PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration))\n    {\n        /* code in `gen` raised a StopAsyncIteration error:\n        raise a RuntimeError.\n        */\n        msg = \"async generator raised StopAsyncIteration\";\n    }\n    if (msg != NULL) {\n        PyObject *message = _PyUnicode_FromASCII(msg, strlen(msg));\n        if (message == NULL) {\n            return NULL;\n        }\n        PyObject *error = PyObject_CallOneArg(PyExc_RuntimeError, message);\n        if (error == NULL) {\n            Py_DECREF(message);\n            return NULL;\n        }\n        assert(PyExceptionInstance_Check(error));\n        PyException_SetCause(error, Py_NewRef(exc));\n        // Steal exc reference, rather than Py_NewRef+Py_DECREF\n        PyException_SetContext(error, Py_NewRef(exc));\n        Py_DECREF(message);\n        return error;\n    }\n    return Py_NewRef(exc);\n}\n\nstatic PyObject *\nunary_pos(PyThreadState* unused, PyObject *value)\n{\n    return PyNumber_Positive(value);\n}\n\nstatic PyObject *\nlist_to_tuple(PyThreadState* unused, PyObject *v)\n{\n    assert(PyList_Check(v));\n    return _PyTuple_FromArray(((PyListObject *)v)->ob_item, Py_SIZE(v));\n}\n\nstatic PyObject *\nmake_typevar(PyThreadState* Py_UNUSED(ignored), PyObject *v)\n{\n    assert(PyUnicode_Check(v));\n    return _Py_make_typevar(v, NULL, NULL);\n}\n\nconst instrinsic_func1\n_PyIntrinsics_UnaryFunctions[] = {\n    [0] = no_intrinsic,\n    [INTRINSIC_PRINT] = print_expr,\n    [INTRINSIC_IMPORT_STAR] = import_star,\n    [INTRINSIC_STOPITERATION_ERROR] = stopiteration_error,\n    [INTRINSIC_ASYNC_GEN_WRAP] = _PyAsyncGenValueWrapperNew,\n    [INTRINSIC_UNARY_POSITIVE] = unary_pos,\n    [INTRINSIC_LIST_TO_TUPLE] = list_to_tuple,\n    [INTRINSIC_TYPEVAR] = make_typevar,\n    [INTRINSIC_PARAMSPEC] = _Py_make_paramspec,\n    [INTRINSIC_TYPEVARTUPLE] = _Py_make_typevartuple,\n    [INTRINSIC_SUBSCRIPT_GENERIC] = _Py_subscript_generic,\n    [INTRINSIC_TYPEALIAS] = _Py_make_typealias,\n};\n\n\n/******** Binary functions ********/\n\n\nstatic PyObject *\nprep_reraise_star(PyThreadState* unused, PyObject *orig, PyObject *excs)\n{\n    assert(PyList_Check(excs));\n    return _PyExc_PrepReraiseStar(orig, excs);\n}\n\nstatic PyObject *\nmake_typevar_with_bound(PyThreadState* Py_UNUSED(ignored), PyObject *name,\n                        PyObject *evaluate_bound)\n{\n    assert(PyUnicode_Check(name));\n    return _Py_make_typevar(name, evaluate_bound, NULL);\n}\n\nstatic PyObject *\nmake_typevar_with_constraints(PyThreadState* Py_UNUSED(ignored), PyObject *name,\n                              PyObject *evaluate_constraints)\n{\n    assert(PyUnicode_Check(name));\n    return _Py_make_typevar(name, NULL, evaluate_constraints);\n}\n\nconst instrinsic_func2\n_PyIntrinsics_BinaryFunctions[] = {\n    [INTRINSIC_PREP_RERAISE_STAR] = prep_reraise_star,\n    [INTRINSIC_TYPEVAR_WITH_BOUND] = make_typevar_with_bound,\n    [INTRINSIC_TYPEVAR_WITH_CONSTRAINTS] = make_typevar_with_constraints,\n    [INTRINSIC_SET_FUNCTION_TYPE_PARAMS] = _Py_set_function_type_params,\n};\n"
  },
  {
    "path": "InitConfig.c",
    "content": "#include \"Python.h\"\n#include \"pycore_fileutils.h\"     // _Py_HasFileSystemDefaultEncodeErrors\n#include \"pycore_getopt.h\"        // _PyOS_GetOpt()\n#include \"pycore_initconfig.h\"    // _PyStatus_OK()\n#include \"pycore_interp.h\"        // _PyInterpreterState.runtime\n#include \"pycore_long.h\"          // _PY_LONG_MAX_STR_DIGITS_THRESHOLD\n#include \"pycore_pathconfig.h\"    // _Py_path_config\n#include \"pycore_pyerrors.h\"      // _PyErr_GetRaisedException()\n#include \"pycore_pylifecycle.h\"   // _Py_PreInitializeFromConfig()\n#include \"pycore_pymem.h\"         // _PyMem_SetDefaultAllocator()\n#include \"pycore_pystate.h\"       // _PyThreadState_GET()\n\n#include \"osdefs.h\"               // DELIM\n\n#include <locale.h>               // setlocale()\n#include <stdlib.h>               // getenv()\n#if defined(MS_WINDOWS) || defined(__CYGWIN__)\n#  ifdef HAVE_IO_H\n#    include <io.h>\n#  endif\n#  ifdef HAVE_FCNTL_H\n#    include <fcntl.h>            // O_BINARY\n#  endif\n#endif\n\n/* --- Command line options --------------------------------------- */\n\n/* Short usage message (with %s for argv0) */\nstatic const char usage_line[] =\n\"usage: %ls [option] ... [-c cmd | -m mod | file | -] [arg] ...\\n\";\n\n/* Long help message */\n/* Lines sorted by option name; keep in sync with usage_envvars* below */\nstatic const char usage_help[] = \"\\\nOptions (and corresponding environment variables):\\n\\\n-b     : issue warnings about str(bytes_instance), str(bytearray_instance)\\n\\\n         and comparing bytes/bytearray with str. (-bb: issue errors)\\n\\\n-B     : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x\\n\\\n-c cmd : program passed in as string (terminates option list)\\n\\\n-d     : turn on parser debugging output (for experts only, only works on\\n\\\n         debug builds); also PYTHONDEBUG=x\\n\\\n-E     : ignore PYTHON* environment variables (such as PYTHONPATH)\\n\\\n-h     : print this help message and exit (also -? or --help)\\n\\\n-i     : inspect interactively after running script; forces a prompt even\\n\\\n         if stdin does not appear to be a terminal; also PYTHONINSPECT=x\\n\\\n-I     : isolate Python from the user's environment (implies -E and -s)\\n\\\n-m mod : run library module as a script (terminates option list)\\n\\\n-O     : remove assert and __debug__-dependent statements; add .opt-1 before\\n\\\n         .pyc extension; also PYTHONOPTIMIZE=x\\n\\\n-OO    : do -O changes and also discard docstrings; add .opt-2 before\\n\\\n         .pyc extension\\n\\\n-P     : don't prepend a potentially unsafe path to sys.path\\n\\\n-q     : don't print version and copyright messages on interactive startup\\n\\\n-s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE\\n\\\n-S     : don't imply 'import site' on initialization\\n\\\n-u     : force the stdout and stderr streams to be unbuffered;\\n\\\n         this option has no effect on stdin; also PYTHONUNBUFFERED=x\\n\\\n-v     : verbose (trace import statements); also PYTHONVERBOSE=x\\n\\\n         can be supplied multiple times to increase verbosity\\n\\\n-V     : print the Python version number and exit (also --version)\\n\\\n         when given twice, print more information about the build\\n\\\n-W arg : warning control; arg is action:message:category:module:lineno\\n\\\n         also PYTHONWARNINGS=arg\\n\\\n-x     : skip first line of source, allowing use of non-Unix forms of #!cmd\\n\\\n-X opt : set implementation-specific option\\n\\\n--check-hash-based-pycs always|default|never:\\n\\\n         control how Python invalidates hash-based .pyc files\\n\\\n--help-env      : print help about Python environment variables and exit\\n\\\n--help-xoptions : print help about implementation-specific -X options and exit\\n\\\n--help-all      : print complete help information and exit\\n\\\nArguments:\\n\\\nfile   : program read from script file\\n\\\n-      : program read from stdin (default; interactive mode if a tty)\\n\\\narg ...: arguments passed to program in sys.argv[1:]\\n\\\n\";\n\nstatic const char usage_xoptions[] = \"\\\nThe following implementation-specific options are available:\\n\\\n\\n\\\n-X faulthandler: enable faulthandler\\n\\\n\\n\\\n-X showrefcount: output the total reference count and number of used\\n\\\n    memory blocks when the program finishes or after each statement in the\\n\\\n    interactive interpreter. This only works on debug builds\\n\\\n\\n\\\n-X tracemalloc: start tracing Python memory allocations using the\\n\\\n    tracemalloc module. By default, only the most recent frame is stored in a\\n\\\n    traceback of a trace. Use -X tracemalloc=NFRAME to start tracing with a\\n\\\n    traceback limit of NFRAME frames\\n\\\n\\n\\\n-X importtime: show how long each import takes. It shows module name,\\n\\\n    cumulative time (including nested imports) and self time (excluding\\n\\\n    nested imports). Note that its output may be broken in multi-threaded\\n\\\n    application. Typical usage is python3 -X importtime -c 'import asyncio'\\n\\\n\\n\\\n-X dev: enable CPython's \\\"development mode\\\", introducing additional runtime\\n\\\n    checks which are too expensive to be enabled by default. Effect of the\\n\\\n    developer mode:\\n\\\n       * Add default warning filter, as -W default\\n\\\n       * Install debug hooks on memory allocators: see the PyMem_SetupDebugHooks()\\n\\\n         C function\\n\\\n       * Enable the faulthandler module to dump the Python traceback on a crash\\n\\\n       * Enable asyncio debug mode\\n\\\n       * Set the dev_mode attribute of sys.flags to True\\n\\\n       * io.IOBase destructor logs close() exceptions\\n\\\n\\n\\\n-X utf8: enable UTF-8 mode for operating system interfaces, overriding the default\\n\\\n    locale-aware mode. -X utf8=0 explicitly disables UTF-8 mode (even when it would\\n\\\n    otherwise activate automatically)\\n\\\n\\n\\\n-X pycache_prefix=PATH: enable writing .pyc files to a parallel tree rooted at the\\n\\\n    given directory instead of to the code tree\\n\\\n\\n\\\n-X warn_default_encoding: enable opt-in EncodingWarning for 'encoding=None'\\n\\\n\\n\\\n-X no_debug_ranges: disable the inclusion of the tables mapping extra location \\n\\\n   information (end line, start column offset and end column offset) to every \\n\\\n   instruction in code objects. This is useful when smaller code objects and pyc \\n\\\n   files are desired as well as suppressing the extra visual location indicators \\n\\\n   when the interpreter displays tracebacks.\\n\\\n\\n\\\n-X perf: activate support for the Linux \\\"perf\\\" profiler by activating the \\\"perf\\\"\\n\\\n    trampoline. When this option is activated, the Linux \\\"perf\\\" profiler will be \\n\\\n    able to report Python calls. This option is only available on some platforms and will \\n\\\n    do nothing if is not supported on the current system. The default value is \\\"off\\\".\\n\\\n\\n\\\n-X frozen_modules=[on|off]: whether or not frozen modules should be used.\\n\\\n   The default is \\\"on\\\" (or \\\"off\\\" if you are running a local build).\\n\\\n\\n\\\n-X int_max_str_digits=number: limit the size of int<->str conversions.\\n\\\n    This helps avoid denial of service attacks when parsing untrusted data.\\n\\\n    The default is sys.int_info.default_max_str_digits.  0 disables.\"\n\n#ifdef Py_STATS\n\"\\n\\\n\\n\\\n-X pystats: Enable pystats collection at startup.\"\n#endif\n;\n\n/* Envvars that don't have equivalent command-line options are listed first */\nstatic const char usage_envvars[] =\n\"Environment variables that change behavior:\\n\"\n\"PYTHONSTARTUP: file executed on interactive startup (no default)\\n\"\n\"PYTHONPATH   : '%lc'-separated list of directories prefixed to the\\n\"\n\"               default module search path.  The result is sys.path.\\n\"\n\"PYTHONSAFEPATH: don't prepend a potentially unsafe path to sys.path.\\n\"\n\"PYTHONHOME   : alternate <prefix> directory (or <prefix>%lc<exec_prefix>).\\n\"\n\"               The default module search path uses %s.\\n\"\n\"PYTHONPLATLIBDIR : override sys.platlibdir.\\n\"\n\"PYTHONCASEOK : ignore case in 'import' statements (Windows).\\n\"\n\"PYTHONUTF8: if set to 1, enable the UTF-8 mode.\\n\"\n\"PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\\n\"\n\"PYTHONFAULTHANDLER: dump the Python traceback on fatal errors.\\n\"\n\"PYTHONHASHSEED: if this variable is set to 'random', a random value is used\\n\"\n\"   to seed the hashes of str and bytes objects.  It can also be set to an\\n\"\n\"   integer in the range [0,4294967295] to get hash values with a\\n\"\n\"   predictable seed.\\n\"\n\"PYTHONINTMAXSTRDIGITS: limits the maximum digit characters in an int value\\n\"\n\"   when converting from a string and when converting an int back to a str.\\n\"\n\"   A value of 0 disables the limit.  Conversions to or from bases 2, 4, 8,\\n\"\n\"   16, and 32 are never limited.\\n\"\n\"PYTHONMALLOC: set the Python memory allocators and/or install debug hooks\\n\"\n\"   on Python memory allocators. Use PYTHONMALLOC=debug to install debug\\n\"\n\"   hooks.\\n\"\n\"PYTHONCOERCECLOCALE: if this variable is set to 0, it disables the locale\\n\"\n\"   coercion behavior. Use PYTHONCOERCECLOCALE=warn to request display of\\n\"\n\"   locale coercion and locale compatibility warnings on stderr.\\n\"\n\"PYTHONBREAKPOINT: if this variable is set to 0, it disables the default\\n\"\n\"   debugger. It can be set to the callable of your debugger of choice.\\n\"\n\"PYTHONDEVMODE: enable the development mode.\\n\"\n\"PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files.\\n\"\n\"PYTHONWARNDEFAULTENCODING: enable opt-in EncodingWarning for 'encoding=None'.\\n\"\n\"PYTHONNODEBUGRANGES: If this variable is set, it disables the inclusion of the \\n\"\n\"   tables mapping extra location information (end line, start column offset \\n\"\n\"   and end column offset) to every instruction in code objects. This is useful \\n\"\n\"   when smaller code objects and pyc files are desired as well as suppressing the \\n\"\n\"   extra visual location indicators when the interpreter displays tracebacks.\\n\"\n\"These variables have equivalent command-line parameters (see --help for details):\\n\"\n\"PYTHONDEBUG             : enable parser debug mode (-d)\\n\"\n\"PYTHONDONTWRITEBYTECODE : don't write .pyc files (-B)\\n\"\n\"PYTHONINSPECT           : inspect interactively after running script (-i)\\n\"\n\"PYTHONINTMAXSTRDIGITS   : limit max digit characters in an int value\\n\"\n\"                          (-X int_max_str_digits=number)\\n\"\n\"PYTHONNOUSERSITE        : disable user site directory (-s)\\n\"\n\"PYTHONOPTIMIZE          : enable level 1 optimizations (-O)\\n\"\n\"PYTHONUNBUFFERED        : disable stdout/stderr buffering (-u)\\n\"\n\"PYTHONVERBOSE           : trace import statements (-v)\\n\"\n\"PYTHONWARNINGS=arg      : warning control (-W arg)\\n\";\n\n#if defined(MS_WINDOWS)\n#  define PYTHONHOMEHELP \"<prefix>\\\\python{major}{minor}\"\n#else\n#  define PYTHONHOMEHELP \"<prefix>/lib/pythonX.X\"\n#endif\n\n\n/* --- Global configuration variables ----------------------------- */\n\n/* UTF-8 mode (PEP 540): if equals to 1, use the UTF-8 encoding, and change\n   stdin and stdout error handler to \"surrogateescape\". */\nint Py_UTF8Mode = 0;\nint Py_DebugFlag = 0; /* Needed by parser.c */\nint Py_VerboseFlag = 0; /* Needed by import.c */\nint Py_QuietFlag = 0; /* Needed by sysmodule.c */\nint Py_InteractiveFlag = 0; /* Previously, was used by Py_FdIsInteractive() */\nint Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */\nint Py_OptimizeFlag = 0; /* Needed by compile.c */\nint Py_NoSiteFlag = 0; /* Suppress 'import site' */\nint Py_BytesWarningFlag = 0; /* Warn on str(bytes) and str(buffer) */\nint Py_FrozenFlag = 0; /* Needed by getpath.c */\nint Py_IgnoreEnvironmentFlag = 0; /* e.g. PYTHONPATH, PYTHONHOME */\nint Py_DontWriteBytecodeFlag = 0; /* Suppress writing bytecode files (*.pyc) */\nint Py_NoUserSiteDirectory = 0; /* for -s and site.py */\nint Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */\nint Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */\nint Py_IsolatedFlag = 0; /* for -I, isolate from user's env */\n#ifdef MS_WINDOWS\nint Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */\nint Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */\n#endif\n\n\nstatic PyObject *\n_Py_GetGlobalVariablesAsDict(void)\n{\n_Py_COMP_DIAG_PUSH\n_Py_COMP_DIAG_IGNORE_DEPR_DECLS\n    PyObject *dict, *obj;\n\n    dict = PyDict_New();\n    if (dict == NULL) {\n        return NULL;\n    }\n\n#define SET_ITEM(KEY, EXPR) \\\n        do { \\\n            obj = (EXPR); \\\n            if (obj == NULL) { \\\n                return NULL; \\\n            } \\\n            int res = PyDict_SetItemString(dict, (KEY), obj); \\\n            Py_DECREF(obj); \\\n            if (res < 0) { \\\n                goto fail; \\\n            } \\\n        } while (0)\n#define SET_ITEM_INT(VAR) \\\n    SET_ITEM(#VAR, PyLong_FromLong(VAR))\n#define FROM_STRING(STR) \\\n    ((STR != NULL) ? \\\n        PyUnicode_FromString(STR) \\\n        : Py_NewRef(Py_None))\n#define SET_ITEM_STR(VAR) \\\n    SET_ITEM(#VAR, FROM_STRING(VAR))\n\n    SET_ITEM_STR(Py_FileSystemDefaultEncoding);\n    SET_ITEM_INT(Py_HasFileSystemDefaultEncoding);\n    SET_ITEM_STR(Py_FileSystemDefaultEncodeErrors);\n    SET_ITEM_INT(_Py_HasFileSystemDefaultEncodeErrors);\n\n    SET_ITEM_INT(Py_UTF8Mode);\n    SET_ITEM_INT(Py_DebugFlag);\n    SET_ITEM_INT(Py_VerboseFlag);\n    SET_ITEM_INT(Py_QuietFlag);\n    SET_ITEM_INT(Py_InteractiveFlag);\n    SET_ITEM_INT(Py_InspectFlag);\n\n    SET_ITEM_INT(Py_OptimizeFlag);\n    SET_ITEM_INT(Py_NoSiteFlag);\n    SET_ITEM_INT(Py_BytesWarningFlag);\n    SET_ITEM_INT(Py_FrozenFlag);\n    SET_ITEM_INT(Py_IgnoreEnvironmentFlag);\n    SET_ITEM_INT(Py_DontWriteBytecodeFlag);\n    SET_ITEM_INT(Py_NoUserSiteDirectory);\n    SET_ITEM_INT(Py_UnbufferedStdioFlag);\n    SET_ITEM_INT(Py_HashRandomizationFlag);\n    SET_ITEM_INT(Py_IsolatedFlag);\n\n#ifdef MS_WINDOWS\n    SET_ITEM_INT(Py_LegacyWindowsFSEncodingFlag);\n    SET_ITEM_INT(Py_LegacyWindowsStdioFlag);\n#endif\n\n    return dict;\n\nfail:\n    Py_DECREF(dict);\n    return NULL;\n\n#undef FROM_STRING\n#undef SET_ITEM\n#undef SET_ITEM_INT\n#undef SET_ITEM_STR\n_Py_COMP_DIAG_POP\n}\n\nchar*\nPy_GETENV(const char *name)\n{\n_Py_COMP_DIAG_PUSH\n_Py_COMP_DIAG_IGNORE_DEPR_DECLS\n    if (Py_IgnoreEnvironmentFlag) {\n        return NULL;\n    }\n    return getenv(name);\n_Py_COMP_DIAG_POP\n}\n\n/* --- PyStatus ----------------------------------------------- */\n\nPyStatus PyStatus_Ok(void)\n{ return _PyStatus_OK(); }\n\nPyStatus PyStatus_Error(const char *err_msg)\n{\n    assert(err_msg != NULL);\n    return (PyStatus){._type = _PyStatus_TYPE_ERROR,\n                      .err_msg = err_msg};\n}\n\nPyStatus PyStatus_NoMemory(void)\n{ return PyStatus_Error(\"memory allocation failed\"); }\n\nPyStatus PyStatus_Exit(int exitcode)\n{ return _PyStatus_EXIT(exitcode); }\n\n\nint PyStatus_IsError(PyStatus status)\n{ return _PyStatus_IS_ERROR(status); }\n\nint PyStatus_IsExit(PyStatus status)\n{ return _PyStatus_IS_EXIT(status); }\n\nint PyStatus_Exception(PyStatus status)\n{ return _PyStatus_EXCEPTION(status); }\n\nPyObject*\n_PyErr_SetFromPyStatus(PyStatus status)\n{\n    if (!_PyStatus_IS_ERROR(status)) {\n        PyErr_Format(PyExc_SystemError,\n                     \"%s() expects an error PyStatus\",\n                     _PyStatus_GET_FUNC());\n    }\n    else if (status.func) {\n        PyErr_Format(PyExc_ValueError, \"%s: %s\", status.func, status.err_msg);\n    }\n    else {\n        PyErr_Format(PyExc_ValueError, \"%s\", status.err_msg);\n    }\n    return NULL;\n}\n\n\n/* --- PyWideStringList ------------------------------------------------ */\n\n#ifndef NDEBUG\nint\n_PyWideStringList_CheckConsistency(const PyWideStringList *list)\n{\n    assert(list->length >= 0);\n    if (list->length != 0) {\n        assert(list->items != NULL);\n    }\n    for (Py_ssize_t i = 0; i < list->length; i++) {\n        assert(list->items[i] != NULL);\n    }\n    return 1;\n}\n#endif   /* Py_DEBUG */\n\n\nvoid\n_PyWideStringList_Clear(PyWideStringList *list)\n{\n    assert(_PyWideStringList_CheckConsistency(list));\n    for (Py_ssize_t i=0; i < list->length; i++) {\n        PyMem_RawFree(list->items[i]);\n    }\n    PyMem_RawFree(list->items);\n    list->length = 0;\n    list->items = NULL;\n}\n\n\nint\n_PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2)\n{\n    assert(_PyWideStringList_CheckConsistency(list));\n    assert(_PyWideStringList_CheckConsistency(list2));\n\n    if (list2->length == 0) {\n        _PyWideStringList_Clear(list);\n        return 0;\n    }\n\n    PyWideStringList copy = _PyWideStringList_INIT;\n\n    size_t size = list2->length * sizeof(list2->items[0]);\n    copy.items = PyMem_RawMalloc(size);\n    if (copy.items == NULL) {\n        return -1;\n    }\n\n    for (Py_ssize_t i=0; i < list2->length; i++) {\n        wchar_t *item = _PyMem_RawWcsdup(list2->items[i]);\n        if (item == NULL) {\n            _PyWideStringList_Clear(&copy);\n            return -1;\n        }\n        copy.items[i] = item;\n        copy.length = i + 1;\n    }\n\n    _PyWideStringList_Clear(list);\n    *list = copy;\n    return 0;\n}\n\n\nPyStatus\nPyWideStringList_Insert(PyWideStringList *list,\n                        Py_ssize_t index, const wchar_t *item)\n{\n    Py_ssize_t len = list->length;\n    if (len == PY_SSIZE_T_MAX) {\n        /* length+1 would overflow */\n        return _PyStatus_NO_MEMORY();\n    }\n    if (index < 0) {\n        return _PyStatus_ERR(\"PyWideStringList_Insert index must be >= 0\");\n    }\n    if (index > len) {\n        index = len;\n    }\n\n    wchar_t *item2 = _PyMem_RawWcsdup(item);\n    if (item2 == NULL) {\n        return _PyStatus_NO_MEMORY();\n    }\n\n    size_t size = (len + 1) * sizeof(list->items[0]);\n    wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size);\n    if (items2 == NULL) {\n        PyMem_RawFree(item2);\n        return _PyStatus_NO_MEMORY();\n    }\n\n    if (index < len) {\n        memmove(&items2[index + 1],\n                &items2[index],\n                (len - index) * sizeof(items2[0]));\n    }\n\n    items2[index] = item2;\n    list->items = items2;\n    list->length++;\n    return _PyStatus_OK();\n}\n\n\nPyStatus\nPyWideStringList_Append(PyWideStringList *list, const wchar_t *item)\n{\n    return PyWideStringList_Insert(list, list->length, item);\n}\n\n\nPyStatus\n_PyWideStringList_Extend(PyWideStringList *list, const PyWideStringList *list2)\n{\n    for (Py_ssize_t i = 0; i < list2->length; i++) {\n        PyStatus status = PyWideStringList_Append(list, list2->items[i]);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n    return _PyStatus_OK();\n}\n\n\nstatic int\n_PyWideStringList_Find(PyWideStringList *list, const wchar_t *item)\n{\n    for (Py_ssize_t i = 0; i < list->length; i++) {\n        if (wcscmp(list->items[i], item) == 0) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\n\nPyObject*\n_PyWideStringList_AsList(const PyWideStringList *list)\n{\n    assert(_PyWideStringList_CheckConsistency(list));\n\n    PyObject *pylist = PyList_New(list->length);\n    if (pylist == NULL) {\n        return NULL;\n    }\n\n    for (Py_ssize_t i = 0; i < list->length; i++) {\n        PyObject *item = PyUnicode_FromWideChar(list->items[i], -1);\n        if (item == NULL) {\n            Py_DECREF(pylist);\n            return NULL;\n        }\n        PyList_SET_ITEM(pylist, i, item);\n    }\n    return pylist;\n}\n\n\n/* --- Py_GetArgcArgv() ------------------------------------------- */\n\nvoid\n_Py_ClearArgcArgv(void)\n{\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    _PyWideStringList_Clear(&_PyRuntime.orig_argv);\n\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n}\n\n\nstatic int\n_Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv)\n{\n    const PyWideStringList argv_list = {.length = argc, .items = (wchar_t **)argv};\n    int res;\n\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    // XXX _PyRuntime.orig_argv only gets cleared by Py_Main(),\n    // so it it currently leaks for embedders.\n    res = _PyWideStringList_Copy(&_PyRuntime.orig_argv, &argv_list);\n\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n    return res;\n}\n\n\n// _PyConfig_Write() calls _Py_SetArgcArgv() with PyConfig.orig_argv.\nvoid\nPy_GetArgcArgv(int *argc, wchar_t ***argv)\n{\n    *argc = (int)_PyRuntime.orig_argv.length;\n    *argv = _PyRuntime.orig_argv.items;\n}\n\n\n/* --- PyConfig ---------------------------------------------- */\n\n#define MAX_HASH_SEED 4294967295UL\n\n\n#ifndef NDEBUG\nstatic int\nconfig_check_consistency(const PyConfig *config)\n{\n    /* Check config consistency */\n    assert(config->isolated >= 0);\n    assert(config->use_environment >= 0);\n    assert(config->dev_mode >= 0);\n    assert(config->install_signal_handlers >= 0);\n    assert(config->use_hash_seed >= 0);\n    assert(config->hash_seed <= MAX_HASH_SEED);\n    assert(config->faulthandler >= 0);\n    assert(config->tracemalloc >= 0);\n    assert(config->import_time >= 0);\n    assert(config->code_debug_ranges >= 0);\n    assert(config->show_ref_count >= 0);\n    assert(config->dump_refs >= 0);\n    assert(config->malloc_stats >= 0);\n    assert(config->site_import >= 0);\n    assert(config->bytes_warning >= 0);\n    assert(config->warn_default_encoding >= 0);\n    assert(config->inspect >= 0);\n    assert(config->interactive >= 0);\n    assert(config->optimization_level >= 0);\n    assert(config->parser_debug >= 0);\n    assert(config->write_bytecode >= 0);\n    assert(config->verbose >= 0);\n    assert(config->quiet >= 0);\n    assert(config->user_site_directory >= 0);\n    assert(config->parse_argv >= 0);\n    assert(config->configure_c_stdio >= 0);\n    assert(config->buffered_stdio >= 0);\n    assert(_PyWideStringList_CheckConsistency(&config->orig_argv));\n    assert(_PyWideStringList_CheckConsistency(&config->argv));\n    /* sys.argv must be non-empty: empty argv is replaced with [''] */\n    assert(config->argv.length >= 1);\n    assert(_PyWideStringList_CheckConsistency(&config->xoptions));\n    assert(_PyWideStringList_CheckConsistency(&config->warnoptions));\n    assert(_PyWideStringList_CheckConsistency(&config->module_search_paths));\n    assert(config->module_search_paths_set >= 0);\n    assert(config->filesystem_encoding != NULL);\n    assert(config->filesystem_errors != NULL);\n    assert(config->stdio_encoding != NULL);\n    assert(config->stdio_errors != NULL);\n#ifdef MS_WINDOWS\n    assert(config->legacy_windows_stdio >= 0);\n#endif\n    /* -c and -m options are exclusive */\n    assert(!(config->run_command != NULL && config->run_module != NULL));\n    assert(config->check_hash_pycs_mode != NULL);\n    assert(config->_install_importlib >= 0);\n    assert(config->pathconfig_warnings >= 0);\n    assert(config->_is_python_build >= 0);\n    assert(config->safe_path >= 0);\n    assert(config->int_max_str_digits >= 0);\n    // config->use_frozen_modules is initialized later\n    // by _PyConfig_InitImportConfig().\n    return 1;\n}\n#endif\n\n\n/* Free memory allocated in config, but don't clear all attributes */\nvoid\nPyConfig_Clear(PyConfig *config)\n{\n#define CLEAR(ATTR) \\\n    do { \\\n        PyMem_RawFree(ATTR); \\\n        ATTR = NULL; \\\n    } while (0)\n\n    CLEAR(config->pycache_prefix);\n    CLEAR(config->pythonpath_env);\n    CLEAR(config->home);\n    CLEAR(config->program_name);\n\n    _PyWideStringList_Clear(&config->argv);\n    _PyWideStringList_Clear(&config->warnoptions);\n    _PyWideStringList_Clear(&config->xoptions);\n    _PyWideStringList_Clear(&config->module_search_paths);\n    config->module_search_paths_set = 0;\n    CLEAR(config->stdlib_dir);\n\n    CLEAR(config->executable);\n    CLEAR(config->base_executable);\n    CLEAR(config->prefix);\n    CLEAR(config->base_prefix);\n    CLEAR(config->exec_prefix);\n    CLEAR(config->base_exec_prefix);\n    CLEAR(config->platlibdir);\n\n    CLEAR(config->filesystem_encoding);\n    CLEAR(config->filesystem_errors);\n    CLEAR(config->stdio_encoding);\n    CLEAR(config->stdio_errors);\n    CLEAR(config->run_command);\n    CLEAR(config->run_module);\n    CLEAR(config->run_filename);\n    CLEAR(config->check_hash_pycs_mode);\n\n    _PyWideStringList_Clear(&config->orig_argv);\n#undef CLEAR\n}\n\n\nvoid\n_PyConfig_InitCompatConfig(PyConfig *config)\n{\n    memset(config, 0, sizeof(*config));\n\n    config->_config_init = (int)_PyConfig_INIT_COMPAT;\n    config->isolated = -1;\n    config->use_environment = -1;\n    config->dev_mode = -1;\n    config->install_signal_handlers = 1;\n    config->use_hash_seed = -1;\n    config->faulthandler = -1;\n    config->tracemalloc = -1;\n    config->perf_profiling = -1;\n    config->module_search_paths_set = 0;\n    config->parse_argv = 0;\n    config->site_import = -1;\n    config->bytes_warning = -1;\n    config->warn_default_encoding = 0;\n    config->inspect = -1;\n    config->interactive = -1;\n    config->optimization_level = -1;\n    config->parser_debug= -1;\n    config->write_bytecode = -1;\n    config->verbose = -1;\n    config->quiet = -1;\n    config->user_site_directory = -1;\n    config->configure_c_stdio = 0;\n    config->buffered_stdio = -1;\n    config->_install_importlib = 1;\n    config->check_hash_pycs_mode = NULL;\n    config->pathconfig_warnings = -1;\n    config->_init_main = 1;\n#ifdef MS_WINDOWS\n    config->legacy_windows_stdio = -1;\n#endif\n#ifdef Py_DEBUG\n    config->use_frozen_modules = 0;\n#else\n    config->use_frozen_modules = 1;\n#endif\n    config->safe_path = 0;\n    config->int_max_str_digits = -1;\n    config->_is_python_build = 0;\n    config->code_debug_ranges = 1;\n}\n\n\nstatic void\nconfig_init_defaults(PyConfig *config)\n{\n    _PyConfig_InitCompatConfig(config);\n\n    config->isolated = 0;\n    config->use_environment = 1;\n    config->site_import = 1;\n    config->bytes_warning = 0;\n    config->inspect = 0;\n    config->interactive = 0;\n    config->optimization_level = 0;\n    config->parser_debug= 0;\n    config->write_bytecode = 1;\n    config->verbose = 0;\n    config->quiet = 0;\n    config->user_site_directory = 1;\n    config->buffered_stdio = 1;\n    config->pathconfig_warnings = 1;\n#ifdef MS_WINDOWS\n    config->legacy_windows_stdio = 0;\n#endif\n}\n\n\nvoid\nPyConfig_InitPythonConfig(PyConfig *config)\n{\n    config_init_defaults(config);\n\n    config->_config_init = (int)_PyConfig_INIT_PYTHON;\n    config->configure_c_stdio = 1;\n    config->parse_argv = 1;\n}\n\n\nvoid\nPyConfig_InitIsolatedConfig(PyConfig *config)\n{\n    config_init_defaults(config);\n\n    config->_config_init = (int)_PyConfig_INIT_ISOLATED;\n    config->isolated = 1;\n    config->use_environment = 0;\n    config->user_site_directory = 0;\n    config->dev_mode = 0;\n    config->install_signal_handlers = 0;\n    config->use_hash_seed = 0;\n    config->faulthandler = 0;\n    config->tracemalloc = 0;\n    config->perf_profiling = 0;\n    config->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;\n    config->safe_path = 1;\n    config->pathconfig_warnings = 0;\n#ifdef MS_WINDOWS\n    config->legacy_windows_stdio = 0;\n#endif\n}\n\n\n/* Copy str into *config_str (duplicate the string) */\nPyStatus\nPyConfig_SetString(PyConfig *config, wchar_t **config_str, const wchar_t *str)\n{\n    PyStatus status = _Py_PreInitializeFromConfig(config, NULL);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    wchar_t *str2;\n    if (str != NULL) {\n        str2 = _PyMem_RawWcsdup(str);\n        if (str2 == NULL) {\n            return _PyStatus_NO_MEMORY();\n        }\n    }\n    else {\n        str2 = NULL;\n    }\n    PyMem_RawFree(*config_str);\n    *config_str = str2;\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\nconfig_set_bytes_string(PyConfig *config, wchar_t **config_str,\n                        const char *str, const char *decode_err_msg)\n{\n    PyStatus status = _Py_PreInitializeFromConfig(config, NULL);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    wchar_t *str2;\n    if (str != NULL) {\n        size_t len;\n        str2 = Py_DecodeLocale(str, &len);\n        if (str2 == NULL) {\n            if (len == (size_t)-2) {\n                return _PyStatus_ERR(decode_err_msg);\n            }\n            else {\n                return  _PyStatus_NO_MEMORY();\n            }\n        }\n    }\n    else {\n        str2 = NULL;\n    }\n    PyMem_RawFree(*config_str);\n    *config_str = str2;\n    return _PyStatus_OK();\n}\n\n\n#define CONFIG_SET_BYTES_STR(config, config_str, str, NAME) \\\n    config_set_bytes_string(config, config_str, str, \"cannot decode \" NAME)\n\n\n/* Decode str using Py_DecodeLocale() and set the result into *config_str.\n   Pre-initialize Python if needed to ensure that encodings are properly\n   configured. */\nPyStatus\nPyConfig_SetBytesString(PyConfig *config, wchar_t **config_str,\n                        const char *str)\n{\n    return CONFIG_SET_BYTES_STR(config, config_str, str, \"string\");\n}\n\n\nPyStatus\n_PyConfig_Copy(PyConfig *config, const PyConfig *config2)\n{\n    PyStatus status;\n\n    PyConfig_Clear(config);\n\n#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR\n#define COPY_WSTR_ATTR(ATTR) \\\n    do { \\\n        status = PyConfig_SetString(config, &config->ATTR, config2->ATTR); \\\n        if (_PyStatus_EXCEPTION(status)) { \\\n            return status; \\\n        } \\\n    } while (0)\n#define COPY_WSTRLIST(LIST) \\\n    do { \\\n        if (_PyWideStringList_Copy(&config->LIST, &config2->LIST) < 0) { \\\n            return _PyStatus_NO_MEMORY(); \\\n        } \\\n    } while (0)\n\n    COPY_ATTR(_config_init);\n    COPY_ATTR(isolated);\n    COPY_ATTR(use_environment);\n    COPY_ATTR(dev_mode);\n    COPY_ATTR(install_signal_handlers);\n    COPY_ATTR(use_hash_seed);\n    COPY_ATTR(hash_seed);\n    COPY_ATTR(_install_importlib);\n    COPY_ATTR(faulthandler);\n    COPY_ATTR(tracemalloc);\n    COPY_ATTR(perf_profiling);\n    COPY_ATTR(import_time);\n    COPY_ATTR(code_debug_ranges);\n    COPY_ATTR(show_ref_count);\n    COPY_ATTR(dump_refs);\n    COPY_ATTR(dump_refs_file);\n    COPY_ATTR(malloc_stats);\n\n    COPY_WSTR_ATTR(pycache_prefix);\n    COPY_WSTR_ATTR(pythonpath_env);\n    COPY_WSTR_ATTR(home);\n    COPY_WSTR_ATTR(program_name);\n\n    COPY_ATTR(parse_argv);\n    COPY_WSTRLIST(argv);\n    COPY_WSTRLIST(warnoptions);\n    COPY_WSTRLIST(xoptions);\n    COPY_WSTRLIST(module_search_paths);\n    COPY_ATTR(module_search_paths_set);\n    COPY_WSTR_ATTR(stdlib_dir);\n\n    COPY_WSTR_ATTR(executable);\n    COPY_WSTR_ATTR(base_executable);\n    COPY_WSTR_ATTR(prefix);\n    COPY_WSTR_ATTR(base_prefix);\n    COPY_WSTR_ATTR(exec_prefix);\n    COPY_WSTR_ATTR(base_exec_prefix);\n    COPY_WSTR_ATTR(platlibdir);\n\n    COPY_ATTR(site_import);\n    COPY_ATTR(bytes_warning);\n    COPY_ATTR(warn_default_encoding);\n    COPY_ATTR(inspect);\n    COPY_ATTR(interactive);\n    COPY_ATTR(optimization_level);\n    COPY_ATTR(parser_debug);\n    COPY_ATTR(write_bytecode);\n    COPY_ATTR(verbose);\n    COPY_ATTR(quiet);\n    COPY_ATTR(user_site_directory);\n    COPY_ATTR(configure_c_stdio);\n    COPY_ATTR(buffered_stdio);\n    COPY_WSTR_ATTR(filesystem_encoding);\n    COPY_WSTR_ATTR(filesystem_errors);\n    COPY_WSTR_ATTR(stdio_encoding);\n    COPY_WSTR_ATTR(stdio_errors);\n#ifdef MS_WINDOWS\n    COPY_ATTR(legacy_windows_stdio);\n#endif\n    COPY_ATTR(skip_source_first_line);\n    COPY_WSTR_ATTR(run_command);\n    COPY_WSTR_ATTR(run_module);\n    COPY_WSTR_ATTR(run_filename);\n    COPY_WSTR_ATTR(check_hash_pycs_mode);\n    COPY_ATTR(pathconfig_warnings);\n    COPY_ATTR(_init_main);\n    COPY_ATTR(use_frozen_modules);\n    COPY_ATTR(safe_path);\n    COPY_WSTRLIST(orig_argv);\n    COPY_ATTR(_is_python_build);\n    COPY_ATTR(int_max_str_digits);\n\n#undef COPY_ATTR\n#undef COPY_WSTR_ATTR\n#undef COPY_WSTRLIST\n    return _PyStatus_OK();\n}\n\n\nPyObject *\n_PyConfig_AsDict(const PyConfig *config)\n{\n    PyObject *dict = PyDict_New();\n    if (dict == NULL) {\n        return NULL;\n    }\n\n#define SET_ITEM(KEY, EXPR) \\\n        do { \\\n            PyObject *obj = (EXPR); \\\n            if (obj == NULL) { \\\n                goto fail; \\\n            } \\\n            int res = PyDict_SetItemString(dict, (KEY), obj); \\\n            Py_DECREF(obj); \\\n            if (res < 0) { \\\n                goto fail; \\\n            } \\\n        } while (0)\n#define SET_ITEM_INT(ATTR) \\\n    SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))\n#define SET_ITEM_UINT(ATTR) \\\n    SET_ITEM(#ATTR, PyLong_FromUnsignedLong(config->ATTR))\n#define FROM_WSTRING(STR) \\\n    ((STR != NULL) ? \\\n        PyUnicode_FromWideChar(STR, -1) \\\n        : Py_NewRef(Py_None))\n#define SET_ITEM_WSTR(ATTR) \\\n    SET_ITEM(#ATTR, FROM_WSTRING(config->ATTR))\n#define SET_ITEM_WSTRLIST(LIST) \\\n    SET_ITEM(#LIST, _PyWideStringList_AsList(&config->LIST))\n\n    SET_ITEM_INT(_config_init);\n    SET_ITEM_INT(isolated);\n    SET_ITEM_INT(use_environment);\n    SET_ITEM_INT(dev_mode);\n    SET_ITEM_INT(install_signal_handlers);\n    SET_ITEM_INT(use_hash_seed);\n    SET_ITEM_UINT(hash_seed);\n    SET_ITEM_INT(faulthandler);\n    SET_ITEM_INT(tracemalloc);\n    SET_ITEM_INT(perf_profiling);\n    SET_ITEM_INT(import_time);\n    SET_ITEM_INT(code_debug_ranges);\n    SET_ITEM_INT(show_ref_count);\n    SET_ITEM_INT(dump_refs);\n    SET_ITEM_INT(malloc_stats);\n    SET_ITEM_WSTR(filesystem_encoding);\n    SET_ITEM_WSTR(filesystem_errors);\n    SET_ITEM_WSTR(pycache_prefix);\n    SET_ITEM_WSTR(program_name);\n    SET_ITEM_INT(parse_argv);\n    SET_ITEM_WSTRLIST(argv);\n    SET_ITEM_WSTRLIST(xoptions);\n    SET_ITEM_WSTRLIST(warnoptions);\n    SET_ITEM_WSTR(pythonpath_env);\n    SET_ITEM_WSTR(home);\n    SET_ITEM_INT(module_search_paths_set);\n    SET_ITEM_WSTRLIST(module_search_paths);\n    SET_ITEM_WSTR(stdlib_dir);\n    SET_ITEM_WSTR(executable);\n    SET_ITEM_WSTR(base_executable);\n    SET_ITEM_WSTR(prefix);\n    SET_ITEM_WSTR(base_prefix);\n    SET_ITEM_WSTR(exec_prefix);\n    SET_ITEM_WSTR(base_exec_prefix);\n    SET_ITEM_WSTR(platlibdir);\n    SET_ITEM_INT(site_import);\n    SET_ITEM_INT(bytes_warning);\n    SET_ITEM_INT(warn_default_encoding);\n    SET_ITEM_INT(inspect);\n    SET_ITEM_INT(interactive);\n    SET_ITEM_INT(optimization_level);\n    SET_ITEM_INT(parser_debug);\n    SET_ITEM_INT(write_bytecode);\n    SET_ITEM_INT(verbose);\n    SET_ITEM_INT(quiet);\n    SET_ITEM_INT(user_site_directory);\n    SET_ITEM_INT(configure_c_stdio);\n    SET_ITEM_INT(buffered_stdio);\n    SET_ITEM_WSTR(stdio_encoding);\n    SET_ITEM_WSTR(stdio_errors);\n#ifdef MS_WINDOWS\n    SET_ITEM_INT(legacy_windows_stdio);\n#endif\n    SET_ITEM_INT(skip_source_first_line);\n    SET_ITEM_WSTR(run_command);\n    SET_ITEM_WSTR(run_module);\n    SET_ITEM_WSTR(run_filename);\n    SET_ITEM_INT(_install_importlib);\n    SET_ITEM_WSTR(check_hash_pycs_mode);\n    SET_ITEM_INT(pathconfig_warnings);\n    SET_ITEM_INT(_init_main);\n    SET_ITEM_WSTRLIST(orig_argv);\n    SET_ITEM_INT(use_frozen_modules);\n    SET_ITEM_INT(safe_path);\n    SET_ITEM_INT(_is_python_build);\n    SET_ITEM_INT(int_max_str_digits);\n\n    return dict;\n\nfail:\n    Py_DECREF(dict);\n    return NULL;\n\n#undef FROM_WSTRING\n#undef SET_ITEM\n#undef SET_ITEM_INT\n#undef SET_ITEM_UINT\n#undef SET_ITEM_WSTR\n#undef SET_ITEM_WSTRLIST\n}\n\n\nstatic PyObject*\nconfig_dict_get(PyObject *dict, const char *name)\n{\n    PyObject *item = _PyDict_GetItemStringWithError(dict, name);\n    if (item == NULL && !PyErr_Occurred()) {\n        PyErr_Format(PyExc_ValueError, \"missing config key: %s\", name);\n        return NULL;\n    }\n    return item;\n}\n\n\nstatic void\nconfig_dict_invalid_value(const char *name)\n{\n    PyErr_Format(PyExc_ValueError, \"invalid config value: %s\", name);\n}\n\n\nstatic void\nconfig_dict_invalid_type(const char *name)\n{\n    PyErr_Format(PyExc_TypeError, \"invalid config type: %s\", name);\n}\n\n\nstatic int\nconfig_dict_get_int(PyObject *dict, const char *name, int *result)\n{\n    PyObject *item = config_dict_get(dict, name);\n    if (item == NULL) {\n        return -1;\n    }\n    int value = _PyLong_AsInt(item);\n    if (value == -1 && PyErr_Occurred()) {\n        if (PyErr_ExceptionMatches(PyExc_TypeError)) {\n            config_dict_invalid_type(name);\n        }\n        else if (PyErr_ExceptionMatches(PyExc_OverflowError)) {\n            config_dict_invalid_value(name);\n        }\n        return -1;\n    }\n    *result = value;\n    return 0;\n}\n\n\nstatic int\nconfig_dict_get_ulong(PyObject *dict, const char *name, unsigned long *result)\n{\n    PyObject *item = config_dict_get(dict, name);\n    if (item == NULL) {\n        return -1;\n    }\n    unsigned long value = PyLong_AsUnsignedLong(item);\n    if (value == (unsigned long)-1 && PyErr_Occurred()) {\n        if (PyErr_ExceptionMatches(PyExc_TypeError)) {\n            config_dict_invalid_type(name);\n        }\n        else if (PyErr_ExceptionMatches(PyExc_OverflowError)) {\n            config_dict_invalid_value(name);\n        }\n        return -1;\n    }\n    *result = value;\n    return 0;\n}\n\n\nstatic int\nconfig_dict_get_wstr(PyObject *dict, const char *name, PyConfig *config,\n                     wchar_t **result)\n{\n    PyObject *item = config_dict_get(dict, name);\n    if (item == NULL) {\n        return -1;\n    }\n    PyStatus status;\n    if (item == Py_None) {\n        status = PyConfig_SetString(config, result, NULL);\n    }\n    else if (!PyUnicode_Check(item)) {\n        config_dict_invalid_type(name);\n        return -1;\n    }\n    else {\n        wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);\n        if (wstr == NULL) {\n            return -1;\n        }\n        status = PyConfig_SetString(config, result, wstr);\n        PyMem_Free(wstr);\n    }\n    if (_PyStatus_EXCEPTION(status)) {\n        PyErr_NoMemory();\n        return -1;\n    }\n    return 0;\n}\n\n\nstatic int\nconfig_dict_get_wstrlist(PyObject *dict, const char *name, PyConfig *config,\n                         PyWideStringList *result)\n{\n    PyObject *list = config_dict_get(dict, name);\n    if (list == NULL) {\n        return -1;\n    }\n\n    if (!PyList_CheckExact(list)) {\n        config_dict_invalid_type(name);\n        return -1;\n    }\n\n    PyWideStringList wstrlist = _PyWideStringList_INIT;\n    for (Py_ssize_t i=0; i < PyList_GET_SIZE(list); i++) {\n        PyObject *item = PyList_GET_ITEM(list, i);\n\n        if (item == Py_None) {\n            config_dict_invalid_value(name);\n            goto error;\n        }\n        else if (!PyUnicode_Check(item)) {\n            config_dict_invalid_type(name);\n            goto error;\n        }\n        wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);\n        if (wstr == NULL) {\n            goto error;\n        }\n        PyStatus status = PyWideStringList_Append(&wstrlist, wstr);\n        PyMem_Free(wstr);\n        if (_PyStatus_EXCEPTION(status)) {\n            PyErr_NoMemory();\n            goto error;\n        }\n    }\n\n    if (_PyWideStringList_Copy(result, &wstrlist) < 0) {\n        PyErr_NoMemory();\n        goto error;\n    }\n    _PyWideStringList_Clear(&wstrlist);\n    return 0;\n\nerror:\n    _PyWideStringList_Clear(&wstrlist);\n    return -1;\n}\n\n\nint\n_PyConfig_FromDict(PyConfig *config, PyObject *dict)\n{\n    if (!PyDict_Check(dict)) {\n        PyErr_SetString(PyExc_TypeError, \"dict expected\");\n        return -1;\n    }\n\n#define CHECK_VALUE(NAME, TEST) \\\n    if (!(TEST)) { \\\n        config_dict_invalid_value(NAME); \\\n        return -1; \\\n    }\n#define GET_UINT(KEY) \\\n    do { \\\n        if (config_dict_get_int(dict, #KEY, &config->KEY) < 0) { \\\n            return -1; \\\n        } \\\n        CHECK_VALUE(#KEY, config->KEY >= 0); \\\n    } while (0)\n#define GET_INT(KEY) \\\n    do { \\\n        if (config_dict_get_int(dict, #KEY, &config->KEY) < 0) { \\\n            return -1; \\\n        } \\\n    } while (0)\n#define GET_WSTR(KEY) \\\n    do { \\\n        if (config_dict_get_wstr(dict, #KEY, config, &config->KEY) < 0) { \\\n            return -1; \\\n        } \\\n        CHECK_VALUE(#KEY, config->KEY != NULL); \\\n    } while (0)\n#define GET_WSTR_OPT(KEY) \\\n    do { \\\n        if (config_dict_get_wstr(dict, #KEY, config, &config->KEY) < 0) { \\\n            return -1; \\\n        } \\\n    } while (0)\n#define GET_WSTRLIST(KEY) \\\n    do { \\\n        if (config_dict_get_wstrlist(dict, #KEY, config, &config->KEY) < 0) { \\\n            return -1; \\\n        } \\\n    } while (0)\n\n    GET_UINT(_config_init);\n    CHECK_VALUE(\"_config_init\",\n                config->_config_init == _PyConfig_INIT_COMPAT\n                || config->_config_init == _PyConfig_INIT_PYTHON\n                || config->_config_init == _PyConfig_INIT_ISOLATED);\n    GET_UINT(isolated);\n    GET_UINT(use_environment);\n    GET_UINT(dev_mode);\n    GET_UINT(install_signal_handlers);\n    GET_UINT(use_hash_seed);\n    if (config_dict_get_ulong(dict, \"hash_seed\", &config->hash_seed) < 0) {\n        return -1;\n    }\n    CHECK_VALUE(\"hash_seed\", config->hash_seed <= MAX_HASH_SEED);\n    GET_UINT(faulthandler);\n    GET_UINT(tracemalloc);\n    GET_UINT(perf_profiling);\n    GET_UINT(import_time);\n    GET_UINT(code_debug_ranges);\n    GET_UINT(show_ref_count);\n    GET_UINT(dump_refs);\n    GET_UINT(malloc_stats);\n    GET_WSTR(filesystem_encoding);\n    GET_WSTR(filesystem_errors);\n    GET_WSTR_OPT(pycache_prefix);\n    GET_UINT(parse_argv);\n    GET_WSTRLIST(orig_argv);\n    GET_WSTRLIST(argv);\n    GET_WSTRLIST(xoptions);\n    GET_WSTRLIST(warnoptions);\n    GET_UINT(site_import);\n    GET_UINT(bytes_warning);\n    GET_UINT(warn_default_encoding);\n    GET_UINT(inspect);\n    GET_UINT(interactive);\n    GET_UINT(optimization_level);\n    GET_UINT(parser_debug);\n    GET_UINT(write_bytecode);\n    GET_UINT(verbose);\n    GET_UINT(quiet);\n    GET_UINT(user_site_directory);\n    GET_UINT(configure_c_stdio);\n    GET_UINT(buffered_stdio);\n    GET_WSTR(stdio_encoding);\n    GET_WSTR(stdio_errors);\n#ifdef MS_WINDOWS\n    GET_UINT(legacy_windows_stdio);\n#endif\n    GET_WSTR(check_hash_pycs_mode);\n\n    GET_UINT(pathconfig_warnings);\n    GET_WSTR(program_name);\n    GET_WSTR_OPT(pythonpath_env);\n    GET_WSTR_OPT(home);\n    GET_WSTR(platlibdir);\n\n    // Path configuration output\n    GET_UINT(module_search_paths_set);\n    GET_WSTRLIST(module_search_paths);\n    GET_WSTR_OPT(stdlib_dir);\n    GET_WSTR_OPT(executable);\n    GET_WSTR_OPT(base_executable);\n    GET_WSTR_OPT(prefix);\n    GET_WSTR_OPT(base_prefix);\n    GET_WSTR_OPT(exec_prefix);\n    GET_WSTR_OPT(base_exec_prefix);\n\n    GET_UINT(skip_source_first_line);\n    GET_WSTR_OPT(run_command);\n    GET_WSTR_OPT(run_module);\n    GET_WSTR_OPT(run_filename);\n\n    GET_UINT(_install_importlib);\n    GET_UINT(_init_main);\n    GET_UINT(use_frozen_modules);\n    GET_UINT(safe_path);\n    GET_UINT(_is_python_build);\n    GET_INT(int_max_str_digits);\n\n#undef CHECK_VALUE\n#undef GET_UINT\n#undef GET_INT\n#undef GET_WSTR\n#undef GET_WSTR_OPT\n    return 0;\n}\n\n\nstatic const char*\nconfig_get_env(const PyConfig *config, const char *name)\n{\n    return _Py_GetEnv(config->use_environment, name);\n}\n\n\n/* Get a copy of the environment variable as wchar_t*.\n   Return 0 on success, but *dest can be NULL.\n   Return -1 on memory allocation failure. Return -2 on decoding error. */\nstatic PyStatus\nconfig_get_env_dup(PyConfig *config,\n                   wchar_t **dest,\n                   wchar_t *wname, char *name,\n                   const char *decode_err_msg)\n{\n    assert(*dest == NULL);\n    assert(config->use_environment >= 0);\n\n    if (!config->use_environment) {\n        *dest = NULL;\n        return _PyStatus_OK();\n    }\n\n#ifdef MS_WINDOWS\n    const wchar_t *var = _wgetenv(wname);\n    if (!var || var[0] == '\\0') {\n        *dest = NULL;\n        return _PyStatus_OK();\n    }\n\n    return PyConfig_SetString(config, dest, var);\n#else\n    const char *var = getenv(name);\n    if (!var || var[0] == '\\0') {\n        *dest = NULL;\n        return _PyStatus_OK();\n    }\n\n    return config_set_bytes_string(config, dest, var, decode_err_msg);\n#endif\n}\n\n\n#define CONFIG_GET_ENV_DUP(CONFIG, DEST, WNAME, NAME) \\\n    config_get_env_dup(CONFIG, DEST, WNAME, NAME, \"cannot decode \" NAME)\n\n\nstatic void\nconfig_get_global_vars(PyConfig *config)\n{\n_Py_COMP_DIAG_PUSH\n_Py_COMP_DIAG_IGNORE_DEPR_DECLS\n    if (config->_config_init != _PyConfig_INIT_COMPAT) {\n        /* Python and Isolated configuration ignore global variables */\n        return;\n    }\n\n#define COPY_FLAG(ATTR, VALUE) \\\n        if (config->ATTR == -1) { \\\n            config->ATTR = VALUE; \\\n        }\n#define COPY_NOT_FLAG(ATTR, VALUE) \\\n        if (config->ATTR == -1) { \\\n            config->ATTR = !(VALUE); \\\n        }\n\n    COPY_FLAG(isolated, Py_IsolatedFlag);\n    COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);\n    COPY_FLAG(bytes_warning, Py_BytesWarningFlag);\n    COPY_FLAG(inspect, Py_InspectFlag);\n    COPY_FLAG(interactive, Py_InteractiveFlag);\n    COPY_FLAG(optimization_level, Py_OptimizeFlag);\n    COPY_FLAG(parser_debug, Py_DebugFlag);\n    COPY_FLAG(verbose, Py_VerboseFlag);\n    COPY_FLAG(quiet, Py_QuietFlag);\n#ifdef MS_WINDOWS\n    COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);\n#endif\n    COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag);\n\n    COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);\n    COPY_NOT_FLAG(site_import, Py_NoSiteFlag);\n    COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);\n    COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);\n\n#undef COPY_FLAG\n#undef COPY_NOT_FLAG\n_Py_COMP_DIAG_POP\n}\n\n\n/* Set Py_xxx global configuration variables from 'config' configuration. */\nstatic void\nconfig_set_global_vars(const PyConfig *config)\n{\n_Py_COMP_DIAG_PUSH\n_Py_COMP_DIAG_IGNORE_DEPR_DECLS\n#define COPY_FLAG(ATTR, VAR) \\\n        if (config->ATTR != -1) { \\\n            VAR = config->ATTR; \\\n        }\n#define COPY_NOT_FLAG(ATTR, VAR) \\\n        if (config->ATTR != -1) { \\\n            VAR = !config->ATTR; \\\n        }\n\n    COPY_FLAG(isolated, Py_IsolatedFlag);\n    COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);\n    COPY_FLAG(bytes_warning, Py_BytesWarningFlag);\n    COPY_FLAG(inspect, Py_InspectFlag);\n    COPY_FLAG(interactive, Py_InteractiveFlag);\n    COPY_FLAG(optimization_level, Py_OptimizeFlag);\n    COPY_FLAG(parser_debug, Py_DebugFlag);\n    COPY_FLAG(verbose, Py_VerboseFlag);\n    COPY_FLAG(quiet, Py_QuietFlag);\n#ifdef MS_WINDOWS\n    COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);\n#endif\n    COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag);\n\n    COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);\n    COPY_NOT_FLAG(site_import, Py_NoSiteFlag);\n    COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);\n    COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);\n\n    /* Random or non-zero hash seed */\n    Py_HashRandomizationFlag = (config->use_hash_seed == 0 ||\n                                config->hash_seed != 0);\n\n#undef COPY_FLAG\n#undef COPY_NOT_FLAG\n_Py_COMP_DIAG_POP\n}\n\n\nstatic const wchar_t*\nconfig_get_xoption(const PyConfig *config, wchar_t *name)\n{\n    return _Py_get_xoption(&config->xoptions, name);\n}\n\nstatic const wchar_t*\nconfig_get_xoption_value(const PyConfig *config, wchar_t *name)\n{\n    const wchar_t *xoption = config_get_xoption(config, name);\n    if (xoption == NULL) {\n        return NULL;\n    }\n    const wchar_t *sep = wcschr(xoption, L'=');\n    return sep ? sep + 1 : L\"\";\n}\n\n\nstatic PyStatus\nconfig_init_hash_seed(PyConfig *config)\n{\n    static_assert(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc),\n                  \"_Py_HashSecret_t has wrong size\");\n\n    const char *seed_text = config_get_env(config, \"PYTHONHASHSEED\");\n\n    /* Convert a text seed to a numeric one */\n    if (seed_text && strcmp(seed_text, \"random\") != 0) {\n        const char *endptr = seed_text;\n        unsigned long seed;\n        errno = 0;\n        seed = strtoul(seed_text, (char **)&endptr, 10);\n        if (*endptr != '\\0'\n            || seed > MAX_HASH_SEED\n            || (errno == ERANGE && seed == ULONG_MAX))\n        {\n            return _PyStatus_ERR(\"PYTHONHASHSEED must be \\\"random\\\" \"\n                                \"or an integer in range [0; 4294967295]\");\n        }\n        /* Use a specific hash */\n        config->use_hash_seed = 1;\n        config->hash_seed = seed;\n    }\n    else {\n        /* Use a random hash */\n        config->use_hash_seed = 0;\n        config->hash_seed = 0;\n    }\n    return _PyStatus_OK();\n}\n\n\nstatic int\nconfig_wstr_to_int(const wchar_t *wstr, int *result)\n{\n    const wchar_t *endptr = wstr;\n    errno = 0;\n    long value = wcstol(wstr, (wchar_t **)&endptr, 10);\n    if (*endptr != '\\0' || errno == ERANGE) {\n        return -1;\n    }\n    if (value < INT_MIN || value > INT_MAX) {\n        return -1;\n    }\n\n    *result = (int)value;\n    return 0;\n}\n\n\nstatic PyStatus\nconfig_read_env_vars(PyConfig *config)\n{\n    PyStatus status;\n    int use_env = config->use_environment;\n\n    /* Get environment variables */\n    _Py_get_env_flag(use_env, &config->parser_debug, \"PYTHONDEBUG\");\n    _Py_get_env_flag(use_env, &config->verbose, \"PYTHONVERBOSE\");\n    _Py_get_env_flag(use_env, &config->optimization_level, \"PYTHONOPTIMIZE\");\n    _Py_get_env_flag(use_env, &config->inspect, \"PYTHONINSPECT\");\n\n    int dont_write_bytecode = 0;\n    _Py_get_env_flag(use_env, &dont_write_bytecode, \"PYTHONDONTWRITEBYTECODE\");\n    if (dont_write_bytecode) {\n        config->write_bytecode = 0;\n    }\n\n    int no_user_site_directory = 0;\n    _Py_get_env_flag(use_env, &no_user_site_directory, \"PYTHONNOUSERSITE\");\n    if (no_user_site_directory) {\n        config->user_site_directory = 0;\n    }\n\n    int unbuffered_stdio = 0;\n    _Py_get_env_flag(use_env, &unbuffered_stdio, \"PYTHONUNBUFFERED\");\n    if (unbuffered_stdio) {\n        config->buffered_stdio = 0;\n    }\n\n#ifdef MS_WINDOWS\n    _Py_get_env_flag(use_env, &config->legacy_windows_stdio,\n                     \"PYTHONLEGACYWINDOWSSTDIO\");\n#endif\n\n    if (config_get_env(config, \"PYTHONDUMPREFS\")) {\n        config->dump_refs = 1;\n    }\n    if (config_get_env(config, \"PYTHONMALLOCSTATS\")) {\n        config->malloc_stats = 1;\n    }\n\n    if (config->dump_refs_file == NULL) {\n        status = CONFIG_GET_ENV_DUP(config, &config->dump_refs_file,\n                                    L\"PYTHONDUMPREFSFILE\", \"PYTHONDUMPREFSFILE\");\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    if (config->pythonpath_env == NULL) {\n        status = CONFIG_GET_ENV_DUP(config, &config->pythonpath_env,\n                                    L\"PYTHONPATH\", \"PYTHONPATH\");\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    if(config->platlibdir == NULL) {\n        status = CONFIG_GET_ENV_DUP(config, &config->platlibdir,\n                                    L\"PYTHONPLATLIBDIR\", \"PYTHONPLATLIBDIR\");\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    if (config->use_hash_seed < 0) {\n        status = config_init_hash_seed(config);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    if (config_get_env(config, \"PYTHONSAFEPATH\")) {\n        config->safe_path = 1;\n    }\n\n    return _PyStatus_OK();\n}\n\nstatic PyStatus\nconfig_init_perf_profiling(PyConfig *config)\n{\n    int active = 0;\n    const char *env = config_get_env(config, \"PYTHONPERFSUPPORT\");\n    if (env) {\n        if (_Py_str_to_int(env, &active) != 0) {\n            active = 0;\n        }\n        if (active) {\n            config->perf_profiling = 1;\n        }\n    }\n    const wchar_t *xoption = config_get_xoption(config, L\"perf\");\n    if (xoption) {\n        config->perf_profiling = 1;\n    }\n    return _PyStatus_OK();\n\n}\n\nstatic PyStatus\nconfig_init_tracemalloc(PyConfig *config)\n{\n    int nframe;\n    int valid;\n\n    const char *env = config_get_env(config, \"PYTHONTRACEMALLOC\");\n    if (env) {\n        if (!_Py_str_to_int(env, &nframe)) {\n            valid = (nframe >= 0);\n        }\n        else {\n            valid = 0;\n        }\n        if (!valid) {\n            return _PyStatus_ERR(\"PYTHONTRACEMALLOC: invalid number of frames\");\n        }\n        config->tracemalloc = nframe;\n    }\n\n    const wchar_t *xoption = config_get_xoption(config, L\"tracemalloc\");\n    if (xoption) {\n        const wchar_t *sep = wcschr(xoption, L'=');\n        if (sep) {\n            if (!config_wstr_to_int(sep + 1, &nframe)) {\n                valid = (nframe >= 0);\n            }\n            else {\n                valid = 0;\n            }\n            if (!valid) {\n                return _PyStatus_ERR(\"-X tracemalloc=NFRAME: \"\n                                     \"invalid number of frames\");\n            }\n        }\n        else {\n            /* -X tracemalloc behaves as -X tracemalloc=1 */\n            nframe = 1;\n        }\n        config->tracemalloc = nframe;\n    }\n    return _PyStatus_OK();\n}\n\nstatic PyStatus\nconfig_init_int_max_str_digits(PyConfig *config)\n{\n    int maxdigits;\n\n    const char *env = config_get_env(config, \"PYTHONINTMAXSTRDIGITS\");\n    if (env) {\n        bool valid = 0;\n        if (!_Py_str_to_int(env, &maxdigits)) {\n            valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));\n        }\n        if (!valid) {\n#define STRINGIFY(VAL) _STRINGIFY(VAL)\n#define _STRINGIFY(VAL) #VAL\n            return _PyStatus_ERR(\n                    \"PYTHONINTMAXSTRDIGITS: invalid limit; must be >= \"\n                    STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)\n                    \" or 0 for unlimited.\");\n        }\n        config->int_max_str_digits = maxdigits;\n    }\n\n    const wchar_t *xoption = config_get_xoption(config, L\"int_max_str_digits\");\n    if (xoption) {\n        const wchar_t *sep = wcschr(xoption, L'=');\n        bool valid = 0;\n        if (sep) {\n            if (!config_wstr_to_int(sep + 1, &maxdigits)) {\n                valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));\n            }\n        }\n        if (!valid) {\n            return _PyStatus_ERR(\n                    \"-X int_max_str_digits: invalid limit; must be >= \"\n                    STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)\n                    \" or 0 for unlimited.\");\n#undef _STRINGIFY\n#undef STRINGIFY\n        }\n        config->int_max_str_digits = maxdigits;\n    }\n    if (config->int_max_str_digits < 0) {\n        config->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;\n    }\n    return _PyStatus_OK();\n}\n\nstatic PyStatus\nconfig_init_pycache_prefix(PyConfig *config)\n{\n    assert(config->pycache_prefix == NULL);\n\n    const wchar_t *xoption = config_get_xoption(config, L\"pycache_prefix\");\n    if (xoption) {\n        const wchar_t *sep = wcschr(xoption, L'=');\n        if (sep && wcslen(sep) > 1) {\n            config->pycache_prefix = _PyMem_RawWcsdup(sep + 1);\n            if (config->pycache_prefix == NULL) {\n                return _PyStatus_NO_MEMORY();\n            }\n        }\n        else {\n            // PYTHONPYCACHEPREFIX env var ignored\n            // if \"-X pycache_prefix=\" option is used\n            config->pycache_prefix = NULL;\n        }\n        return _PyStatus_OK();\n    }\n\n    return CONFIG_GET_ENV_DUP(config, &config->pycache_prefix,\n                              L\"PYTHONPYCACHEPREFIX\",\n                              \"PYTHONPYCACHEPREFIX\");\n}\n\n\nstatic PyStatus\nconfig_read_complex_options(PyConfig *config)\n{\n    /* More complex options configured by env var and -X option */\n    if (config->faulthandler < 0) {\n        if (config_get_env(config, \"PYTHONFAULTHANDLER\")\n           || config_get_xoption(config, L\"faulthandler\")) {\n            config->faulthandler = 1;\n        }\n    }\n    if (config_get_env(config, \"PYTHONPROFILEIMPORTTIME\")\n       || config_get_xoption(config, L\"importtime\")) {\n        config->import_time = 1;\n    }\n\n    if (config_get_env(config, \"PYTHONNODEBUGRANGES\")\n       || config_get_xoption(config, L\"no_debug_ranges\")) {\n        config->code_debug_ranges = 0;\n    }\n\n    PyStatus status;\n    if (config->tracemalloc < 0) {\n        status = config_init_tracemalloc(config);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    if (config->perf_profiling < 0) {\n        status = config_init_perf_profiling(config);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    if (config->int_max_str_digits < 0) {\n        status = config_init_int_max_str_digits(config);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    if (config->pycache_prefix == NULL) {\n        status = config_init_pycache_prefix(config);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n    return _PyStatus_OK();\n}\n\n\nstatic const wchar_t *\nconfig_get_stdio_errors(const PyPreConfig *preconfig)\n{\n    if (preconfig->utf8_mode) {\n        /* UTF-8 Mode uses UTF-8/surrogateescape */\n        return L\"surrogateescape\";\n    }\n\n#ifndef MS_WINDOWS\n    const char *loc = setlocale(LC_CTYPE, NULL);\n    if (loc != NULL) {\n        /* surrogateescape is the default in the legacy C and POSIX locales */\n        if (strcmp(loc, \"C\") == 0 || strcmp(loc, \"POSIX\") == 0) {\n            return L\"surrogateescape\";\n        }\n\n#ifdef PY_COERCE_C_LOCALE\n        /* surrogateescape is the default in locale coercion target locales */\n        if (_Py_IsLocaleCoercionTarget(loc)) {\n            return L\"surrogateescape\";\n        }\n#endif\n    }\n\n    return L\"strict\";\n#else\n    /* On Windows, always use surrogateescape by default */\n    return L\"surrogateescape\";\n#endif\n}\n\n\n// See also config_get_fs_encoding()\nstatic PyStatus\nconfig_get_locale_encoding(PyConfig *config, const PyPreConfig *preconfig,\n                           wchar_t **locale_encoding)\n{\n    wchar_t *encoding;\n    if (preconfig->utf8_mode) {\n        encoding = _PyMem_RawWcsdup(L\"utf-8\");\n    }\n    else {\n        encoding = _Py_GetLocaleEncoding();\n    }\n    if (encoding == NULL) {\n        return _PyStatus_NO_MEMORY();\n    }\n    PyStatus status = PyConfig_SetString(config, locale_encoding, encoding);\n    PyMem_RawFree(encoding);\n    return status;\n}\n\n\nstatic PyStatus\nconfig_init_stdio_encoding(PyConfig *config,\n                           const PyPreConfig *preconfig)\n{\n    PyStatus status;\n\n    // Exit if encoding and errors are defined\n    if (config->stdio_encoding != NULL && config->stdio_errors != NULL) {\n        return _PyStatus_OK();\n    }\n\n    /* PYTHONIOENCODING environment variable */\n    const char *opt = config_get_env(config, \"PYTHONIOENCODING\");\n    if (opt) {\n        char *pythonioencoding = _PyMem_RawStrdup(opt);\n        if (pythonioencoding == NULL) {\n            return _PyStatus_NO_MEMORY();\n        }\n\n        char *errors = strchr(pythonioencoding, ':');\n        if (errors) {\n            *errors = '\\0';\n            errors++;\n            if (!errors[0]) {\n                errors = NULL;\n            }\n        }\n\n        /* Does PYTHONIOENCODING contain an encoding? */\n        if (pythonioencoding[0]) {\n            if (config->stdio_encoding == NULL) {\n                status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding,\n                                              pythonioencoding,\n                                              \"PYTHONIOENCODING environment variable\");\n                if (_PyStatus_EXCEPTION(status)) {\n                    PyMem_RawFree(pythonioencoding);\n                    return status;\n                }\n            }\n\n            /* If the encoding is set but not the error handler,\n               use \"strict\" error handler by default.\n               PYTHONIOENCODING=latin1 behaves as\n               PYTHONIOENCODING=latin1:strict. */\n            if (!errors) {\n                errors = \"strict\";\n            }\n        }\n\n        if (config->stdio_errors == NULL && errors != NULL) {\n            status = CONFIG_SET_BYTES_STR(config, &config->stdio_errors,\n                                          errors,\n                                          \"PYTHONIOENCODING environment variable\");\n            if (_PyStatus_EXCEPTION(status)) {\n                PyMem_RawFree(pythonioencoding);\n                return status;\n            }\n        }\n\n        PyMem_RawFree(pythonioencoding);\n    }\n\n    /* Choose the default error handler based on the current locale. */\n    if (config->stdio_encoding == NULL) {\n        status = config_get_locale_encoding(config, preconfig,\n                                            &config->stdio_encoding);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n    if (config->stdio_errors == NULL) {\n        const wchar_t *errors = config_get_stdio_errors(preconfig);\n        assert(errors != NULL);\n\n        status = PyConfig_SetString(config, &config->stdio_errors, errors);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    return _PyStatus_OK();\n}\n\n\n// See also config_get_locale_encoding()\nstatic PyStatus\nconfig_get_fs_encoding(PyConfig *config, const PyPreConfig *preconfig,\n                       wchar_t **fs_encoding)\n{\n#ifdef _Py_FORCE_UTF8_FS_ENCODING\n    return PyConfig_SetString(config, fs_encoding, L\"utf-8\");\n#elif defined(MS_WINDOWS)\n    const wchar_t *encoding;\n    if (preconfig->legacy_windows_fs_encoding) {\n        // Legacy Windows filesystem encoding: mbcs/replace\n        encoding = L\"mbcs\";\n    }\n    else {\n        // Windows defaults to utf-8/surrogatepass (PEP 529)\n        encoding = L\"utf-8\";\n    }\n     return PyConfig_SetString(config, fs_encoding, encoding);\n#else  // !MS_WINDOWS\n    if (preconfig->utf8_mode) {\n        return PyConfig_SetString(config, fs_encoding, L\"utf-8\");\n    }\n\n    if (_Py_GetForceASCII()) {\n        return PyConfig_SetString(config, fs_encoding, L\"ascii\");\n    }\n\n    return config_get_locale_encoding(config, preconfig, fs_encoding);\n#endif  // !MS_WINDOWS\n}\n\n\nstatic PyStatus\nconfig_init_fs_encoding(PyConfig *config, const PyPreConfig *preconfig)\n{\n    PyStatus status;\n\n    if (config->filesystem_encoding == NULL) {\n        status = config_get_fs_encoding(config, preconfig,\n                                        &config->filesystem_encoding);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    if (config->filesystem_errors == NULL) {\n        const wchar_t *errors;\n#ifdef MS_WINDOWS\n        if (preconfig->legacy_windows_fs_encoding) {\n            errors = L\"replace\";\n        }\n        else {\n            errors = L\"surrogatepass\";\n        }\n#else\n        errors = L\"surrogateescape\";\n#endif\n        status = PyConfig_SetString(config, &config->filesystem_errors, errors);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\nconfig_init_import(PyConfig *config, int compute_path_config)\n{\n    PyStatus status;\n\n    status = _PyConfig_InitPathConfig(config, compute_path_config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    /* -X frozen_modules=[on|off] */\n    const wchar_t *value = config_get_xoption_value(config, L\"frozen_modules\");\n    if (value == NULL) {\n    }\n    else if (wcscmp(value, L\"on\") == 0) {\n        config->use_frozen_modules = 1;\n    }\n    else if (wcscmp(value, L\"off\") == 0) {\n        config->use_frozen_modules = 0;\n    }\n    else if (wcslen(value) == 0) {\n        // \"-X frozen_modules\" and \"-X frozen_modules=\" both imply \"on\".\n        config->use_frozen_modules = 1;\n    }\n    else {\n        return PyStatus_Error(\"bad value for option -X frozen_modules \"\n                              \"(expected \\\"on\\\" or \\\"off\\\")\");\n    }\n\n    assert(config->use_frozen_modules >= 0);\n    return _PyStatus_OK();\n}\n\nPyStatus\n_PyConfig_InitImportConfig(PyConfig *config)\n{\n    return config_init_import(config, 1);\n}\n\n\nstatic PyStatus\nconfig_read(PyConfig *config, int compute_path_config)\n{\n    PyStatus status;\n    const PyPreConfig *preconfig = &_PyRuntime.preconfig;\n\n    if (config->use_environment) {\n        status = config_read_env_vars(config);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    /* -X options */\n    if (config_get_xoption(config, L\"showrefcount\")) {\n        config->show_ref_count = 1;\n    }\n\n#ifdef Py_STATS\n    if (config_get_xoption(config, L\"pystats\")) {\n        _py_stats = &_py_stats_struct;\n    }\n#endif\n\n    status = config_read_complex_options(config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    if (config->_install_importlib) {\n        status = config_init_import(config, compute_path_config);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    /* default values */\n    if (config->dev_mode) {\n        if (config->faulthandler < 0) {\n            config->faulthandler = 1;\n        }\n    }\n    if (config->faulthandler < 0) {\n        config->faulthandler = 0;\n    }\n    if (config->tracemalloc < 0) {\n        config->tracemalloc = 0;\n    }\n    if (config->perf_profiling < 0) {\n        config->perf_profiling = 0;\n    }\n    if (config->use_hash_seed < 0) {\n        config->use_hash_seed = 0;\n        config->hash_seed = 0;\n    }\n\n    if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) {\n        status = config_init_fs_encoding(config, preconfig);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    status = config_init_stdio_encoding(config, preconfig);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    if (config->argv.length < 1) {\n        /* Ensure at least one (empty) argument is seen */\n        status = PyWideStringList_Append(&config->argv, L\"\");\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    if (config->check_hash_pycs_mode == NULL) {\n        status = PyConfig_SetString(config, &config->check_hash_pycs_mode,\n                                    L\"default\");\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    if (config->configure_c_stdio < 0) {\n        config->configure_c_stdio = 1;\n    }\n\n    // Only parse arguments once.\n    if (config->parse_argv == 1) {\n        config->parse_argv = 2;\n    }\n\n    return _PyStatus_OK();\n}\n\n\nstatic void\nconfig_init_stdio(const PyConfig *config)\n{\n#if defined(MS_WINDOWS) || defined(__CYGWIN__)\n    /* don't translate newlines (\\r\\n <=> \\n) */\n    _setmode(fileno(stdin), O_BINARY);\n    _setmode(fileno(stdout), O_BINARY);\n    _setmode(fileno(stderr), O_BINARY);\n#endif\n\n    if (!config->buffered_stdio) {\n#ifdef HAVE_SETVBUF\n        setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);\n        setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);\n        setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);\n#else /* !HAVE_SETVBUF */\n        setbuf(stdin,  (char *)NULL);\n        setbuf(stdout, (char *)NULL);\n        setbuf(stderr, (char *)NULL);\n#endif /* !HAVE_SETVBUF */\n    }\n    else if (config->interactive) {\n#ifdef MS_WINDOWS\n        /* Doesn't have to have line-buffered -- use unbuffered */\n        /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */\n        setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);\n#else /* !MS_WINDOWS */\n#ifdef HAVE_SETVBUF\n        setvbuf(stdin,  (char *)NULL, _IOLBF, BUFSIZ);\n        setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);\n#endif /* HAVE_SETVBUF */\n#endif /* !MS_WINDOWS */\n        /* Leave stderr alone - it should be unbuffered anyway. */\n    }\n}\n\n\n/* Write the configuration:\n\n   - set Py_xxx global configuration variables\n   - initialize C standard streams (stdin, stdout, stderr) */\nPyStatus\n_PyConfig_Write(const PyConfig *config, _PyRuntimeState *runtime)\n{\n    config_set_global_vars(config);\n\n    if (config->configure_c_stdio) {\n        config_init_stdio(config);\n    }\n\n    /* Write the new pre-configuration into _PyRuntime */\n    PyPreConfig *preconfig = &runtime->preconfig;\n    preconfig->isolated = config->isolated;\n    preconfig->use_environment = config->use_environment;\n    preconfig->dev_mode = config->dev_mode;\n\n    if (_Py_SetArgcArgv(config->orig_argv.length,\n                        config->orig_argv.items) < 0)\n    {\n        return _PyStatus_NO_MEMORY();\n    }\n    return _PyStatus_OK();\n}\n\n\n/* --- PyConfig command line parser -------------------------- */\n\nstatic void\nconfig_usage(int error, const wchar_t* program)\n{\n    FILE *f = error ? stderr : stdout;\n\n    fprintf(f, usage_line, program);\n    if (error)\n        fprintf(f, \"Try `python -h' for more information.\\n\");\n    else {\n        fputs(usage_help, f);\n    }\n}\n\nstatic void\nconfig_envvars_usage(void)\n{\n    printf(usage_envvars, (wint_t)DELIM, (wint_t)DELIM, PYTHONHOMEHELP);\n}\n\nstatic void\nconfig_xoptions_usage(void)\n{\n    puts(usage_xoptions);\n}\n\nstatic void\nconfig_complete_usage(const wchar_t* program)\n{\n   config_usage(0, program);\n   puts(\"\\n\");\n   config_envvars_usage();\n   puts(\"\\n\");\n   config_xoptions_usage();\n}\n\n\n/* Parse the command line arguments */\nstatic PyStatus\nconfig_parse_cmdline(PyConfig *config, PyWideStringList *warnoptions,\n                     Py_ssize_t *opt_index)\n{\n    PyStatus status;\n    const PyWideStringList *argv = &config->argv;\n    int print_version = 0;\n    const wchar_t* program = config->program_name;\n    if (!program && argv->length >= 1) {\n        program = argv->items[0];\n    }\n\n    _PyOS_ResetGetOpt();\n    do {\n        int longindex = -1;\n        int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);\n        if (c == EOF) {\n            break;\n        }\n\n        if (c == 'c') {\n            if (config->run_command == NULL) {\n                /* -c is the last option; following arguments\n                   that look like options are left for the\n                   command to interpret. */\n                size_t len = wcslen(_PyOS_optarg) + 1 + 1;\n                wchar_t *command = PyMem_RawMalloc(sizeof(wchar_t) * len);\n                if (command == NULL) {\n                    return _PyStatus_NO_MEMORY();\n                }\n                memcpy(command, _PyOS_optarg, (len - 2) * sizeof(wchar_t));\n                command[len - 2] = '\\n';\n                command[len - 1] = 0;\n                config->run_command = command;\n            }\n            break;\n        }\n\n        if (c == 'm') {\n            /* -m is the last option; following arguments\n               that look like options are left for the\n               module to interpret. */\n            if (config->run_module == NULL) {\n                config->run_module = _PyMem_RawWcsdup(_PyOS_optarg);\n                if (config->run_module == NULL) {\n                    return _PyStatus_NO_MEMORY();\n                }\n            }\n            break;\n        }\n\n        switch (c) {\n        // Integers represent long options, see Python/getopt.c\n        case 0:\n            // check-hash-based-pycs\n            if (wcscmp(_PyOS_optarg, L\"always\") == 0\n                || wcscmp(_PyOS_optarg, L\"never\") == 0\n                || wcscmp(_PyOS_optarg, L\"default\") == 0)\n            {\n                status = PyConfig_SetString(config, &config->check_hash_pycs_mode,\n                                            _PyOS_optarg);\n                if (_PyStatus_EXCEPTION(status)) {\n                    return status;\n                }\n            } else {\n                fprintf(stderr, \"--check-hash-based-pycs must be one of \"\n                        \"'default', 'always', or 'never'\\n\");\n                config_usage(1, program);\n                return _PyStatus_EXIT(2);\n            }\n            break;\n\n        case 1:\n            // help-all\n            config_complete_usage(program);\n            return _PyStatus_EXIT(0);\n\n        case 2:\n            // help-env\n            config_envvars_usage();\n            return _PyStatus_EXIT(0);\n\n        case 3:\n            // help-xoptions\n            config_xoptions_usage();\n            return _PyStatus_EXIT(0);\n\n        case 'b':\n            config->bytes_warning++;\n            break;\n\n        case 'd':\n            config->parser_debug++;\n            break;\n\n        case 'i':\n            config->inspect++;\n            config->interactive++;\n            break;\n\n        case 'E':\n        case 'I':\n        case 'X':\n            /* option handled by _PyPreCmdline_Read() */\n            break;\n\n        /* case 'J': reserved for Jython */\n\n        case 'O':\n            config->optimization_level++;\n            break;\n\n        case 'P':\n            config->safe_path = 1;\n            break;\n\n        case 'B':\n            config->write_bytecode = 0;\n            break;\n\n        case 's':\n            config->user_site_directory = 0;\n            break;\n\n        case 'S':\n            config->site_import = 0;\n            break;\n\n        case 't':\n            /* ignored for backwards compatibility */\n            break;\n\n        case 'u':\n            config->buffered_stdio = 0;\n            break;\n\n        case 'v':\n            config->verbose++;\n            break;\n\n        case 'x':\n            config->skip_source_first_line = 1;\n            break;\n\n        case 'h':\n        case '?':\n            config_usage(0, program);\n            return _PyStatus_EXIT(0);\n\n        case 'V':\n            print_version++;\n            break;\n\n        case 'W':\n            status = PyWideStringList_Append(warnoptions, _PyOS_optarg);\n            if (_PyStatus_EXCEPTION(status)) {\n                return status;\n            }\n            break;\n\n        case 'q':\n            config->quiet++;\n            break;\n\n        case 'R':\n            config->use_hash_seed = 0;\n            break;\n\n        /* This space reserved for other options */\n\n        default:\n            /* unknown argument: parsing failed */\n            config_usage(1, program);\n            return _PyStatus_EXIT(2);\n        }\n    } while (1);\n\n    if (print_version) {\n        printf(\"Python %s\\n\",\n                (print_version >= 2) ? Py_GetVersion() : PY_VERSION);\n        return _PyStatus_EXIT(0);\n    }\n\n    if (config->run_command == NULL && config->run_module == NULL\n        && _PyOS_optind < argv->length\n        && wcscmp(argv->items[_PyOS_optind], L\"-\") != 0\n        && config->run_filename == NULL)\n    {\n        config->run_filename = _PyMem_RawWcsdup(argv->items[_PyOS_optind]);\n        if (config->run_filename == NULL) {\n            return _PyStatus_NO_MEMORY();\n        }\n    }\n\n    if (config->run_command != NULL || config->run_module != NULL) {\n        /* Backup _PyOS_optind */\n        _PyOS_optind--;\n    }\n\n    *opt_index = _PyOS_optind;\n\n    return _PyStatus_OK();\n}\n\n\n#ifdef MS_WINDOWS\n#  define WCSTOK wcstok_s\n#else\n#  define WCSTOK wcstok\n#endif\n\n/* Get warning options from PYTHONWARNINGS environment variable. */\nstatic PyStatus\nconfig_init_env_warnoptions(PyConfig *config, PyWideStringList *warnoptions)\n{\n    PyStatus status;\n    /* CONFIG_GET_ENV_DUP requires dest to be initialized to NULL */\n    wchar_t *env = NULL;\n    status = CONFIG_GET_ENV_DUP(config, &env,\n                             L\"PYTHONWARNINGS\", \"PYTHONWARNINGS\");\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    /* env var is not set or is empty */\n    if (env == NULL) {\n        return _PyStatus_OK();\n    }\n\n\n    wchar_t *warning, *context = NULL;\n    for (warning = WCSTOK(env, L\",\", &context);\n         warning != NULL;\n         warning = WCSTOK(NULL, L\",\", &context))\n    {\n        status = PyWideStringList_Append(warnoptions, warning);\n        if (_PyStatus_EXCEPTION(status)) {\n            PyMem_RawFree(env);\n            return status;\n        }\n    }\n    PyMem_RawFree(env);\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\nwarnoptions_append(PyConfig *config, PyWideStringList *options,\n                   const wchar_t *option)\n{\n    /* config_init_warnoptions() add existing config warnoptions at the end:\n       ensure that the new option is not already present in this list to\n       prevent change the options order when config_init_warnoptions() is\n       called twice. */\n    if (_PyWideStringList_Find(&config->warnoptions, option)) {\n        /* Already present: do nothing */\n        return _PyStatus_OK();\n    }\n    if (_PyWideStringList_Find(options, option)) {\n        /* Already present: do nothing */\n        return _PyStatus_OK();\n    }\n    return PyWideStringList_Append(options, option);\n}\n\n\nstatic PyStatus\nwarnoptions_extend(PyConfig *config, PyWideStringList *options,\n                   const PyWideStringList *options2)\n{\n    const Py_ssize_t len = options2->length;\n    wchar_t *const *items = options2->items;\n\n    for (Py_ssize_t i = 0; i < len; i++) {\n        PyStatus status = warnoptions_append(config, options, items[i]);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\nconfig_init_warnoptions(PyConfig *config,\n                        const PyWideStringList *cmdline_warnoptions,\n                        const PyWideStringList *env_warnoptions,\n                        const PyWideStringList *sys_warnoptions)\n{\n    PyStatus status;\n    PyWideStringList options = _PyWideStringList_INIT;\n\n    /* Priority of warnings options, lowest to highest:\n     *\n     * - any implicit filters added by _warnings.c/warnings.py\n     * - PyConfig.dev_mode: \"default\" filter\n     * - PYTHONWARNINGS environment variable\n     * - '-W' command line options\n     * - PyConfig.bytes_warning ('-b' and '-bb' command line options):\n     *   \"default::BytesWarning\" or \"error::BytesWarning\" filter\n     * - early PySys_AddWarnOption() calls\n     * - PyConfig.warnoptions\n     *\n     * PyConfig.warnoptions is copied to sys.warnoptions. Since the warnings\n     * module works on the basis of \"the most recently added filter will be\n     * checked first\", we add the lowest precedence entries first so that later\n     * entries override them.\n     */\n\n    if (config->dev_mode) {\n        status = warnoptions_append(config, &options, L\"default\");\n        if (_PyStatus_EXCEPTION(status)) {\n            goto error;\n        }\n    }\n\n    status = warnoptions_extend(config, &options, env_warnoptions);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto error;\n    }\n\n    status = warnoptions_extend(config, &options, cmdline_warnoptions);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto error;\n    }\n\n    /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c\n     * don't even try to emit a warning, so we skip setting the filter in that\n     * case.\n     */\n    if (config->bytes_warning) {\n        const wchar_t *filter;\n        if (config->bytes_warning> 1) {\n            filter = L\"error::BytesWarning\";\n        }\n        else {\n            filter = L\"default::BytesWarning\";\n        }\n        status = warnoptions_append(config, &options, filter);\n        if (_PyStatus_EXCEPTION(status)) {\n            goto error;\n        }\n    }\n\n    status = warnoptions_extend(config, &options, sys_warnoptions);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto error;\n    }\n\n    /* Always add all PyConfig.warnoptions options */\n    status = _PyWideStringList_Extend(&options, &config->warnoptions);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto error;\n    }\n\n    _PyWideStringList_Clear(&config->warnoptions);\n    config->warnoptions = options;\n    return _PyStatus_OK();\n\nerror:\n    _PyWideStringList_Clear(&options);\n    return status;\n}\n\n\nstatic PyStatus\nconfig_update_argv(PyConfig *config, Py_ssize_t opt_index)\n{\n    const PyWideStringList *cmdline_argv = &config->argv;\n    PyWideStringList config_argv = _PyWideStringList_INIT;\n\n    /* Copy argv to be able to modify it (to force -c/-m) */\n    if (cmdline_argv->length <= opt_index) {\n        /* Ensure at least one (empty) argument is seen */\n        PyStatus status = PyWideStringList_Append(&config_argv, L\"\");\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n    else {\n        PyWideStringList slice;\n        slice.length = cmdline_argv->length - opt_index;\n        slice.items = &cmdline_argv->items[opt_index];\n        if (_PyWideStringList_Copy(&config_argv, &slice) < 0) {\n            return _PyStatus_NO_MEMORY();\n        }\n    }\n    assert(config_argv.length >= 1);\n\n    wchar_t *arg0 = NULL;\n    if (config->run_command != NULL) {\n        /* Force sys.argv[0] = '-c' */\n        arg0 = L\"-c\";\n    }\n    else if (config->run_module != NULL) {\n        /* Force sys.argv[0] = '-m'*/\n        arg0 = L\"-m\";\n    }\n\n    if (arg0 != NULL) {\n        arg0 = _PyMem_RawWcsdup(arg0);\n        if (arg0 == NULL) {\n            _PyWideStringList_Clear(&config_argv);\n            return _PyStatus_NO_MEMORY();\n        }\n\n        PyMem_RawFree(config_argv.items[0]);\n        config_argv.items[0] = arg0;\n    }\n\n    _PyWideStringList_Clear(&config->argv);\n    config->argv = config_argv;\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\ncore_read_precmdline(PyConfig *config, _PyPreCmdline *precmdline)\n{\n    PyStatus status;\n\n    if (config->parse_argv == 1) {\n        if (_PyWideStringList_Copy(&precmdline->argv, &config->argv) < 0) {\n            return _PyStatus_NO_MEMORY();\n        }\n    }\n\n    PyPreConfig preconfig;\n\n    status = _PyPreConfig_InitFromPreConfig(&preconfig, &_PyRuntime.preconfig);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    _PyPreConfig_GetConfig(&preconfig, config);\n\n    status = _PyPreCmdline_Read(precmdline, &preconfig);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyPreCmdline_SetConfig(precmdline, config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    return _PyStatus_OK();\n}\n\n\n/* Get run_filename absolute path */\nstatic PyStatus\nconfig_run_filename_abspath(PyConfig *config)\n{\n    if (!config->run_filename) {\n        return _PyStatus_OK();\n    }\n\n#ifndef MS_WINDOWS\n    if (_Py_isabs(config->run_filename)) {\n        /* path is already absolute */\n        return _PyStatus_OK();\n    }\n#endif\n\n    wchar_t *abs_filename;\n    if (_Py_abspath(config->run_filename, &abs_filename) < 0) {\n        /* failed to get the absolute path of the command line filename:\n           ignore the error, keep the relative path */\n        return _PyStatus_OK();\n    }\n    if (abs_filename == NULL) {\n        return _PyStatus_NO_MEMORY();\n    }\n\n    PyMem_RawFree(config->run_filename);\n    config->run_filename = abs_filename;\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\nconfig_read_cmdline(PyConfig *config)\n{\n    PyStatus status;\n    PyWideStringList cmdline_warnoptions = _PyWideStringList_INIT;\n    PyWideStringList env_warnoptions = _PyWideStringList_INIT;\n    PyWideStringList sys_warnoptions = _PyWideStringList_INIT;\n\n    if (config->parse_argv < 0) {\n        config->parse_argv = 1;\n    }\n\n    if (config->parse_argv == 1) {\n        Py_ssize_t opt_index;\n        status = config_parse_cmdline(config, &cmdline_warnoptions, &opt_index);\n        if (_PyStatus_EXCEPTION(status)) {\n            goto done;\n        }\n\n        status = config_run_filename_abspath(config);\n        if (_PyStatus_EXCEPTION(status)) {\n            goto done;\n        }\n\n        status = config_update_argv(config, opt_index);\n        if (_PyStatus_EXCEPTION(status)) {\n            goto done;\n        }\n    }\n    else {\n        status = config_run_filename_abspath(config);\n        if (_PyStatus_EXCEPTION(status)) {\n            goto done;\n        }\n    }\n\n    if (config->use_environment) {\n        status = config_init_env_warnoptions(config, &env_warnoptions);\n        if (_PyStatus_EXCEPTION(status)) {\n            goto done;\n        }\n    }\n\n    /* Handle early PySys_AddWarnOption() calls */\n    status = _PySys_ReadPreinitWarnOptions(&sys_warnoptions);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\n    status = config_init_warnoptions(config,\n                                     &cmdline_warnoptions,\n                                     &env_warnoptions,\n                                     &sys_warnoptions);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\n    status = _PyStatus_OK();\n\ndone:\n    _PyWideStringList_Clear(&cmdline_warnoptions);\n    _PyWideStringList_Clear(&env_warnoptions);\n    _PyWideStringList_Clear(&sys_warnoptions);\n    return status;\n}\n\n\nPyStatus\n_PyConfig_SetPyArgv(PyConfig *config, const _PyArgv *args)\n{\n    PyStatus status = _Py_PreInitializeFromConfig(config, args);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    return _PyArgv_AsWstrList(args, &config->argv);\n}\n\n\n/* Set config.argv: decode argv using Py_DecodeLocale(). Pre-initialize Python\n   if needed to ensure that encodings are properly configured. */\nPyStatus\nPyConfig_SetBytesArgv(PyConfig *config, Py_ssize_t argc, char * const *argv)\n{\n    _PyArgv args = {\n        .argc = argc,\n        .use_bytes_argv = 1,\n        .bytes_argv = argv,\n        .wchar_argv = NULL};\n    return _PyConfig_SetPyArgv(config, &args);\n}\n\n\nPyStatus\nPyConfig_SetArgv(PyConfig *config, Py_ssize_t argc, wchar_t * const *argv)\n{\n    _PyArgv args = {\n        .argc = argc,\n        .use_bytes_argv = 0,\n        .bytes_argv = NULL,\n        .wchar_argv = argv};\n    return _PyConfig_SetPyArgv(config, &args);\n}\n\n\nPyStatus\nPyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list,\n                           Py_ssize_t length, wchar_t **items)\n{\n    PyStatus status = _Py_PreInitializeFromConfig(config, NULL);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    PyWideStringList list2 = {.length = length, .items = items};\n    if (_PyWideStringList_Copy(list, &list2) < 0) {\n        return _PyStatus_NO_MEMORY();\n    }\n    return _PyStatus_OK();\n}\n\n\n/* Read the configuration into PyConfig from:\n\n   * Command line arguments\n   * Environment variables\n   * Py_xxx global configuration variables\n\n   The only side effects are to modify config and to call _Py_SetArgcArgv(). */\nPyStatus\n_PyConfig_Read(PyConfig *config, int compute_path_config)\n{\n    PyStatus status;\n\n    status = _Py_PreInitializeFromConfig(config, NULL);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    config_get_global_vars(config);\n\n    if (config->orig_argv.length == 0\n        && !(config->argv.length == 1\n             && wcscmp(config->argv.items[0], L\"\") == 0))\n    {\n        if (_PyWideStringList_Copy(&config->orig_argv, &config->argv) < 0) {\n            return _PyStatus_NO_MEMORY();\n        }\n    }\n\n    _PyPreCmdline precmdline = _PyPreCmdline_INIT;\n    status = core_read_precmdline(config, &precmdline);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\n    assert(config->isolated >= 0);\n    if (config->isolated) {\n        config->safe_path = 1;\n        config->use_environment = 0;\n        config->user_site_directory = 0;\n    }\n\n    status = config_read_cmdline(config);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\n    /* Handle early PySys_AddXOption() calls */\n    status = _PySys_ReadPreinitXOptions(config);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\n    status = config_read(config, compute_path_config);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\n    assert(config_check_consistency(config));\n\n    status = _PyStatus_OK();\n\ndone:\n    _PyPreCmdline_Clear(&precmdline);\n    return status;\n}\n\n\nPyStatus\nPyConfig_Read(PyConfig *config)\n{\n    return _PyConfig_Read(config, 0);\n}\n\n\nPyObject*\n_Py_GetConfigsAsDict(void)\n{\n    PyObject *result = NULL;\n    PyObject *dict = NULL;\n\n    result = PyDict_New();\n    if (result == NULL) {\n        goto error;\n    }\n\n    /* global result */\n    dict = _Py_GetGlobalVariablesAsDict();\n    if (dict == NULL) {\n        goto error;\n    }\n    if (PyDict_SetItemString(result, \"global_config\", dict) < 0) {\n        goto error;\n    }\n    Py_CLEAR(dict);\n\n    /* pre config */\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    const PyPreConfig *pre_config = &interp->runtime->preconfig;\n    dict = _PyPreConfig_AsDict(pre_config);\n    if (dict == NULL) {\n        goto error;\n    }\n    if (PyDict_SetItemString(result, \"pre_config\", dict) < 0) {\n        goto error;\n    }\n    Py_CLEAR(dict);\n\n    /* core config */\n    const PyConfig *config = _PyInterpreterState_GetConfig(interp);\n    dict = _PyConfig_AsDict(config);\n    if (dict == NULL) {\n        goto error;\n    }\n    if (PyDict_SetItemString(result, \"config\", dict) < 0) {\n        goto error;\n    }\n    Py_CLEAR(dict);\n\n    return result;\n\nerror:\n    Py_XDECREF(result);\n    Py_XDECREF(dict);\n    return NULL;\n}\n\n\nstatic void\ninit_dump_ascii_wstr(const wchar_t *str)\n{\n    if (str == NULL) {\n        PySys_WriteStderr(\"(not set)\");\n        return;\n    }\n\n    PySys_WriteStderr(\"'\");\n    for (; *str != L'\\0'; str++) {\n        unsigned int ch = (unsigned int)*str;\n        if (ch == L'\\'') {\n            PySys_WriteStderr(\"\\\\'\");\n        } else if (0x20 <= ch && ch < 0x7f) {\n            PySys_WriteStderr(\"%c\", ch);\n        }\n        else if (ch <= 0xff) {\n            PySys_WriteStderr(\"\\\\x%02x\", ch);\n        }\n#if SIZEOF_WCHAR_T > 2\n        else if (ch > 0xffff) {\n            PySys_WriteStderr(\"\\\\U%08x\", ch);\n        }\n#endif\n        else {\n            PySys_WriteStderr(\"\\\\u%04x\", ch);\n        }\n    }\n    PySys_WriteStderr(\"'\");\n}\n\n\n/* Dump the Python path configuration into sys.stderr */\nvoid\n_Py_DumpPathConfig(PyThreadState *tstate)\n{\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n\n    PySys_WriteStderr(\"Python path configuration:\\n\");\n\n#define DUMP_CONFIG(NAME, FIELD) \\\n        do { \\\n            PySys_WriteStderr(\"  \" NAME \" = \"); \\\n            init_dump_ascii_wstr(config->FIELD); \\\n            PySys_WriteStderr(\"\\n\"); \\\n        } while (0)\n\n    const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);\n    DUMP_CONFIG(\"PYTHONHOME\", home);\n    DUMP_CONFIG(\"PYTHONPATH\", pythonpath_env);\n    DUMP_CONFIG(\"program name\", program_name);\n    PySys_WriteStderr(\"  isolated = %i\\n\", config->isolated);\n    PySys_WriteStderr(\"  environment = %i\\n\", config->use_environment);\n    PySys_WriteStderr(\"  user site = %i\\n\", config->user_site_directory);\n    PySys_WriteStderr(\"  safe_path = %i\\n\", config->safe_path);\n    PySys_WriteStderr(\"  import site = %i\\n\", config->site_import);\n    PySys_WriteStderr(\"  is in build tree = %i\\n\", config->_is_python_build);\n    DUMP_CONFIG(\"stdlib dir\", stdlib_dir);\n#undef DUMP_CONFIG\n\n#define DUMP_SYS(NAME) \\\n        do { \\\n            obj = PySys_GetObject(#NAME); \\\n            PySys_FormatStderr(\"  sys.%s = \", #NAME); \\\n            if (obj != NULL) { \\\n                PySys_FormatStderr(\"%A\", obj); \\\n            } \\\n            else { \\\n                PySys_WriteStderr(\"(not set)\"); \\\n            } \\\n            PySys_FormatStderr(\"\\n\"); \\\n        } while (0)\n\n    PyObject *obj;\n    DUMP_SYS(_base_executable);\n    DUMP_SYS(base_prefix);\n    DUMP_SYS(base_exec_prefix);\n    DUMP_SYS(platlibdir);\n    DUMP_SYS(executable);\n    DUMP_SYS(prefix);\n    DUMP_SYS(exec_prefix);\n#undef DUMP_SYS\n\n    PyObject *sys_path = PySys_GetObject(\"path\");  /* borrowed reference */\n    if (sys_path != NULL && PyList_Check(sys_path)) {\n        PySys_WriteStderr(\"  sys.path = [\\n\");\n        Py_ssize_t len = PyList_GET_SIZE(sys_path);\n        for (Py_ssize_t i=0; i < len; i++) {\n            PyObject *path = PyList_GET_ITEM(sys_path, i);\n            PySys_FormatStderr(\"    %A,\\n\", path);\n        }\n        PySys_WriteStderr(\"  ]\\n\");\n    }\n\n    _PyErr_SetRaisedException(tstate, exc);\n}\n"
  },
  {
    "path": "InstruMenTation.c",
    "content": "#include \"Python.h\"\n#include \"pycore_call.h\"\n#include \"pycore_frame.h\"\n#include \"pycore_interp.h\"\n#include \"pycore_long.h\"\n#include \"pycore_namespace.h\"\n#include \"pycore_object.h\"\n#include \"pycore_opcode.h\"\n#include \"pycore_pyerrors.h\"\n#include \"pycore_pystate.h\"\n\n/* Uncomment this to dump debugging output when assertions fail */\n// #define INSTRUMENT_DEBUG 1\n\nPyObject _PyInstrumentation_DISABLE =\n{\n    .ob_refcnt = _Py_IMMORTAL_REFCNT,\n    .ob_type = &PyBaseObject_Type\n};\n\nPyObject _PyInstrumentation_MISSING =\n{\n    .ob_refcnt = _Py_IMMORTAL_REFCNT,\n    .ob_type = &PyBaseObject_Type\n};\n\nstatic const int8_t EVENT_FOR_OPCODE[256] = {\n    [RETURN_CONST] = PY_MONITORING_EVENT_PY_RETURN,\n    [INSTRUMENTED_RETURN_CONST] = PY_MONITORING_EVENT_PY_RETURN,\n    [RETURN_VALUE] = PY_MONITORING_EVENT_PY_RETURN,\n    [INSTRUMENTED_RETURN_VALUE] = PY_MONITORING_EVENT_PY_RETURN,\n    [CALL] = PY_MONITORING_EVENT_CALL,\n    [INSTRUMENTED_CALL] = PY_MONITORING_EVENT_CALL,\n    [CALL_FUNCTION_EX] = PY_MONITORING_EVENT_CALL,\n    [INSTRUMENTED_CALL_FUNCTION_EX] = PY_MONITORING_EVENT_CALL,\n    [LOAD_SUPER_ATTR] = PY_MONITORING_EVENT_CALL,\n    [INSTRUMENTED_LOAD_SUPER_ATTR] = PY_MONITORING_EVENT_CALL,\n    [RESUME] = -1,\n    [YIELD_VALUE] = PY_MONITORING_EVENT_PY_YIELD,\n    [INSTRUMENTED_YIELD_VALUE] = PY_MONITORING_EVENT_PY_YIELD,\n    [JUMP_FORWARD] = PY_MONITORING_EVENT_JUMP,\n    [JUMP_BACKWARD] = PY_MONITORING_EVENT_JUMP,\n    [POP_JUMP_IF_FALSE] = PY_MONITORING_EVENT_BRANCH,\n    [POP_JUMP_IF_TRUE] = PY_MONITORING_EVENT_BRANCH,\n    [POP_JUMP_IF_NONE] = PY_MONITORING_EVENT_BRANCH,\n    [POP_JUMP_IF_NOT_NONE] = PY_MONITORING_EVENT_BRANCH,\n    [INSTRUMENTED_JUMP_FORWARD] = PY_MONITORING_EVENT_JUMP,\n    [INSTRUMENTED_JUMP_BACKWARD] = PY_MONITORING_EVENT_JUMP,\n    [INSTRUMENTED_POP_JUMP_IF_FALSE] = PY_MONITORING_EVENT_BRANCH,\n    [INSTRUMENTED_POP_JUMP_IF_TRUE] = PY_MONITORING_EVENT_BRANCH,\n    [INSTRUMENTED_POP_JUMP_IF_NONE] = PY_MONITORING_EVENT_BRANCH,\n    [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = PY_MONITORING_EVENT_BRANCH,\n    [FOR_ITER] = PY_MONITORING_EVENT_BRANCH,\n    [INSTRUMENTED_FOR_ITER] = PY_MONITORING_EVENT_BRANCH,\n    [END_FOR] = PY_MONITORING_EVENT_STOP_ITERATION,\n    [INSTRUMENTED_END_FOR] = PY_MONITORING_EVENT_STOP_ITERATION,\n    [END_SEND] = PY_MONITORING_EVENT_STOP_ITERATION,\n    [INSTRUMENTED_END_SEND] = PY_MONITORING_EVENT_STOP_ITERATION,\n};\n\nstatic const uint8_t DE_INSTRUMENT[256] = {\n    [INSTRUMENTED_RESUME] = RESUME,\n    [INSTRUMENTED_RETURN_VALUE] = RETURN_VALUE,\n    [INSTRUMENTED_RETURN_CONST] = RETURN_CONST,\n    [INSTRUMENTED_CALL] = CALL,\n    [INSTRUMENTED_CALL_FUNCTION_EX] = CALL_FUNCTION_EX,\n    [INSTRUMENTED_YIELD_VALUE] = YIELD_VALUE,\n    [INSTRUMENTED_JUMP_FORWARD] = JUMP_FORWARD,\n    [INSTRUMENTED_JUMP_BACKWARD] = JUMP_BACKWARD,\n    [INSTRUMENTED_POP_JUMP_IF_FALSE] = POP_JUMP_IF_FALSE,\n    [INSTRUMENTED_POP_JUMP_IF_TRUE] = POP_JUMP_IF_TRUE,\n    [INSTRUMENTED_POP_JUMP_IF_NONE] = POP_JUMP_IF_NONE,\n    [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = POP_JUMP_IF_NOT_NONE,\n    [INSTRUMENTED_FOR_ITER] = FOR_ITER,\n    [INSTRUMENTED_END_FOR] = END_FOR,\n    [INSTRUMENTED_END_SEND] = END_SEND,\n    [INSTRUMENTED_LOAD_SUPER_ATTR] = LOAD_SUPER_ATTR,\n};\n\nstatic const uint8_t INSTRUMENTED_OPCODES[256] = {\n    [RETURN_CONST] = INSTRUMENTED_RETURN_CONST,\n    [INSTRUMENTED_RETURN_CONST] = INSTRUMENTED_RETURN_CONST,\n    [RETURN_VALUE] = INSTRUMENTED_RETURN_VALUE,\n    [INSTRUMENTED_RETURN_VALUE] = INSTRUMENTED_RETURN_VALUE,\n    [CALL] = INSTRUMENTED_CALL,\n    [INSTRUMENTED_CALL] = INSTRUMENTED_CALL,\n    [CALL_FUNCTION_EX] = INSTRUMENTED_CALL_FUNCTION_EX,\n    [INSTRUMENTED_CALL_FUNCTION_EX] = INSTRUMENTED_CALL_FUNCTION_EX,\n    [YIELD_VALUE] = INSTRUMENTED_YIELD_VALUE,\n    [INSTRUMENTED_YIELD_VALUE] = INSTRUMENTED_YIELD_VALUE,\n    [RESUME] = INSTRUMENTED_RESUME,\n    [INSTRUMENTED_RESUME] = INSTRUMENTED_RESUME,\n    [JUMP_FORWARD] = INSTRUMENTED_JUMP_FORWARD,\n    [INSTRUMENTED_JUMP_FORWARD] = INSTRUMENTED_JUMP_FORWARD,\n    [JUMP_BACKWARD] = INSTRUMENTED_JUMP_BACKWARD,\n    [INSTRUMENTED_JUMP_BACKWARD] = INSTRUMENTED_JUMP_BACKWARD,\n    [POP_JUMP_IF_FALSE] = INSTRUMENTED_POP_JUMP_IF_FALSE,\n    [INSTRUMENTED_POP_JUMP_IF_FALSE] = INSTRUMENTED_POP_JUMP_IF_FALSE,\n    [POP_JUMP_IF_TRUE] = INSTRUMENTED_POP_JUMP_IF_TRUE,\n    [INSTRUMENTED_POP_JUMP_IF_TRUE] = INSTRUMENTED_POP_JUMP_IF_TRUE,\n    [POP_JUMP_IF_NONE] = INSTRUMENTED_POP_JUMP_IF_NONE,\n    [INSTRUMENTED_POP_JUMP_IF_NONE] = INSTRUMENTED_POP_JUMP_IF_NONE,\n    [POP_JUMP_IF_NOT_NONE] = INSTRUMENTED_POP_JUMP_IF_NOT_NONE,\n    [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = INSTRUMENTED_POP_JUMP_IF_NOT_NONE,\n    [END_FOR] = INSTRUMENTED_END_FOR,\n    [INSTRUMENTED_END_FOR] = INSTRUMENTED_END_FOR,\n    [END_SEND] = INSTRUMENTED_END_SEND,\n    [INSTRUMENTED_END_SEND] = INSTRUMENTED_END_SEND,\n    [FOR_ITER] = INSTRUMENTED_FOR_ITER,\n    [INSTRUMENTED_FOR_ITER] = INSTRUMENTED_FOR_ITER,\n    [LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR,\n    [INSTRUMENTED_LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR,\n\n    [INSTRUMENTED_LINE] = INSTRUMENTED_LINE,\n    [INSTRUMENTED_INSTRUCTION] = INSTRUMENTED_INSTRUCTION,\n};\n\nstatic inline bool\nopcode_has_event(int opcode)\n{\n    return (\n        opcode < INSTRUMENTED_LINE &&\n        INSTRUMENTED_OPCODES[opcode] > 0\n    );\n}\n\nstatic inline bool\nis_instrumented(int opcode)\n{\n    assert(opcode != 0);\n    assert(opcode != RESERVED);\n    return opcode >= MIN_INSTRUMENTED_OPCODE;\n}\n\n#ifndef NDEBUG\nstatic inline bool\nmonitors_equals(_Py_Monitors a, _Py_Monitors b)\n{\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        if (a.tools[i] != b.tools[i]) {\n            return false;\n        }\n    }\n    return true;\n}\n#endif\n\nstatic inline _Py_Monitors\nmonitors_sub(_Py_Monitors a, _Py_Monitors b)\n{\n    _Py_Monitors res;\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        res.tools[i] = a.tools[i] & ~b.tools[i];\n    }\n    return res;\n}\n\n#ifndef NDEBUG\nstatic inline _Py_Monitors\nmonitors_and(_Py_Monitors a, _Py_Monitors b)\n{\n    _Py_Monitors res;\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        res.tools[i] = a.tools[i] & b.tools[i];\n    }\n    return res;\n}\n#endif\n\nstatic inline _Py_Monitors\nmonitors_or(_Py_Monitors a, _Py_Monitors b)\n{\n    _Py_Monitors res;\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        res.tools[i] = a.tools[i] | b.tools[i];\n    }\n    return res;\n}\n\nstatic inline bool\nmonitors_are_empty(_Py_Monitors m)\n{\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        if (m.tools[i]) {\n            return false;\n        }\n    }\n    return true;\n}\n\nstatic inline bool\nmultiple_tools(_Py_Monitors *m)\n{\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        if (_Py_popcount32(m->tools[i]) > 1) {\n            return true;\n        }\n    }\n    return false;\n}\n\nstatic inline _PyMonitoringEventSet\nget_events(_Py_Monitors *m, int tool_id)\n{\n    _PyMonitoringEventSet result = 0;\n    for (int e = 0; e < PY_MONITORING_UNGROUPED_EVENTS; e++) {\n        if ((m->tools[e] >> tool_id) & 1) {\n            result |= (1 << e);\n        }\n    }\n    return result;\n}\n\n/* Line delta.\n * 8 bit value.\n * if line_delta == -128:\n *     line = None # represented as -1\n * elif line_delta == -127:\n *     line = PyCode_Addr2Line(code, offset * sizeof(_Py_CODEUNIT));\n * else:\n *     line = first_line  + (offset >> OFFSET_SHIFT) + line_delta;\n */\n\n#define NO_LINE -128\n#define COMPUTED_LINE -127\n\n#define OFFSET_SHIFT 4\n\nstatic int8_t\ncompute_line_delta(PyCodeObject *code, int offset, int line)\n{\n    if (line < 0) {\n        return NO_LINE;\n    }\n    int delta = line - code->co_firstlineno - (offset >> OFFSET_SHIFT);\n    if (delta <= INT8_MAX && delta > COMPUTED_LINE) {\n        return delta;\n    }\n    return COMPUTED_LINE;\n}\n\nstatic int\ncompute_line(PyCodeObject *code, int offset, int8_t line_delta)\n{\n    if (line_delta > COMPUTED_LINE) {\n        return code->co_firstlineno + (offset >> OFFSET_SHIFT) + line_delta;\n    }\n    if (line_delta == NO_LINE) {\n\n        return -1;\n    }\n    assert(line_delta == COMPUTED_LINE);\n    /* Look it up */\n    return PyCode_Addr2Line(code, offset * sizeof(_Py_CODEUNIT));\n}\n\nint\n_PyInstruction_GetLength(PyCodeObject *code, int offset)\n{\n    int opcode = _PyCode_CODE(code)[offset].op.code;\n    assert(opcode != 0);\n    assert(opcode != RESERVED);\n    if (opcode == INSTRUMENTED_LINE) {\n        opcode = code->_co_monitoring->lines[offset].original_opcode;\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        opcode = code->_co_monitoring->per_instruction_opcodes[offset];\n    }\n    int deinstrumented = DE_INSTRUMENT[opcode];\n    if (deinstrumented) {\n        opcode = deinstrumented;\n    }\n    else {\n        opcode = _PyOpcode_Deopt[opcode];\n    }\n    assert(opcode != 0);\n    assert(!is_instrumented(opcode));\n    assert(opcode == _PyOpcode_Deopt[opcode]);\n    return 1 + _PyOpcode_Caches[opcode];\n}\n\n#ifdef INSTRUMENT_DEBUG\n\nstatic void\ndump_instrumentation_data_tools(PyCodeObject *code, uint8_t *tools, int i, FILE*out)\n{\n    if (tools == NULL) {\n        fprintf(out, \"tools = NULL\");\n    }\n    else {\n        fprintf(out, \"tools = %d\", tools[i]);\n    }\n}\n\nstatic void\ndump_instrumentation_data_lines(PyCodeObject *code, _PyCoLineInstrumentationData *lines, int i, FILE*out)\n{\n    if (lines == NULL) {\n        fprintf(out, \", lines = NULL\");\n    }\n    else if (lines[i].original_opcode == 0) {\n        fprintf(out, \", lines = {original_opcode = No LINE (0), line_delta = %d)\", lines[i].line_delta);\n    }\n    else {\n        fprintf(out, \", lines = {original_opcode = %s, line_delta = %d)\", _PyOpcode_OpName[lines[i].original_opcode], lines[i].line_delta);\n    }\n}\n\nstatic void\ndump_instrumentation_data_line_tools(PyCodeObject *code, uint8_t *line_tools, int i, FILE*out)\n{\n    if (line_tools == NULL) {\n        fprintf(out, \", line_tools = NULL\");\n    }\n    else {\n        fprintf(out, \", line_tools = %d\", line_tools[i]);\n    }\n}\n\nstatic void\ndump_instrumentation_data_per_instruction(PyCodeObject *code, _PyCoMonitoringData *data, int i, FILE*out)\n{\n    if (data->per_instruction_opcodes == NULL) {\n        fprintf(out, \", per-inst opcode = NULL\");\n    }\n    else {\n        fprintf(out, \", per-inst opcode = %s\", _PyOpcode_OpName[data->per_instruction_opcodes[i]]);\n    }\n    if (data->per_instruction_tools == NULL) {\n        fprintf(out, \", per-inst tools = NULL\");\n    }\n    else {\n        fprintf(out, \", per-inst tools = %d\", data->per_instruction_tools[i]);\n    }\n}\n\nstatic void\ndump_monitors(const char *prefix, _Py_Monitors monitors, FILE*out)\n{\n    fprintf(out, \"%s monitors:\\n\", prefix);\n    for (int event = 0; event < PY_MONITORING_UNGROUPED_EVENTS; event++) {\n        fprintf(out, \"    Event %d: Tools %x\\n\", event, monitors.tools[event]);\n    }\n}\n\n/* Like _Py_GetBaseOpcode but without asserts.\n * Does its best to give the right answer, but won't abort\n * if something is wrong */\nstatic int\nget_base_opcode_best_attempt(PyCodeObject *code, int offset)\n{\n    int opcode = _Py_OPCODE(_PyCode_CODE(code)[offset]);\n    if (INSTRUMENTED_OPCODES[opcode] != opcode) {\n        /* Not instrumented */\n        return _PyOpcode_Deopt[opcode] == 0 ? opcode : _PyOpcode_Deopt[opcode];\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        if (code->_co_monitoring->per_instruction_opcodes[offset] == 0) {\n            return opcode;\n        }\n        opcode = code->_co_monitoring->per_instruction_opcodes[offset];\n    }\n    if (opcode == INSTRUMENTED_LINE) {\n        if (code->_co_monitoring->lines[offset].original_opcode == 0) {\n            return opcode;\n        }\n        opcode = code->_co_monitoring->lines[offset].original_opcode;\n    }\n    int deinstrumented = DE_INSTRUMENT[opcode];\n    if (deinstrumented) {\n        return deinstrumented;\n    }\n    if (_PyOpcode_Deopt[opcode] == 0) {\n        return opcode;\n    }\n    return _PyOpcode_Deopt[opcode];\n}\n\n/* No error checking -- Don't use this for anything but experimental debugging */\nstatic void\ndump_instrumentation_data(PyCodeObject *code, int star, FILE*out)\n{\n    _PyCoMonitoringData *data = code->_co_monitoring;\n    fprintf(out, \"\\n\");\n    PyObject_Print(code->co_name, out, Py_PRINT_RAW);\n    fprintf(out, \"\\n\");\n    if (data == NULL) {\n        fprintf(out, \"NULL\\n\");\n        return;\n    }\n    dump_monitors(\"Global\", PyInterpreterState_Get()->monitors, out);\n    dump_monitors(\"Code\", data->local_monitors, out);\n    dump_monitors(\"Active\", data->active_monitors, out);\n    int code_len = (int)Py_SIZE(code);\n    bool starred = false;\n    for (int i = 0; i < code_len; i += _PyInstruction_GetLength(code, i)) {\n        _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n        int opcode = instr->op.code;\n        if (i == star) {\n            fprintf(out, \"**  \");\n            starred = true;\n        }\n        fprintf(out, \"Offset: %d, line: %d %s: \", i, PyCode_Addr2Line(code, i*2), _PyOpcode_OpName[opcode]);\n        dump_instrumentation_data_tools(code, data->tools, i, out);\n        dump_instrumentation_data_lines(code, data->lines, i, out);\n        dump_instrumentation_data_line_tools(code, data->line_tools, i, out);\n        dump_instrumentation_data_per_instruction(code, data, i, out);\n        fprintf(out, \"\\n\");\n        ;\n    }\n    if (!starred && star >= 0) {\n        fprintf(out, \"Error offset not at valid instruction offset: %d\\n\", star);\n        fprintf(out, \"    \");\n        dump_instrumentation_data_tools(code, data->tools, star, out);\n        dump_instrumentation_data_lines(code, data->lines, star, out);\n        dump_instrumentation_data_line_tools(code, data->line_tools, star, out);\n        dump_instrumentation_data_per_instruction(code, data, star, out);\n        fprintf(out, \"\\n\");\n    }\n}\n\n#define CHECK(test) do { \\\n    if (!(test)) { \\\n        dump_instrumentation_data(code, i, stderr); \\\n    } \\\n    assert(test); \\\n} while (0)\n\nstatic bool\nvalid_opcode(int opcode)\n{\n    if (opcode > 0 &&\n        opcode != RESERVED &&\n        opcode < 255 &&\n        _PyOpcode_OpName[opcode] &&\n        _PyOpcode_OpName[opcode][0] != '<')\n    {\n       return true;\n    }\n    return false;\n}\n\nstatic void\nsanity_check_instrumentation(PyCodeObject *code)\n{\n    _PyCoMonitoringData *data = code->_co_monitoring;\n    if (data == NULL) {\n        return;\n    }\n    _Py_Monitors active_monitors = PyInterpreterState_Get()->monitors;\n    if (code->_co_monitoring) {\n        _Py_Monitors local_monitors = code->_co_monitoring->local_monitors;\n        active_monitors = monitors_or(active_monitors, local_monitors);\n    }\n    assert(monitors_equals(\n        code->_co_monitoring->active_monitors,\n        active_monitors)\n    );\n    int code_len = (int)Py_SIZE(code);\n    for (int i = 0; i < code_len;) {\n        int opcode = _PyCode_CODE(code)[i].op.code;\n        int base_opcode = _Py_GetBaseOpcode(code, i);\n        CHECK(valid_opcode(opcode));\n        CHECK(valid_opcode(base_opcode));\n        if (opcode == INSTRUMENTED_INSTRUCTION) {\n            opcode = data->per_instruction_opcodes[i];\n            if (!is_instrumented(opcode)) {\n                CHECK(_PyOpcode_Deopt[opcode] == opcode);\n            }\n            if (data->per_instruction_tools) {\n                uint8_t tools = active_monitors.tools[PY_MONITORING_EVENT_INSTRUCTION];\n                CHECK((tools & data->per_instruction_tools[i]) == data->per_instruction_tools[i]);\n            }\n        }\n        if (opcode == INSTRUMENTED_LINE) {\n            CHECK(data->lines);\n            CHECK(valid_opcode(data->lines[i].original_opcode));\n            opcode = data->lines[i].original_opcode;\n            CHECK(opcode != END_FOR);\n            CHECK(opcode != RESUME);\n            CHECK(opcode != INSTRUMENTED_RESUME);\n            if (!is_instrumented(opcode)) {\n                CHECK(_PyOpcode_Deopt[opcode] == opcode);\n            }\n            CHECK(opcode != INSTRUMENTED_LINE);\n        }\n        else if (data->lines && !is_instrumented(opcode)) {\n            CHECK(data->lines[i].original_opcode == 0 ||\n                  data->lines[i].original_opcode == base_opcode ||\n                  DE_INSTRUMENT[data->lines[i].original_opcode] == base_opcode);\n        }\n        if (is_instrumented(opcode)) {\n            CHECK(DE_INSTRUMENT[opcode] == base_opcode);\n            int event = EVENT_FOR_OPCODE[DE_INSTRUMENT[opcode]];\n            if (event < 0) {\n                /* RESUME fixup */\n                event = _PyCode_CODE(code)[i].op.arg;\n            }\n            CHECK(active_monitors.tools[event] != 0);\n        }\n        if (data->lines && base_opcode != END_FOR) {\n            int line1 = compute_line(code, i, data->lines[i].line_delta);\n            int line2 = PyCode_Addr2Line(code, i*sizeof(_Py_CODEUNIT));\n            CHECK(line1 == line2);\n        }\n        CHECK(valid_opcode(opcode));\n        if (data->tools) {\n            uint8_t local_tools = data->tools[i];\n            if (opcode_has_event(base_opcode)) {\n                int event = EVENT_FOR_OPCODE[base_opcode];\n                if (event == -1) {\n                    /* RESUME fixup */\n                    event = _PyCode_CODE(code)[i].op.arg;\n                }\n                CHECK((active_monitors.tools[event] & local_tools) == local_tools);\n            }\n            else {\n                CHECK(local_tools == 0xff);\n            }\n        }\n        i += _PyInstruction_GetLength(code, i);\n        assert(i <= code_len);\n    }\n}\n#else\n\n#define CHECK(test) assert(test)\n\n#endif\n\n/* Get the underlying opcode, stripping instrumentation */\nint _Py_GetBaseOpcode(PyCodeObject *code, int i)\n{\n    int opcode = _PyCode_CODE(code)[i].op.code;\n    if (opcode == INSTRUMENTED_LINE) {\n        opcode = code->_co_monitoring->lines[i].original_opcode;\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        opcode = code->_co_monitoring->per_instruction_opcodes[i];\n    }\n    CHECK(opcode != INSTRUMENTED_INSTRUCTION);\n    CHECK(opcode != INSTRUMENTED_LINE);\n    int deinstrumented = DE_INSTRUMENT[opcode];\n    if (deinstrumented) {\n        return deinstrumented;\n    }\n    return _PyOpcode_Deopt[opcode];\n}\n\nstatic void\nde_instrument(PyCodeObject *code, int i, int event)\n{\n    assert(event != PY_MONITORING_EVENT_INSTRUCTION);\n    assert(event != PY_MONITORING_EVENT_LINE);\n\n    _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n    uint8_t *opcode_ptr = &instr->op.code;\n    int opcode = *opcode_ptr;\n    if (opcode == INSTRUMENTED_LINE) {\n        opcode_ptr = &code->_co_monitoring->lines[i].original_opcode;\n        opcode = *opcode_ptr;\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        opcode_ptr = &code->_co_monitoring->per_instruction_opcodes[i];\n        opcode = *opcode_ptr;\n    }\n    int deinstrumented = DE_INSTRUMENT[opcode];\n    if (deinstrumented == 0) {\n        return;\n    }\n    CHECK(_PyOpcode_Deopt[deinstrumented] == deinstrumented);\n    *opcode_ptr = deinstrumented;\n    if (_PyOpcode_Caches[deinstrumented]) {\n        instr[1].cache = adaptive_counter_warmup();\n    }\n}\n\nstatic void\nde_instrument_line(PyCodeObject *code, int i)\n{\n    _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n    uint8_t *opcode_ptr = &instr->op.code;\n    int opcode =*opcode_ptr;\n    if (opcode != INSTRUMENTED_LINE) {\n        return;\n    }\n    _PyCoLineInstrumentationData *lines = &code->_co_monitoring->lines[i];\n    int original_opcode = lines->original_opcode;\n    CHECK(original_opcode != 0);\n    CHECK(original_opcode == _PyOpcode_Deopt[original_opcode]);\n    *opcode_ptr = instr->op.code = original_opcode;\n    if (_PyOpcode_Caches[original_opcode]) {\n        instr[1].cache = adaptive_counter_warmup();\n    }\n    assert(*opcode_ptr != INSTRUMENTED_LINE);\n    assert(instr->op.code != INSTRUMENTED_LINE);\n}\n\n\nstatic void\nde_instrument_per_instruction(PyCodeObject *code, int i)\n{\n    _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n    uint8_t *opcode_ptr = &instr->op.code;\n    int opcode =*opcode_ptr;\n    if (opcode == INSTRUMENTED_LINE) {\n        opcode_ptr = &code->_co_monitoring->lines[i].original_opcode;\n        opcode = *opcode_ptr;\n    }\n    if (opcode != INSTRUMENTED_INSTRUCTION) {\n        return;\n    }\n    int original_opcode = code->_co_monitoring->per_instruction_opcodes[i];\n    CHECK(original_opcode != 0);\n    CHECK(original_opcode == _PyOpcode_Deopt[original_opcode]);\n    instr->op.code = original_opcode;\n    if (_PyOpcode_Caches[original_opcode]) {\n        instr[1].cache = adaptive_counter_warmup();\n    }\n    assert(instr->op.code != INSTRUMENTED_INSTRUCTION);\n    /* Keep things clean for sanity check */\n    code->_co_monitoring->per_instruction_opcodes[i] = 0;\n}\n\n\nstatic void\ninstrument(PyCodeObject *code, int i)\n{\n    _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n    uint8_t *opcode_ptr = &instr->op.code;\n    int opcode =*opcode_ptr;\n    if (opcode == INSTRUMENTED_LINE) {\n        _PyCoLineInstrumentationData *lines = &code->_co_monitoring->lines[i];\n        opcode_ptr = &lines->original_opcode;\n        opcode = *opcode_ptr;\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        opcode_ptr = &code->_co_monitoring->per_instruction_opcodes[i];\n        opcode = *opcode_ptr;\n        CHECK(!is_instrumented(opcode));\n        CHECK(opcode == _PyOpcode_Deopt[opcode]);\n    }\n    CHECK(opcode != 0);\n    if (!is_instrumented(opcode)) {\n        int deopt = _PyOpcode_Deopt[opcode];\n        int instrumented = INSTRUMENTED_OPCODES[deopt];\n        assert(instrumented);\n        *opcode_ptr = instrumented;\n        if (_PyOpcode_Caches[deopt]) {\n            instr[1].cache = adaptive_counter_warmup();\n        }\n    }\n}\n\nstatic void\ninstrument_line(PyCodeObject *code, int i)\n{\n    uint8_t *opcode_ptr = &_PyCode_CODE(code)[i].op.code;\n    int opcode =*opcode_ptr;\n    if (opcode == INSTRUMENTED_LINE) {\n        return;\n    }\n    _PyCoLineInstrumentationData *lines = &code->_co_monitoring->lines[i];\n    lines->original_opcode = _PyOpcode_Deopt[opcode];\n    CHECK(lines->original_opcode > 0);\n    *opcode_ptr = INSTRUMENTED_LINE;\n}\n\nstatic void\ninstrument_per_instruction(PyCodeObject *code, int i)\n{\n    _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n    uint8_t *opcode_ptr = &instr->op.code;\n    int opcode =*opcode_ptr;\n    if (opcode == INSTRUMENTED_LINE) {\n        _PyCoLineInstrumentationData *lines = &code->_co_monitoring->lines[i];\n        opcode_ptr = &lines->original_opcode;\n        opcode = *opcode_ptr;\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        return;\n    }\n    CHECK(opcode != 0);\n    if (is_instrumented(opcode)) {\n        code->_co_monitoring->per_instruction_opcodes[i] = opcode;\n    }\n    else {\n        assert(opcode != 0);\n        assert(_PyOpcode_Deopt[opcode] != 0);\n        assert(_PyOpcode_Deopt[opcode] != RESUME);\n        code->_co_monitoring->per_instruction_opcodes[i] = _PyOpcode_Deopt[opcode];\n    }\n    assert(code->_co_monitoring->per_instruction_opcodes[i] > 0);\n    *opcode_ptr = INSTRUMENTED_INSTRUCTION;\n}\n\n#ifndef NDEBUG\nstatic bool\ninstruction_has_event(PyCodeObject *code, int offset)\n{\n    _Py_CODEUNIT instr = _PyCode_CODE(code)[offset];\n    int opcode = instr.op.code;\n    if (opcode == INSTRUMENTED_LINE) {\n        opcode = code->_co_monitoring->lines[offset].original_opcode;\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        opcode = code->_co_monitoring->per_instruction_opcodes[offset];\n    }\n    return opcode_has_event(opcode);\n}\n#endif\n\nstatic void\nremove_tools(PyCodeObject * code, int offset, int event, int tools)\n{\n    assert(event != PY_MONITORING_EVENT_LINE);\n    assert(event != PY_MONITORING_EVENT_INSTRUCTION);\n    assert(event < PY_MONITORING_INSTRUMENTED_EVENTS);\n    assert(instruction_has_event(code, offset));\n    _PyCoMonitoringData *monitoring = code->_co_monitoring;\n    if (monitoring && monitoring->tools) {\n        monitoring->tools[offset] &= ~tools;\n        if (monitoring->tools[offset] == 0) {\n            de_instrument(code, offset, event);\n        }\n    }\n    else {\n        /* Single tool */\n        uint8_t single_tool = code->_co_monitoring->active_monitors.tools[event];\n        assert(_Py_popcount32(single_tool) <= 1);\n        if (((single_tool & tools) == single_tool)) {\n            de_instrument(code, offset, event);\n        }\n    }\n}\n\n#ifndef NDEBUG\nstatic bool\ntools_is_subset_for_event(PyCodeObject * code, int event, int tools)\n{\n    int global_tools = PyInterpreterState_Get()->monitors.tools[event];\n    int local_tools = code->_co_monitoring->local_monitors.tools[event];\n    return tools == ((global_tools | local_tools) & tools);\n}\n#endif\n\nstatic void\nremove_line_tools(PyCodeObject * code, int offset, int tools)\n{\n    assert(code->_co_monitoring);\n    if (code->_co_monitoring->line_tools)\n    {\n        uint8_t *toolsptr = &code->_co_monitoring->line_tools[offset];\n        *toolsptr &= ~tools;\n        if (*toolsptr == 0 ) {\n            de_instrument_line(code, offset);\n        }\n    }\n    else {\n        /* Single tool */\n        uint8_t single_tool = code->_co_monitoring->active_monitors.tools[PY_MONITORING_EVENT_LINE];\n        assert(_Py_popcount32(single_tool) <= 1);\n        if (((single_tool & tools) == single_tool)) {\n            de_instrument_line(code, offset);\n        }\n    }\n}\n\nstatic void\nadd_tools(PyCodeObject * code, int offset, int event, int tools)\n{\n    assert(event != PY_MONITORING_EVENT_LINE);\n    assert(event != PY_MONITORING_EVENT_INSTRUCTION);\n    assert(event < PY_MONITORING_INSTRUMENTED_EVENTS);\n    assert(code->_co_monitoring);\n    if (code->_co_monitoring &&\n        code->_co_monitoring->tools\n    ) {\n        code->_co_monitoring->tools[offset] |= tools;\n    }\n    else {\n        /* Single tool */\n        assert(_Py_popcount32(tools) == 1);\n        assert(tools_is_subset_for_event(code, event, tools));\n    }\n    instrument(code, offset);\n}\n\nstatic void\nadd_line_tools(PyCodeObject * code, int offset, int tools)\n{\n    assert(tools_is_subset_for_event(code, PY_MONITORING_EVENT_LINE, tools));\n    assert(code->_co_monitoring);\n    if (code->_co_monitoring->line_tools) {\n        code->_co_monitoring->line_tools[offset] |= tools;\n    }\n    else {\n        /* Single tool */\n        assert(_Py_popcount32(tools) == 1);\n    }\n    instrument_line(code, offset);\n}\n\n\nstatic void\nadd_per_instruction_tools(PyCodeObject * code, int offset, int tools)\n{\n    assert(tools_is_subset_for_event(code, PY_MONITORING_EVENT_INSTRUCTION, tools));\n    assert(code->_co_monitoring);\n    if (code->_co_monitoring->per_instruction_tools) {\n        code->_co_monitoring->per_instruction_tools[offset] |= tools;\n    }\n    else {\n        /* Single tool */\n        assert(_Py_popcount32(tools) == 1);\n    }\n    instrument_per_instruction(code, offset);\n}\n\n\nstatic void\nremove_per_instruction_tools(PyCodeObject * code, int offset, int tools)\n{\n    assert(code->_co_monitoring);\n    if (code->_co_monitoring->per_instruction_tools) {\n        uint8_t *toolsptr = &code->_co_monitoring->per_instruction_tools[offset];\n        *toolsptr &= ~tools;\n        if (*toolsptr == 0) {\n            de_instrument_per_instruction(code, offset);\n        }\n    }\n    else {\n        /* Single tool */\n        uint8_t single_tool = code->_co_monitoring->active_monitors.tools[PY_MONITORING_EVENT_INSTRUCTION];\n        assert(_Py_popcount32(single_tool) <= 1);\n        if (((single_tool & tools) == single_tool)) {\n            de_instrument_per_instruction(code, offset);\n        }\n    }\n}\n\n\n/* Return 1 if DISABLE returned, -1 if error, 0 otherwise */\nstatic int\ncall_one_instrument(\n    PyInterpreterState *interp, PyThreadState *tstate, PyObject **args,\n    Py_ssize_t nargsf, int8_t tool, int event)\n{\n    assert(0 <= tool && tool < 8);\n    assert(tstate->tracing == 0);\n    PyObject *instrument = interp->monitoring_callables[tool][event];\n    if (instrument == NULL) {\n        return 0;\n    }\n    int old_what = tstate->what_event;\n    tstate->what_event = event;\n    tstate->tracing++;\n    PyObject *res = _PyObject_VectorcallTstate(tstate, instrument, args, nargsf, NULL);\n    tstate->tracing--;\n    tstate->what_event = old_what;\n    if (res == NULL) {\n        return -1;\n    }\n    Py_DECREF(res);\n    return (res == &_PyInstrumentation_DISABLE);\n}\n\nstatic const int8_t MOST_SIGNIFICANT_BITS[16] = {\n    -1, 0, 1, 1,\n    2, 2, 2, 2,\n    3, 3, 3, 3,\n    3, 3, 3, 3,\n};\n\n/* We could use _Py_bit_length here, but that is designed for larger (32/64)\n * bit ints, and can perform relatively poorly on platforms without the\n * necessary intrinsics. */\nstatic inline int most_significant_bit(uint8_t bits) {\n    assert(bits != 0);\n    if (bits > 15) {\n        return MOST_SIGNIFICANT_BITS[bits>>4]+4;\n    }\n    return MOST_SIGNIFICANT_BITS[bits];\n}\n\nstatic bool\nis_version_up_to_date(PyCodeObject *code, PyInterpreterState *interp)\n{\n    return interp->monitoring_version == code->_co_instrumentation_version;\n}\n\n#ifndef NDEBUG\nstatic bool\ninstrumentation_cross_checks(PyInterpreterState *interp, PyCodeObject *code)\n{\n    _Py_Monitors expected = monitors_or(\n        interp->monitors,\n        code->_co_monitoring->local_monitors);\n    return monitors_equals(code->_co_monitoring->active_monitors, expected);\n}\n#endif\n\nstatic inline uint8_t\nget_tools_for_instruction(PyCodeObject * code, int i, int event)\n{\n    uint8_t tools;\n    assert(event != PY_MONITORING_EVENT_LINE);\n    assert(event != PY_MONITORING_EVENT_INSTRUCTION);\n    assert(instrumentation_cross_checks(PyThreadState_GET()->interp, code));\n    _PyCoMonitoringData *monitoring = code->_co_monitoring;\n    if (event >= PY_MONITORING_UNGROUPED_EVENTS) {\n        assert(event == PY_MONITORING_EVENT_C_RAISE ||\n                event == PY_MONITORING_EVENT_C_RETURN);\n        event = PY_MONITORING_EVENT_CALL;\n    }\n    if (event < PY_MONITORING_INSTRUMENTED_EVENTS && monitoring->tools) {\n        tools = monitoring->tools[i];\n    }\n    else {\n        tools = code->_co_monitoring->active_monitors.tools[event];\n    }\n    CHECK(tools_is_subset_for_event(code, event, tools));\n    CHECK((tools & code->_co_monitoring->active_monitors.tools[event]) == tools);\n    return tools;\n}\n\nstatic int\ncall_instrumentation_vector(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, Py_ssize_t nargs, PyObject *args[])\n{\n    if (tstate->tracing) {\n        return 0;\n    }\n    assert(!_PyErr_Occurred(tstate));\n    assert(args[0] == NULL);\n    PyCodeObject *code = frame->f_code;\n    assert(code->_co_instrumentation_version == tstate->interp->monitoring_version);\n    assert(is_version_up_to_date(code, tstate->interp));\n    assert(instrumentation_cross_checks(tstate->interp, code));\n    assert(args[1] == NULL);\n    args[1] = (PyObject *)code;\n    int offset = (int)(instr - _PyCode_CODE(code));\n    /* Offset visible to user should be the offset in bytes, as that is the\n     * convention for APIs involving code offsets. */\n    int bytes_offset = offset * (int)sizeof(_Py_CODEUNIT);\n    PyObject *offset_obj = PyLong_FromSsize_t(bytes_offset);\n    if (offset_obj == NULL) {\n        return -1;\n    }\n    assert(args[2] == NULL);\n    args[2] = offset_obj;\n    uint8_t tools = get_tools_for_instruction(code, offset, event);\n    Py_ssize_t nargsf = nargs | PY_VECTORCALL_ARGUMENTS_OFFSET;\n    PyObject **callargs = &args[1];\n    int err = 0;\n    PyInterpreterState *interp = tstate->interp;\n    while (tools) {\n        int tool = most_significant_bit(tools);\n        assert(tool >= 0 && tool < 8);\n        assert(tools & (1 << tool));\n        tools ^= (1 << tool);\n        int res = call_one_instrument(interp, tstate, callargs, nargsf, tool, event);\n        if (res == 0) {\n            /* Nothing to do */\n        }\n        else if (res < 0) {\n            /* error */\n            err = -1;\n            break;\n        }\n        else {\n            /* DISABLE */\n            remove_tools(code, offset, event, 1 << tool);\n        }\n    }\n    Py_DECREF(offset_obj);\n    return err;\n}\n\nint\n_Py_call_instrumentation(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr)\n{\n    PyObject *args[3] = { NULL, NULL, NULL };\n    return call_instrumentation_vector(tstate, event, frame, instr, 2, args);\n}\n\nint\n_Py_call_instrumentation_arg(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg)\n{\n    PyObject *args[4] = { NULL, NULL, NULL, arg };\n    return call_instrumentation_vector(tstate, event, frame, instr, 3, args);\n}\n\nint\n_Py_call_instrumentation_2args(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1)\n{\n    PyObject *args[5] = { NULL, NULL, NULL, arg0, arg1 };\n    return call_instrumentation_vector(tstate, event, frame, instr, 4, args);\n}\n\n_Py_CODEUNIT *\n_Py_call_instrumentation_jump(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *target)\n{\n    assert(event == PY_MONITORING_EVENT_JUMP ||\n           event == PY_MONITORING_EVENT_BRANCH);\n    assert(frame->prev_instr == instr);\n    /* Event should occur after the jump */\n    frame->prev_instr = target;\n    PyCodeObject *code = frame->f_code;\n    int to = (int)(target - _PyCode_CODE(code));\n    PyObject *to_obj = PyLong_FromLong(to * (int)sizeof(_Py_CODEUNIT));\n    if (to_obj == NULL) {\n        return NULL;\n    }\n    PyObject *args[4] = { NULL, NULL, NULL, to_obj };\n    int err = call_instrumentation_vector(tstate, event, frame, instr, 3, args);\n    Py_DECREF(to_obj);\n    if (err) {\n        return NULL;\n    }\n    if (frame->prev_instr != target) {\n        /* The callback has caused a jump (by setting the line number) */\n        return frame->prev_instr;\n    }\n    /* Reset prev_instr for INSTRUMENTED_LINE */\n    frame->prev_instr = instr;\n    return target;\n}\n\nstatic void\ncall_instrumentation_vector_protected(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, Py_ssize_t nargs, PyObject *args[])\n{\n    assert(_PyErr_Occurred(tstate));\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    int err = call_instrumentation_vector(tstate, event, frame, instr, nargs, args);\n    if (err) {\n        Py_XDECREF(exc);\n    }\n    else {\n        _PyErr_SetRaisedException(tstate, exc);\n    }\n    assert(_PyErr_Occurred(tstate));\n}\n\nvoid\n_Py_call_instrumentation_exc0(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr)\n{\n    assert(_PyErr_Occurred(tstate));\n    PyObject *args[3] = { NULL, NULL, NULL };\n    call_instrumentation_vector_protected(tstate, event, frame, instr, 2, args);\n}\n\nvoid\n_Py_call_instrumentation_exc2(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1)\n{\n    assert(_PyErr_Occurred(tstate));\n    PyObject *args[5] = { NULL, NULL, NULL, arg0, arg1 };\n    call_instrumentation_vector_protected(tstate, event, frame, instr, 4, args);\n}\n\n\nint\n_Py_Instrumentation_GetLine(PyCodeObject *code, int index)\n{\n    _PyCoMonitoringData *monitoring = code->_co_monitoring;\n    assert(monitoring != NULL);\n    assert(monitoring->lines != NULL);\n    assert(index >= code->_co_firsttraceable);\n    assert(index < Py_SIZE(code));\n    _PyCoLineInstrumentationData *line_data = &monitoring->lines[index];\n    int8_t line_delta = line_data->line_delta;\n    int line = compute_line(code, index, line_delta);\n    return line;\n}\n\nint\n_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)\n{\n    frame->prev_instr = instr;\n    PyCodeObject *code = frame->f_code;\n    assert(is_version_up_to_date(code, tstate->interp));\n    assert(instrumentation_cross_checks(tstate->interp, code));\n    int i = (int)(instr - _PyCode_CODE(code));\n\n    _PyCoMonitoringData *monitoring = code->_co_monitoring;\n    _PyCoLineInstrumentationData *line_data = &monitoring->lines[i];\n    uint8_t original_opcode = line_data->original_opcode;\n    if (tstate->tracing) {\n        goto done;\n    }\n    PyInterpreterState *interp = tstate->interp;\n    int8_t line_delta = line_data->line_delta;\n    int line = compute_line(code, i, line_delta);\n    assert(line >= 0);\n    int prev_index = (int)(prev - _PyCode_CODE(code));\n    int prev_line = _Py_Instrumentation_GetLine(code, prev_index);\n    if (prev_line == line) {\n        int prev_opcode = _PyCode_CODE(code)[prev_index].op.code;\n        /* RESUME and INSTRUMENTED_RESUME are needed for the operation of\n         * instrumentation, so must never be hidden by an INSTRUMENTED_LINE.\n         */\n        if (prev_opcode != RESUME && prev_opcode != INSTRUMENTED_RESUME) {\n            goto done;\n        }\n    }\n    uint8_t tools = code->_co_monitoring->line_tools != NULL ?\n        code->_co_monitoring->line_tools[i] :\n        (interp->monitors.tools[PY_MONITORING_EVENT_LINE] |\n         code->_co_monitoring->local_monitors.tools[PY_MONITORING_EVENT_LINE]\n        );\n    PyObject *line_obj = PyLong_FromSsize_t(line);\n    if (line_obj == NULL) {\n        return -1;\n    }\n    PyObject *args[3] = { NULL, (PyObject *)code, line_obj };\n    while (tools) {\n        int tool = most_significant_bit(tools);\n        assert(tool >= 0 && tool < 8);\n        assert(tools & (1 << tool));\n        tools &= ~(1 << tool);\n        int res = call_one_instrument(interp, tstate, &args[1],\n                                      2 | PY_VECTORCALL_ARGUMENTS_OFFSET,\n                                      tool, PY_MONITORING_EVENT_LINE);\n        if (res == 0) {\n            /* Nothing to do */\n        }\n        else if (res < 0) {\n            /* error */\n            Py_DECREF(line_obj);\n            return -1;\n        }\n        else {\n            /* DISABLE  */\n            remove_line_tools(code, i, 1 << tool);\n        }\n    }\n    Py_DECREF(line_obj);\ndone:\n    assert(original_opcode != 0);\n    assert(original_opcode < INSTRUMENTED_LINE);\n    assert(_PyOpcode_Deopt[original_opcode] == original_opcode);\n    return original_opcode;\n}\n\nint\n_Py_call_instrumentation_instruction(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr)\n{\n    PyCodeObject *code = frame->f_code;\n    assert(is_version_up_to_date(code, tstate->interp));\n    assert(instrumentation_cross_checks(tstate->interp, code));\n    int offset = (int)(instr - _PyCode_CODE(code));\n    _PyCoMonitoringData *instrumentation_data = code->_co_monitoring;\n    assert(instrumentation_data->per_instruction_opcodes);\n    int next_opcode = instrumentation_data->per_instruction_opcodes[offset];\n    if (tstate->tracing) {\n        return next_opcode;\n    }\n    PyInterpreterState *interp = tstate->interp;\n    uint8_t tools = instrumentation_data->per_instruction_tools != NULL ?\n        instrumentation_data->per_instruction_tools[offset] :\n        (interp->monitors.tools[PY_MONITORING_EVENT_INSTRUCTION] |\n         code->_co_monitoring->local_monitors.tools[PY_MONITORING_EVENT_INSTRUCTION]\n        );\n    int bytes_offset = offset * (int)sizeof(_Py_CODEUNIT);\n    PyObject *offset_obj = PyLong_FromSsize_t(bytes_offset);\n    if (offset_obj == NULL) {\n        return -1;\n    }\n    PyObject *args[3] = { NULL, (PyObject *)code, offset_obj };\n    while (tools) {\n        int tool = most_significant_bit(tools);\n        assert(tool >= 0 && tool < 8);\n        assert(tools & (1 << tool));\n        tools &= ~(1 << tool);\n        int res = call_one_instrument(interp, tstate, &args[1],\n                                      2 | PY_VECTORCALL_ARGUMENTS_OFFSET,\n                                      tool, PY_MONITORING_EVENT_INSTRUCTION);\n        if (res == 0) {\n            /* Nothing to do */\n        }\n        else if (res < 0) {\n            /* error */\n            Py_DECREF(offset_obj);\n            return -1;\n        }\n        else {\n            /* DISABLE  */\n            remove_per_instruction_tools(code, offset, 1 << tool);\n        }\n    }\n    Py_DECREF(offset_obj);\n    assert(next_opcode != 0);\n    return next_opcode;\n}\n\n\nPyObject *\n_PyMonitoring_RegisterCallback(int tool_id, int event_id, PyObject *obj)\n{\n    PyInterpreterState *is = _PyInterpreterState_Get();\n    assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);\n    assert(0 <= event_id && event_id < PY_MONITORING_EVENTS);\n    PyObject *callback = is->monitoring_callables[tool_id][event_id];\n    is->monitoring_callables[tool_id][event_id] = Py_XNewRef(obj);\n    return callback;\n}\n\nstatic void\ninitialize_tools(PyCodeObject *code)\n{\n    uint8_t* tools = code->_co_monitoring->tools;\n    assert(tools != NULL);\n    int code_len = (int)Py_SIZE(code);\n    for (int i = 0; i < code_len; i++) {\n        _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n        int opcode = instr->op.code;\n        if (opcode == INSTRUMENTED_LINE) {\n            opcode = code->_co_monitoring->lines[i].original_opcode;\n        }\n        bool instrumented = is_instrumented(opcode);\n        if (instrumented) {\n            opcode = DE_INSTRUMENT[opcode];\n            assert(opcode != 0);\n        }\n        opcode = _PyOpcode_Deopt[opcode];\n        if (opcode_has_event(opcode)) {\n            if (instrumented) {\n                int8_t event;\n                if (opcode == RESUME) {\n                    event = instr->op.arg != 0;\n                }\n                else {\n                    event = EVENT_FOR_OPCODE[opcode];\n                    assert(event > 0);\n                }\n                assert(event >= 0);\n                assert(event < PY_MONITORING_INSTRUMENTED_EVENTS);\n                tools[i] = code->_co_monitoring->active_monitors.tools[event];\n                CHECK(tools[i] != 0);\n            }\n            else {\n                tools[i] = 0;\n            }\n        }\n#ifdef Py_DEBUG\n        /* Initialize tools for invalid locations to all ones to try to catch errors */\n        else {\n            tools[i] = 0xff;\n        }\n        for (int j = 1; j <= _PyOpcode_Caches[opcode]; j++) {\n            tools[i+j] = 0xff;\n        }\n#endif\n        i += _PyOpcode_Caches[opcode];\n    }\n}\n\n#define NO_LINE -128\n\nstatic void\ninitialize_lines(PyCodeObject *code)\n{\n    _PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines;\n    assert(line_data != NULL);\n    int code_len = (int)Py_SIZE(code);\n    PyCodeAddressRange range;\n    _PyCode_InitAddressRange(code, &range);\n    for (int i = 0; i < code->_co_firsttraceable && i < code_len; i++) {\n        line_data[i].original_opcode = 0;\n        line_data[i].line_delta = -127;\n    }\n    int current_line = -1;\n    for (int i = code->_co_firsttraceable; i < code_len; ) {\n        int opcode = _Py_GetBaseOpcode(code, i);\n        int line = _PyCode_CheckLineNumber(i*(int)sizeof(_Py_CODEUNIT), &range);\n        line_data[i].line_delta = compute_line_delta(code, i, line);\n        int length = _PyInstruction_GetLength(code, i);\n        switch (opcode) {\n            case END_ASYNC_FOR:\n            case END_FOR:\n            case END_SEND:\n            case RESUME:\n                /* END_FOR cannot start a line, as it is skipped by FOR_ITER\n                 * END_SEND cannot start a line, as it is skipped by SEND\n                 * RESUME must not be instrumented with INSTRUMENT_LINE */\n                line_data[i].original_opcode = 0;\n                break;\n            default:\n                /* Set original_opcode to the opcode iff the instruction\n                 * starts a line, and thus should be instrumented.\n                 * This saves having to perform this check every time the\n                 * we turn instrumentation on or off, and serves as a sanity\n                 * check when debugging.\n                 */\n                if (line != current_line && line >= 0) {\n                    line_data[i].original_opcode = opcode;\n                }\n                else {\n                    line_data[i].original_opcode = 0;\n                }\n                current_line = line;\n        }\n        for (int j = 1; j < length; j++) {\n            line_data[i+j].original_opcode = 0;\n            line_data[i+j].line_delta = NO_LINE;\n        }\n        i += length;\n    }\n    for (int i = code->_co_firsttraceable; i < code_len; ) {\n        int opcode = _Py_GetBaseOpcode(code, i);\n        int oparg = 0;\n        while (opcode == EXTENDED_ARG) {\n            oparg = (oparg << 8) | _PyCode_CODE(code)[i].op.arg;\n            i++;\n            opcode = _Py_GetBaseOpcode(code, i);\n        }\n        oparg = (oparg << 8) | _PyCode_CODE(code)[i].op.arg;\n        i += _PyInstruction_GetLength(code, i);\n        int target = -1;\n        switch (opcode) {\n            case POP_JUMP_IF_FALSE:\n            case POP_JUMP_IF_TRUE:\n            case POP_JUMP_IF_NONE:\n            case POP_JUMP_IF_NOT_NONE:\n            case JUMP_FORWARD:\n            {\n                target = i + oparg;\n                break;\n            }\n            case FOR_ITER:\n            case SEND:\n            {\n                /* Skip over END_FOR/END_SEND */\n                target = i + oparg + 1;\n                break;\n            }\n            case JUMP_BACKWARD:\n            case JUMP_BACKWARD_NO_INTERRUPT:\n            {\n                target = i - oparg;\n                break;\n            }\n            default:\n                continue;\n        }\n        assert(target >= 0);\n        if (line_data[target].line_delta != NO_LINE) {\n            line_data[target].original_opcode = _Py_GetBaseOpcode(code, target);\n        }\n    }\n    /* Scan exception table */\n    unsigned char *start = (unsigned char *)PyBytes_AS_STRING(code->co_exceptiontable);\n    unsigned char *end = start + PyBytes_GET_SIZE(code->co_exceptiontable);\n    unsigned char *scan = start;\n    while (scan < end) {\n        int start_offset, size, handler;\n        scan = parse_varint(scan, &start_offset);\n        assert(start_offset >= 0 && start_offset < code_len);\n        scan = parse_varint(scan, &size);\n        assert(size >= 0 && start_offset+size <= code_len);\n        scan = parse_varint(scan, &handler);\n        assert(handler >= 0 && handler < code_len);\n        int depth_and_lasti;\n        scan = parse_varint(scan, &depth_and_lasti);\n        int original_opcode = _Py_GetBaseOpcode(code, handler);\n        /* Skip if not the start of a line.\n         * END_ASYNC_FOR is a bit special as it marks the end of\n         * an `async for` loop, which should not generate its own\n         * line event. */\n        if (line_data[handler].line_delta != NO_LINE &&\n            original_opcode != END_ASYNC_FOR) {\n            line_data[handler].original_opcode = original_opcode;\n        }\n    }\n}\n\nstatic void\ninitialize_line_tools(PyCodeObject *code, _Py_Monitors *all_events)\n{\n    uint8_t *line_tools = code->_co_monitoring->line_tools;\n    assert(line_tools != NULL);\n    int code_len = (int)Py_SIZE(code);\n    for (int i = 0; i < code_len; i++) {\n        line_tools[i] = all_events->tools[PY_MONITORING_EVENT_LINE];\n    }\n}\n\nstatic int\nallocate_instrumentation_data(PyCodeObject *code)\n{\n\n    if (code->_co_monitoring == NULL) {\n        code->_co_monitoring = PyMem_Malloc(sizeof(_PyCoMonitoringData));\n        if (code->_co_monitoring == NULL) {\n            PyErr_NoMemory();\n            return -1;\n        }\n        code->_co_monitoring->local_monitors = (_Py_Monitors){ 0 };\n        code->_co_monitoring->active_monitors = (_Py_Monitors){ 0 };\n        code->_co_monitoring->tools = NULL;\n        code->_co_monitoring->lines = NULL;\n        code->_co_monitoring->line_tools = NULL;\n        code->_co_monitoring->per_instruction_opcodes = NULL;\n        code->_co_monitoring->per_instruction_tools = NULL;\n    }\n    return 0;\n}\n\nstatic int\nupdate_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp)\n{\n    int code_len = (int)Py_SIZE(code);\n    if (allocate_instrumentation_data(code)) {\n        return -1;\n    }\n    _Py_Monitors all_events = monitors_or(\n        interp->monitors,\n        code->_co_monitoring->local_monitors);\n    bool multitools = multiple_tools(&all_events);\n    if (code->_co_monitoring->tools == NULL && multitools) {\n        code->_co_monitoring->tools = PyMem_Malloc(code_len);\n        if (code->_co_monitoring->tools == NULL) {\n            PyErr_NoMemory();\n            return -1;\n        }\n        initialize_tools(code);\n    }\n    if (all_events.tools[PY_MONITORING_EVENT_LINE]) {\n        if (code->_co_monitoring->lines == NULL) {\n            code->_co_monitoring->lines = PyMem_Malloc(code_len * sizeof(_PyCoLineInstrumentationData));\n            if (code->_co_monitoring->lines == NULL) {\n                PyErr_NoMemory();\n                return -1;\n            }\n            initialize_lines(code);\n        }\n        if (multitools && code->_co_monitoring->line_tools == NULL) {\n            code->_co_monitoring->line_tools = PyMem_Malloc(code_len);\n            if (code->_co_monitoring->line_tools == NULL) {\n                PyErr_NoMemory();\n                return -1;\n            }\n            initialize_line_tools(code, &all_events);\n        }\n    }\n    if (all_events.tools[PY_MONITORING_EVENT_INSTRUCTION]) {\n        if (code->_co_monitoring->per_instruction_opcodes == NULL) {\n            code->_co_monitoring->per_instruction_opcodes = PyMem_Malloc(code_len * sizeof(_PyCoLineInstrumentationData));\n            if (code->_co_monitoring->per_instruction_opcodes == NULL) {\n                PyErr_NoMemory();\n                return -1;\n            }\n            /* This may not be necessary, as we can initialize this memory lazily, but it helps catch errors. */\n            for (int i = 0; i < code_len; i++) {\n                code->_co_monitoring->per_instruction_opcodes[i] = 0;\n            }\n        }\n        if (multitools && code->_co_monitoring->per_instruction_tools == NULL) {\n            code->_co_monitoring->per_instruction_tools = PyMem_Malloc(code_len);\n            if (code->_co_monitoring->per_instruction_tools == NULL) {\n                PyErr_NoMemory();\n                return -1;\n            }\n            /* This may not be necessary, as we can initialize this memory lazily, but it helps catch errors. */\n            for (int i = 0; i < code_len; i++) {\n                code->_co_monitoring->per_instruction_tools[i] = 0;\n            }\n        }\n    }\n    return 0;\n}\n\nstatic const uint8_t super_instructions[256] = {\n    [LOAD_FAST__LOAD_CONST] = 1,\n    [LOAD_CONST__LOAD_FAST] = 1,\n};\n\n/* Should use instruction metadata for this */\nstatic bool\nis_super_instruction(uint8_t opcode) {\n    return super_instructions[opcode] != 0;\n}\n\nint\n_Py_Instrument(PyCodeObject *code, PyInterpreterState *interp)\n{\n    if (is_version_up_to_date(code, interp)) {\n        assert(\n            interp->monitoring_version == 0 ||\n            instrumentation_cross_checks(interp, code)\n        );\n        return 0;\n    }\n    int code_len = (int)Py_SIZE(code);\n    if (update_instrumentation_data(code, interp)) {\n        return -1;\n    }\n    _Py_Monitors active_events = monitors_or(\n        interp->monitors,\n        code->_co_monitoring->local_monitors);\n    _Py_Monitors new_events;\n    _Py_Monitors removed_events;\n\n    bool restarted = interp->last_restart_version > code->_co_instrumentation_version;\n    if (restarted) {\n        removed_events = code->_co_monitoring->active_monitors;\n        new_events = active_events;\n    }\n    else {\n        removed_events = monitors_sub(code->_co_monitoring->active_monitors, active_events);\n        new_events = monitors_sub(active_events, code->_co_monitoring->active_monitors);\n        assert(monitors_are_empty(monitors_and(new_events, removed_events)));\n    }\n    code->_co_monitoring->active_monitors = active_events;\n    code->_co_instrumentation_version = interp->monitoring_version;\n    if (monitors_are_empty(new_events) && monitors_are_empty(removed_events)) {\n#ifdef INSTRUMENT_DEBUG\n        sanity_check_instrumentation(code);\n#endif\n        return 0;\n    }\n    /* Insert instrumentation */\n    for (int i = 0; i < code_len; i+= _PyInstruction_GetLength(code, i)) {\n        _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n        if (is_super_instruction(instr->op.code)) {\n            instr->op.code = _PyOpcode_Deopt[instr->op.code];\n        }\n        CHECK(instr->op.code != 0);\n        int base_opcode = _Py_GetBaseOpcode(code, i);\n        if (opcode_has_event(base_opcode)) {\n            int8_t event;\n            if (base_opcode == RESUME) {\n                event = instr->op.arg > 0;\n            }\n            else {\n                event = EVENT_FOR_OPCODE[base_opcode];\n                assert(event > 0);\n            }\n            uint8_t removed_tools = removed_events.tools[event];\n            if (removed_tools) {\n                remove_tools(code, i, event, removed_tools);\n            }\n            uint8_t new_tools = new_events.tools[event];\n            if (new_tools) {\n                add_tools(code, i, event, new_tools);\n            }\n        }\n    }\n\n    // GH-103845: We need to remove both the line and instruction instrumentation before\n    // adding new ones, otherwise we may remove the newly added instrumentation.\n\n    uint8_t removed_line_tools = removed_events.tools[PY_MONITORING_EVENT_LINE];\n    uint8_t removed_per_instruction_tools = removed_events.tools[PY_MONITORING_EVENT_INSTRUCTION];\n\n    if (removed_line_tools) {\n        _PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines;\n        for (int i = code->_co_firsttraceable; i < code_len;) {\n            if (line_data[i].original_opcode) {\n                if (removed_line_tools) {\n                    remove_line_tools(code, i, removed_line_tools);\n                }\n            }\n            i += _PyInstruction_GetLength(code, i);\n        }\n    }\n    if (removed_per_instruction_tools) {\n        for (int i = code->_co_firsttraceable; i < code_len;) {\n            int opcode = _Py_GetBaseOpcode(code, i);\n            if (opcode == RESUME || opcode == END_FOR) {\n                i += _PyInstruction_GetLength(code, i);\n                continue;\n            }\n            if (removed_per_instruction_tools) {\n                remove_per_instruction_tools(code, i, removed_per_instruction_tools);\n            }\n            i += _PyInstruction_GetLength(code, i);\n        }\n    }\n\n    uint8_t new_line_tools = new_events.tools[PY_MONITORING_EVENT_LINE];\n    uint8_t new_per_instruction_tools = new_events.tools[PY_MONITORING_EVENT_INSTRUCTION];\n\n    if (new_line_tools) {\n        _PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines;\n        for (int i = code->_co_firsttraceable; i < code_len;) {\n            if (line_data[i].original_opcode) {\n                if (new_line_tools) {\n                    add_line_tools(code, i, new_line_tools);\n                }\n            }\n            i += _PyInstruction_GetLength(code, i);\n        }\n    }\n    if (new_per_instruction_tools) {\n        for (int i = code->_co_firsttraceable; i < code_len;) {\n            int opcode = _Py_GetBaseOpcode(code, i);\n            if (opcode == RESUME || opcode == END_FOR) {\n                i += _PyInstruction_GetLength(code, i);\n                continue;\n            }\n            if (new_per_instruction_tools) {\n                add_per_instruction_tools(code, i, new_per_instruction_tools);\n            }\n            i += _PyInstruction_GetLength(code, i);\n        }\n    }\n#ifdef INSTRUMENT_DEBUG\n    sanity_check_instrumentation(code);\n#endif\n    return 0;\n}\n\n#define C_RETURN_EVENTS \\\n    ((1 << PY_MONITORING_EVENT_C_RETURN) | \\\n     (1 << PY_MONITORING_EVENT_C_RAISE))\n\n#define C_CALL_EVENTS \\\n    (C_RETURN_EVENTS | (1 << PY_MONITORING_EVENT_CALL))\n\n\nstatic int\ninstrument_all_executing_code_objects(PyInterpreterState *interp) {\n    _PyRuntimeState *runtime = &_PyRuntime;\n    HEAD_LOCK(runtime);\n    PyThreadState* ts = PyInterpreterState_ThreadHead(interp);\n    HEAD_UNLOCK(runtime);\n    while (ts) {\n        _PyInterpreterFrame *frame = ts->cframe->current_frame;\n        while (frame) {\n            if (frame->owner != FRAME_OWNED_BY_CSTACK) {\n                if (_Py_Instrument(frame->f_code, interp)) {\n                    return -1;\n                }\n            }\n            frame = frame->previous;\n        }\n        HEAD_LOCK(runtime);\n        ts = PyThreadState_Next(ts);\n        HEAD_UNLOCK(runtime);\n    }\n    return 0;\n}\n\nstatic void\nset_events(_Py_Monitors *m, int tool_id, _PyMonitoringEventSet events)\n{\n    assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);\n    for (int e = 0; e < PY_MONITORING_UNGROUPED_EVENTS; e++) {\n        uint8_t *tools = &m->tools[e];\n        int val = (events >> e) & 1;\n        *tools &= ~(1 << tool_id);\n        *tools |= (val << tool_id);\n    }\n}\n\nstatic int\ncheck_tool(PyInterpreterState *interp, int tool_id)\n{\n    if (tool_id < PY_MONITORING_SYS_PROFILE_ID &&\n        interp->monitoring_tool_names[tool_id] == NULL)\n    {\n        PyErr_Format(PyExc_ValueError, \"tool %d is not in use\", tool_id);\n        return -1;\n    }\n    return 0;\n}\n\nint\n_PyMonitoring_SetEvents(int tool_id, _PyMonitoringEventSet events)\n{\n    assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    assert(events < (1 << PY_MONITORING_UNGROUPED_EVENTS));\n    if (check_tool(interp, tool_id)) {\n        return -1;\n    }\n    uint32_t existing_events = get_events(&interp->monitors, tool_id);\n    if (existing_events == events) {\n        return 0;\n    }\n    set_events(&interp->monitors, tool_id, events);\n    interp->monitoring_version++;\n    return instrument_all_executing_code_objects(interp);\n}\n\nint\n_PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEventSet events)\n{\n    assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    assert(events < (1 << PY_MONITORING_UNGROUPED_EVENTS));\n    if (check_tool(interp, tool_id)) {\n        return -1;\n    }\n    if (allocate_instrumentation_data(code)) {\n        return -1;\n    }\n    _Py_Monitors *local = &code->_co_monitoring->local_monitors;\n    uint32_t existing_events = get_events(local, tool_id);\n    if (existing_events == events) {\n        return 0;\n    }\n    set_events(local, tool_id, events);\n    if (is_version_up_to_date(code, interp)) {\n        /* Force instrumentation update */\n        code->_co_instrumentation_version = UINT64_MAX;\n    }\n    if (_Py_Instrument(code, interp)) {\n        return -1;\n    }\n    return 0;\n}\n\n/*[clinic input]\nmodule monitoring\n[clinic start generated code]*/\n/*[clinic end generated code: output=da39a3ee5e6b4b0d input=37257f5987a360cf]*/\n/*[clinic end generated code]*/\n\n#include \"clinic/instrumentation.c.h\"\n\nstatic int\ncheck_valid_tool(int tool_id)\n{\n    if (tool_id < 0 || tool_id >= PY_MONITORING_SYS_PROFILE_ID) {\n        PyErr_Format(PyExc_ValueError, \"invalid tool %d (must be between 0 and 5)\", tool_id);\n        return -1;\n    }\n    return 0;\n}\n\n/*[clinic input]\nmonitoring.use_tool_id\n\n    tool_id: int\n    name: object\n    /\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_use_tool_id_impl(PyObject *module, int tool_id, PyObject *name)\n/*[clinic end generated code: output=30d76dc92b7cd653 input=ebc453761c621be1]*/\n{\n    if (check_valid_tool(tool_id))  {\n        return NULL;\n    }\n    if (!PyUnicode_Check(name)) {\n        PyErr_SetString(PyExc_ValueError, \"tool name must be a str\");\n        return NULL;\n    }\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    if (interp->monitoring_tool_names[tool_id] != NULL) {\n        PyErr_Format(PyExc_ValueError, \"tool %d is already in use\", tool_id);\n        return NULL;\n    }\n    interp->monitoring_tool_names[tool_id] = Py_NewRef(name);\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nmonitoring.free_tool_id\n\n    tool_id: int\n    /\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_free_tool_id_impl(PyObject *module, int tool_id)\n/*[clinic end generated code: output=86c2d2a1219a8591 input=a23fb6be3a8618e9]*/\n{\n    if (check_valid_tool(tool_id))  {\n        return NULL;\n    }\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    Py_CLEAR(interp->monitoring_tool_names[tool_id]);\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nmonitoring.get_tool\n\n    tool_id: int\n    /\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_get_tool_impl(PyObject *module, int tool_id)\n/*[clinic end generated code: output=1c05a98b404a9a16 input=eeee9bebd0bcae9d]*/\n\n/*[clinic end generated code]*/\n{\n    if (check_valid_tool(tool_id))  {\n        return NULL;\n    }\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    PyObject *name = interp->monitoring_tool_names[tool_id];\n    if (name == NULL) {\n        Py_RETURN_NONE;\n    }\n    return Py_NewRef(name);\n}\n\n/*[clinic input]\nmonitoring.register_callback\n\n\n    tool_id: int\n    event: int\n    func: object\n    /\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_register_callback_impl(PyObject *module, int tool_id, int event,\n                                  PyObject *func)\n/*[clinic end generated code: output=e64daa363004030c input=df6d70ea4cf81007]*/\n{\n    if (check_valid_tool(tool_id))  {\n        return NULL;\n    }\n    if (_Py_popcount32(event) != 1) {\n        PyErr_SetString(PyExc_ValueError, \"The callback can only be set for one event at a time\");\n        return NULL;\n    }\n    int event_id = _Py_bit_length(event)-1;\n    if (event_id < 0 || event_id >= PY_MONITORING_EVENTS) {\n        PyErr_Format(PyExc_ValueError, \"invalid event %d\", event);\n        return NULL;\n    }\n    if (func == Py_None) {\n        func = NULL;\n    }\n    func = _PyMonitoring_RegisterCallback(tool_id, event_id, func);\n    if (func == NULL) {\n        Py_RETURN_NONE;\n    }\n    return func;\n}\n\n/*[clinic input]\nmonitoring.get_events -> int\n\n    tool_id: int\n    /\n\n[clinic start generated code]*/\n\nstatic int\nmonitoring_get_events_impl(PyObject *module, int tool_id)\n/*[clinic end generated code: output=4450cc13f826c8c0 input=a64b238f76c4b2f7]*/\n{\n    if (check_valid_tool(tool_id))  {\n        return -1;\n    }\n    _Py_Monitors *m = &_PyInterpreterState_Get()->monitors;\n    _PyMonitoringEventSet event_set = get_events(m, tool_id);\n    return event_set;\n}\n\n/*[clinic input]\nmonitoring.set_events\n\n    tool_id: int\n    event_set: int\n    /\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_set_events_impl(PyObject *module, int tool_id, int event_set)\n/*[clinic end generated code: output=1916c1e49cfb5bdb input=a77ba729a242142b]*/\n{\n    if (check_valid_tool(tool_id))  {\n        return NULL;\n    }\n    if (event_set < 0 || event_set >= (1 << PY_MONITORING_EVENTS)) {\n        PyErr_Format(PyExc_ValueError, \"invalid event set 0x%x\", event_set);\n        return NULL;\n    }\n    if ((event_set & C_RETURN_EVENTS) && (event_set & C_CALL_EVENTS) != C_CALL_EVENTS) {\n        PyErr_Format(PyExc_ValueError, \"cannot set C_RETURN or C_RAISE events independently\");\n        return NULL;\n    }\n    event_set &= ~C_RETURN_EVENTS;\n    if (_PyMonitoring_SetEvents(tool_id, event_set)) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nmonitoring.get_local_events -> int\n\n    tool_id: int\n    code: object\n    /\n\n[clinic start generated code]*/\n\nstatic int\nmonitoring_get_local_events_impl(PyObject *module, int tool_id,\n                                 PyObject *code)\n/*[clinic end generated code: output=d3e92c1c9c1de8f9 input=bb0f927530386a94]*/\n{\n    if (!PyCode_Check(code)) {\n        PyErr_Format(\n            PyExc_TypeError,\n            \"code must be a code object\"\n        );\n        return -1;\n    }\n    if (check_valid_tool(tool_id))  {\n        return -1;\n    }\n    _PyMonitoringEventSet event_set = 0;\n    _PyCoMonitoringData *data = ((PyCodeObject *)code)->_co_monitoring;\n    if (data != NULL) {\n        for (int e = 0; e < PY_MONITORING_UNGROUPED_EVENTS; e++) {\n            if ((data->local_monitors.tools[e] >> tool_id) & 1) {\n                event_set |= (1 << e);\n            }\n        }\n    }\n    return event_set;\n}\n\n/*[clinic input]\nmonitoring.set_local_events\n\n    tool_id: int\n    code: object\n    event_set: int\n    /\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_set_local_events_impl(PyObject *module, int tool_id,\n                                 PyObject *code, int event_set)\n/*[clinic end generated code: output=68cc755a65dfea99 input=5655ecd78d937a29]*/\n{\n    if (!PyCode_Check(code)) {\n        PyErr_Format(\n            PyExc_TypeError,\n            \"code must be a code object\"\n        );\n        return NULL;\n    }\n    if (check_valid_tool(tool_id))  {\n        return NULL;\n    }\n    if (event_set < 0 || event_set >= (1 << PY_MONITORING_EVENTS)) {\n        PyErr_Format(PyExc_ValueError, \"invalid event set 0x%x\", event_set);\n        return NULL;\n    }\n    if ((event_set & C_RETURN_EVENTS) && (event_set & C_CALL_EVENTS) != C_CALL_EVENTS) {\n        PyErr_Format(PyExc_ValueError, \"cannot set C_RETURN or C_RAISE events independently\");\n        return NULL;\n    }\n    event_set &= ~C_RETURN_EVENTS;\n    if (_PyMonitoring_SetLocalEvents((PyCodeObject*)code, tool_id, event_set)) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nmonitoring.restart_events\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_restart_events_impl(PyObject *module)\n/*[clinic end generated code: output=e025dd5ba33314c4 input=add8a855063c8008]*/\n{\n    /* We want to ensure that:\n     * last restart version > instrumented version for all code objects\n     * last restart version < current version\n     */\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    interp->last_restart_version = interp->monitoring_version + 1;\n    interp->monitoring_version = interp->last_restart_version + 1;\n    if (instrument_all_executing_code_objects(interp)) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\nstatic int\nadd_power2_constant(PyObject *obj, const char *name, int i)\n{\n    PyObject *val = PyLong_FromLong(1<<i);\n    if (val == NULL) {\n        return -1;\n    }\n    int err = PyObject_SetAttrString(obj, name, val);\n    Py_DECREF(val);\n    return err;\n}\n\nstatic const char *const event_names [] = {\n    [PY_MONITORING_EVENT_PY_START] = \"PY_START\",\n    [PY_MONITORING_EVENT_PY_RESUME] = \"PY_RESUME\",\n    [PY_MONITORING_EVENT_PY_RETURN] = \"PY_RETURN\",\n    [PY_MONITORING_EVENT_PY_YIELD] = \"PY_YIELD\",\n    [PY_MONITORING_EVENT_CALL] = \"CALL\",\n    [PY_MONITORING_EVENT_LINE] = \"LINE\",\n    [PY_MONITORING_EVENT_INSTRUCTION] = \"INSTRUCTION\",\n    [PY_MONITORING_EVENT_JUMP] = \"JUMP\",\n    [PY_MONITORING_EVENT_BRANCH] = \"BRANCH\",\n    [PY_MONITORING_EVENT_C_RETURN] = \"C_RETURN\",\n    [PY_MONITORING_EVENT_PY_THROW] = \"PY_THROW\",\n    [PY_MONITORING_EVENT_RAISE] = \"RAISE\",\n    [PY_MONITORING_EVENT_EXCEPTION_HANDLED] = \"EXCEPTION_HANDLED\",\n    [PY_MONITORING_EVENT_C_RAISE] = \"C_RAISE\",\n    [PY_MONITORING_EVENT_PY_UNWIND] = \"PY_UNWIND\",\n    [PY_MONITORING_EVENT_STOP_ITERATION] = \"STOP_ITERATION\",\n};\n\n/*[clinic input]\nmonitoring._all_events\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring__all_events_impl(PyObject *module)\n/*[clinic end generated code: output=6b7581e2dbb690f6 input=62ee9672c17b7f0e]*/\n{\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    PyObject *res = PyDict_New();\n    if (res == NULL) {\n        return NULL;\n    }\n    for (int e = 0; e < PY_MONITORING_UNGROUPED_EVENTS; e++) {\n        uint8_t tools = interp->monitors.tools[e];\n        if (tools == 0) {\n            continue;\n        }\n        PyObject *tools_obj = PyLong_FromLong(tools);\n        assert(tools_obj != NULL);\n        int err = PyDict_SetItemString(res, event_names[e], tools_obj);\n        Py_DECREF(tools_obj);\n        if (err < 0) {\n            Py_DECREF(res);\n            return NULL;\n        }\n    }\n    return res;\n}\n\nstatic PyMethodDef methods[] = {\n    MONITORING_USE_TOOL_ID_METHODDEF\n    MONITORING_FREE_TOOL_ID_METHODDEF\n    MONITORING_GET_TOOL_METHODDEF\n    MONITORING_REGISTER_CALLBACK_METHODDEF\n    MONITORING_GET_EVENTS_METHODDEF\n    MONITORING_SET_EVENTS_METHODDEF\n    MONITORING_GET_LOCAL_EVENTS_METHODDEF\n    MONITORING_SET_LOCAL_EVENTS_METHODDEF\n    MONITORING_RESTART_EVENTS_METHODDEF\n    MONITORING__ALL_EVENTS_METHODDEF\n    {NULL, NULL}  // sentinel\n};\n\nstatic struct PyModuleDef monitoring_module = {\n    PyModuleDef_HEAD_INIT,\n    .m_name = \"sys.monitoring\",\n    .m_size = -1, /* multiple \"initialization\" just copies the module dict. */\n    .m_methods = methods,\n};\n\nPyObject *_Py_CreateMonitoringObject(void)\n{\n    PyObject *mod = _PyModule_CreateInitialized(&monitoring_module, PYTHON_API_VERSION);\n    if (mod == NULL) {\n        return NULL;\n    }\n    if (PyObject_SetAttrString(mod, \"DISABLE\", &_PyInstrumentation_DISABLE)) {\n        goto error;\n    }\n    if (PyObject_SetAttrString(mod, \"MISSING\", &_PyInstrumentation_MISSING)) {\n        goto error;\n    }\n    PyObject *events = _PyNamespace_New(NULL);\n    if (events == NULL) {\n        goto error;\n    }\n    int err = PyObject_SetAttrString(mod, \"events\", events);\n    Py_DECREF(events);\n    if (err) {\n        goto error;\n    }\n    for (int i = 0; i < PY_MONITORING_EVENTS; i++) {\n        if (add_power2_constant(events, event_names[i], i)) {\n            goto error;\n        }\n    }\n    err = PyObject_SetAttrString(events, \"NO_EVENTS\", _PyLong_GetZero());\n    if (err) goto error;\n    PyObject *val = PyLong_FromLong(PY_MONITORING_DEBUGGER_ID);\n    err = PyObject_SetAttrString(mod, \"DEBUGGER_ID\", val);\n    Py_DECREF(val);\n    if (err) goto error;\n    val = PyLong_FromLong(PY_MONITORING_COVERAGE_ID);\n    err = PyObject_SetAttrString(mod, \"COVERAGE_ID\", val);\n    Py_DECREF(val);\n    if (err) goto error;\n    val = PyLong_FromLong(PY_MONITORING_PROFILER_ID);\n    err = PyObject_SetAttrString(mod, \"PROFILER_ID\", val);\n    Py_DECREF(val);\n    if (err) goto error;\n    val = PyLong_FromLong(PY_MONITORING_OPTIMIZER_ID);\n    err = PyObject_SetAttrString(mod, \"OPTIMIZER_ID\", val);\n    Py_DECREF(val);\n    if (err) goto error;\n    return mod;\nerror:\n    Py_DECREF(mod);\n    return NULL;\n}\n"
  },
  {
    "path": "InstruMentation.c",
    "content": "\n\n#include \"Python.h\"\n#include \"pycore_call.h\"\n#include \"pycore_frame.h\"\n#include \"pycore_interp.h\"\n#include \"pycore_long.h\"\n#include \"pycore_namespace.h\"\n#include \"pycore_object.h\"\n#include \"pycore_opcode.h\"\n#include \"pycore_pyerrors.h\"\n#include \"pycore_pystate.h\"\n\n/* Uncomment this to dump debugging output when assertions fail */\n// #define INSTRUMENT_DEBUG 1\n\nPyObject _PyInstrumentation_DISABLE =\n{\n    .ob_refcnt = _Py_IMMORTAL_REFCNT,\n    .ob_type = &PyBaseObject_Type\n};\n\nPyObject _PyInstrumentation_MISSING =\n{\n    .ob_refcnt = _Py_IMMORTAL_REFCNT,\n    .ob_type = &PyBaseObject_Type\n};\n\nstatic const int8_t EVENT_FOR_OPCODE[256] = {\n    [RETURN_CONST] = PY_MONITORING_EVENT_PY_RETURN,\n    [INSTRUMENTED_RETURN_CONST] = PY_MONITORING_EVENT_PY_RETURN,\n    [RETURN_VALUE] = PY_MONITORING_EVENT_PY_RETURN,\n    [INSTRUMENTED_RETURN_VALUE] = PY_MONITORING_EVENT_PY_RETURN,\n    [CALL] = PY_MONITORING_EVENT_CALL,\n    [INSTRUMENTED_CALL] = PY_MONITORING_EVENT_CALL,\n    [CALL_FUNCTION_EX] = PY_MONITORING_EVENT_CALL,\n    [INSTRUMENTED_CALL_FUNCTION_EX] = PY_MONITORING_EVENT_CALL,\n    [LOAD_SUPER_ATTR] = PY_MONITORING_EVENT_CALL,\n    [INSTRUMENTED_LOAD_SUPER_ATTR] = PY_MONITORING_EVENT_CALL,\n    [RESUME] = -1,\n    [YIELD_VALUE] = PY_MONITORING_EVENT_PY_YIELD,\n    [INSTRUMENTED_YIELD_VALUE] = PY_MONITORING_EVENT_PY_YIELD,\n    [JUMP_FORWARD] = PY_MONITORING_EVENT_JUMP,\n    [JUMP_BACKWARD] = PY_MONITORING_EVENT_JUMP,\n    [POP_JUMP_IF_FALSE] = PY_MONITORING_EVENT_BRANCH,\n    [POP_JUMP_IF_TRUE] = PY_MONITORING_EVENT_BRANCH,\n    [POP_JUMP_IF_NONE] = PY_MONITORING_EVENT_BRANCH,\n    [POP_JUMP_IF_NOT_NONE] = PY_MONITORING_EVENT_BRANCH,\n    [INSTRUMENTED_JUMP_FORWARD] = PY_MONITORING_EVENT_JUMP,\n    [INSTRUMENTED_JUMP_BACKWARD] = PY_MONITORING_EVENT_JUMP,\n    [INSTRUMENTED_POP_JUMP_IF_FALSE] = PY_MONITORING_EVENT_BRANCH,\n    [INSTRUMENTED_POP_JUMP_IF_TRUE] = PY_MONITORING_EVENT_BRANCH,\n    [INSTRUMENTED_POP_JUMP_IF_NONE] = PY_MONITORING_EVENT_BRANCH,\n    [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = PY_MONITORING_EVENT_BRANCH,\n    [FOR_ITER] = PY_MONITORING_EVENT_BRANCH,\n    [INSTRUMENTED_FOR_ITER] = PY_MONITORING_EVENT_BRANCH,\n    [END_FOR] = PY_MONITORING_EVENT_STOP_ITERATION,\n    [INSTRUMENTED_END_FOR] = PY_MONITORING_EVENT_STOP_ITERATION,\n    [END_SEND] = PY_MONITORING_EVENT_STOP_ITERATION,\n    [INSTRUMENTED_END_SEND] = PY_MONITORING_EVENT_STOP_ITERATION,\n};\n\nstatic const uint8_t DE_INSTRUMENT[256] = {\n    [INSTRUMENTED_RESUME] = RESUME,\n    [INSTRUMENTED_RETURN_VALUE] = RETURN_VALUE,\n    [INSTRUMENTED_RETURN_CONST] = RETURN_CONST,\n    [INSTRUMENTED_CALL] = CALL,\n    [INSTRUMENTED_CALL_FUNCTION_EX] = CALL_FUNCTION_EX,\n    [INSTRUMENTED_YIELD_VALUE] = YIELD_VALUE,\n    [INSTRUMENTED_JUMP_FORWARD] = JUMP_FORWARD,\n    [INSTRUMENTED_JUMP_BACKWARD] = JUMP_BACKWARD,\n    [INSTRUMENTED_POP_JUMP_IF_FALSE] = POP_JUMP_IF_FALSE,\n    [INSTRUMENTED_POP_JUMP_IF_TRUE] = POP_JUMP_IF_TRUE,\n    [INSTRUMENTED_POP_JUMP_IF_NONE] = POP_JUMP_IF_NONE,\n    [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = POP_JUMP_IF_NOT_NONE,\n    [INSTRUMENTED_FOR_ITER] = FOR_ITER,\n    [INSTRUMENTED_END_FOR] = END_FOR,\n    [INSTRUMENTED_END_SEND] = END_SEND,\n    [INSTRUMENTED_LOAD_SUPER_ATTR] = LOAD_SUPER_ATTR,\n};\n\nstatic const uint8_t INSTRUMENTED_OPCODES[256] = {\n    [RETURN_CONST] = INSTRUMENTED_RETURN_CONST,\n    [INSTRUMENTED_RETURN_CONST] = INSTRUMENTED_RETURN_CONST,\n    [RETURN_VALUE] = INSTRUMENTED_RETURN_VALUE,\n    [INSTRUMENTED_RETURN_VALUE] = INSTRUMENTED_RETURN_VALUE,\n    [CALL] = INSTRUMENTED_CALL,\n    [INSTRUMENTED_CALL] = INSTRUMENTED_CALL,\n    [CALL_FUNCTION_EX] = INSTRUMENTED_CALL_FUNCTION_EX,\n    [INSTRUMENTED_CALL_FUNCTION_EX] = INSTRUMENTED_CALL_FUNCTION_EX,\n    [YIELD_VALUE] = INSTRUMENTED_YIELD_VALUE,\n    [INSTRUMENTED_YIELD_VALUE] = INSTRUMENTED_YIELD_VALUE,\n    [RESUME] = INSTRUMENTED_RESUME,\n    [INSTRUMENTED_RESUME] = INSTRUMENTED_RESUME,\n    [JUMP_FORWARD] = INSTRUMENTED_JUMP_FORWARD,\n    [INSTRUMENTED_JUMP_FORWARD] = INSTRUMENTED_JUMP_FORWARD,\n    [JUMP_BACKWARD] = INSTRUMENTED_JUMP_BACKWARD,\n    [INSTRUMENTED_JUMP_BACKWARD] = INSTRUMENTED_JUMP_BACKWARD,\n    [POP_JUMP_IF_FALSE] = INSTRUMENTED_POP_JUMP_IF_FALSE,\n    [INSTRUMENTED_POP_JUMP_IF_FALSE] = INSTRUMENTED_POP_JUMP_IF_FALSE,\n    [POP_JUMP_IF_TRUE] = INSTRUMENTED_POP_JUMP_IF_TRUE,\n    [INSTRUMENTED_POP_JUMP_IF_TRUE] = INSTRUMENTED_POP_JUMP_IF_TRUE,\n    [POP_JUMP_IF_NONE] = INSTRUMENTED_POP_JUMP_IF_NONE,\n    [INSTRUMENTED_POP_JUMP_IF_NONE] = INSTRUMENTED_POP_JUMP_IF_NONE,\n    [POP_JUMP_IF_NOT_NONE] = INSTRUMENTED_POP_JUMP_IF_NOT_NONE,\n    [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = INSTRUMENTED_POP_JUMP_IF_NOT_NONE,\n    [END_FOR] = INSTRUMENTED_END_FOR,\n    [INSTRUMENTED_END_FOR] = INSTRUMENTED_END_FOR,\n    [END_SEND] = INSTRUMENTED_END_SEND,\n    [INSTRUMENTED_END_SEND] = INSTRUMENTED_END_SEND,\n    [FOR_ITER] = INSTRUMENTED_FOR_ITER,\n    [INSTRUMENTED_FOR_ITER] = INSTRUMENTED_FOR_ITER,\n    [LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR,\n    [INSTRUMENTED_LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR,\n\n    [INSTRUMENTED_LINE] = INSTRUMENTED_LINE,\n    [INSTRUMENTED_INSTRUCTION] = INSTRUMENTED_INSTRUCTION,\n};\n\nstatic inline bool\nopcode_has_event(int opcode)\n{\n    return (\n        opcode < INSTRUMENTED_LINE &&\n        INSTRUMENTED_OPCODES[opcode] > 0\n    );\n}\n\nstatic inline bool\nis_instrumented(int opcode)\n{\n    assert(opcode != 0);\n    assert(opcode != RESERVED);\n    return opcode >= MIN_INSTRUMENTED_OPCODE;\n}\n\n#ifndef NDEBUG\nstatic inline bool\nmonitors_equals(_Py_Monitors a, _Py_Monitors b)\n{\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        if (a.tools[i] != b.tools[i]) {\n            return false;\n        }\n    }\n    return true;\n}\n#endif\n\nstatic inline _Py_Monitors\nmonitors_sub(_Py_Monitors a, _Py_Monitors b)\n{\n    _Py_Monitors res;\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        res.tools[i] = a.tools[i] & ~b.tools[i];\n    }\n    return res;\n}\n\n#ifndef NDEBUG\nstatic inline _Py_Monitors\nmonitors_and(_Py_Monitors a, _Py_Monitors b)\n{\n    _Py_Monitors res;\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        res.tools[i] = a.tools[i] & b.tools[i];\n    }\n    return res;\n}\n#endif\n\nstatic inline _Py_Monitors\nmonitors_or(_Py_Monitors a, _Py_Monitors b)\n{\n    _Py_Monitors res;\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        res.tools[i] = a.tools[i] | b.tools[i];\n    }\n    return res;\n}\n\nstatic inline bool\nmonitors_are_empty(_Py_Monitors m)\n{\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        if (m.tools[i]) {\n            return false;\n        }\n    }\n    return true;\n}\n\nstatic inline bool\nmultiple_tools(_Py_Monitors *m)\n{\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        if (_Py_popcount32(m->tools[i]) > 1) {\n            return true;\n        }\n    }\n    return false;\n}\n\nstatic inline _PyMonitoringEventSet\nget_events(_Py_Monitors *m, int tool_id)\n{\n    _PyMonitoringEventSet result = 0;\n    for (int e = 0; e < PY_MONITORING_UNGROUPED_EVENTS; e++) {\n        if ((m->tools[e] >> tool_id) & 1) {\n            result |= (1 << e);\n        }\n    }\n    return result;\n}\n\n/* Line delta.\n * 8 bit value.\n * if line_delta == -128:\n *     line = None # represented as -1\n * elif line_delta == -127:\n *     line = PyCode_Addr2Line(code, offset * sizeof(_Py_CODEUNIT));\n * else:\n *     line = first_line  + (offset >> OFFSET_SHIFT) + line_delta;\n */\n\n#define NO_LINE -128\n#define COMPUTED_LINE -127\n\n#define OFFSET_SHIFT 4\n\nstatic int8_t\ncompute_line_delta(PyCodeObject *code, int offset, int line)\n{\n    if (line < 0) {\n        return NO_LINE;\n    }\n    int delta = line - code->co_firstlineno - (offset >> OFFSET_SHIFT);\n    if (delta <= INT8_MAX && delta > COMPUTED_LINE) {\n        return delta;\n    }\n    return COMPUTED_LINE;\n}\n\nstatic int\ncompute_line(PyCodeObject *code, int offset, int8_t line_delta)\n{\n    if (line_delta > COMPUTED_LINE) {\n        return code->co_firstlineno + (offset >> OFFSET_SHIFT) + line_delta;\n    }\n    if (line_delta == NO_LINE) {\n\n        return -1;\n    }\n    assert(line_delta == COMPUTED_LINE);\n    /* Look it up */\n    return PyCode_Addr2Line(code, offset * sizeof(_Py_CODEUNIT));\n}\n\nint\n_PyInstruction_GetLength(PyCodeObject *code, int offset)\n{\n    int opcode = _PyCode_CODE(code)[offset].op.code;\n    assert(opcode != 0);\n    assert(opcode != RESERVED);\n    if (opcode == INSTRUMENTED_LINE) {\n        opcode = code->_co_monitoring->lines[offset].original_opcode;\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        opcode = code->_co_monitoring->per_instruction_opcodes[offset];\n    }\n    int deinstrumented = DE_INSTRUMENT[opcode];\n    if (deinstrumented) {\n        opcode = deinstrumented;\n    }\n    else {\n        opcode = _PyOpcode_Deopt[opcode];\n    }\n    assert(opcode != 0);\n    assert(!is_instrumented(opcode));\n    assert(opcode == _PyOpcode_Deopt[opcode]);\n    return 1 + _PyOpcode_Caches[opcode];\n}\n\n#ifdef INSTRUMENT_DEBUG\n\nstatic void\ndump_instrumentation_data_tools(PyCodeObject *code, uint8_t *tools, int i, FILE*out)\n{\n    if (tools == NULL) {\n        fprintf(out, \"tools = NULL\");\n    }\n    else {\n        fprintf(out, \"tools = %d\", tools[i]);\n    }\n}\n\nstatic void\ndump_instrumentation_data_lines(PyCodeObject *code, _PyCoLineInstrumentationData *lines, int i, FILE*out)\n{\n    if (lines == NULL) {\n        fprintf(out, \", lines = NULL\");\n    }\n    else if (lines[i].original_opcode == 0) {\n        fprintf(out, \", lines = {original_opcode = No LINE (0), line_delta = %d)\", lines[i].line_delta);\n    }\n    else {\n        fprintf(out, \", lines = {original_opcode = %s, line_delta = %d)\", _PyOpcode_OpName[lines[i].original_opcode], lines[i].line_delta);\n    }\n}\n\nstatic void\ndump_instrumentation_data_line_tools(PyCodeObject *code, uint8_t *line_tools, int i, FILE*out)\n{\n    if (line_tools == NULL) {\n        fprintf(out, \", line_tools = NULL\");\n    }\n    else {\n        fprintf(out, \", line_tools = %d\", line_tools[i]);\n    }\n}\n\nstatic void\ndump_instrumentation_data_per_instruction(PyCodeObject *code, _PyCoMonitoringData *data, int i, FILE*out)\n{\n    if (data->per_instruction_opcodes == NULL) {\n        fprintf(out, \", per-inst opcode = NULL\");\n    }\n    else {\n        fprintf(out, \", per-inst opcode = %s\", _PyOpcode_OpName[data->per_instruction_opcodes[i]]);\n    }\n    if (data->per_instruction_tools == NULL) {\n        fprintf(out, \", per-inst tools = NULL\");\n    }\n    else {\n        fprintf(out, \", per-inst tools = %d\", data->per_instruction_tools[i]);\n    }\n}\n\nstatic void\ndump_monitors(const char *prefix, _Py_Monitors monitors, FILE*out)\n{\n    fprintf(out, \"%s monitors:\\n\", prefix);\n    for (int event = 0; event < PY_MONITORING_UNGROUPED_EVENTS; event++) {\n        fprintf(out, \"    Event %d: Tools %x\\n\", event, monitors.tools[event]);\n    }\n}\n\n/* Like _Py_GetBaseOpcode but without asserts.\n * Does its best to give the right answer, but won't abort\n * if something is wrong */\nstatic int\nget_base_opcode_best_attempt(PyCodeObject *code, int offset)\n{\n    int opcode = _Py_OPCODE(_PyCode_CODE(code)[offset]);\n    if (INSTRUMENTED_OPCODES[opcode] != opcode) {\n        /* Not instrumented */\n        return _PyOpcode_Deopt[opcode] == 0 ? opcode : _PyOpcode_Deopt[opcode];\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        if (code->_co_monitoring->per_instruction_opcodes[offset] == 0) {\n            return opcode;\n        }\n        opcode = code->_co_monitoring->per_instruction_opcodes[offset];\n    }\n    if (opcode == INSTRUMENTED_LINE) {\n        if (code->_co_monitoring->lines[offset].original_opcode == 0) {\n            return opcode;\n        }\n        opcode = code->_co_monitoring->lines[offset].original_opcode;\n    }\n    int deinstrumented = DE_INSTRUMENT[opcode];\n    if (deinstrumented) {\n        return deinstrumented;\n    }\n    if (_PyOpcode_Deopt[opcode] == 0) {\n        return opcode;\n    }\n    return _PyOpcode_Deopt[opcode];\n}\n\n/* No error checking -- Don't use this for anything but experimental debugging */\nstatic void\ndump_instrumentation_data(PyCodeObject *code, int star, FILE*out)\n{\n    _PyCoMonitoringData *data = code->_co_monitoring;\n    fprintf(out, \"\\n\");\n    PyObject_Print(code->co_name, out, Py_PRINT_RAW);\n    fprintf(out, \"\\n\");\n    if (data == NULL) {\n        fprintf(out, \"NULL\\n\");\n        return;\n    }\n    dump_monitors(\"Global\", PyInterpreterState_Get()->monitors, out);\n    dump_monitors(\"Code\", data->local_monitors, out);\n    dump_monitors(\"Active\", data->active_monitors, out);\n    int code_len = (int)Py_SIZE(code);\n    bool starred = false;\n    for (int i = 0; i < code_len; i += _PyInstruction_GetLength(code, i)) {\n        _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n        int opcode = instr->op.code;\n        if (i == star) {\n            fprintf(out, \"**  \");\n            starred = true;\n        }\n        fprintf(out, \"Offset: %d, line: %d %s: \", i, PyCode_Addr2Line(code, i*2), _PyOpcode_OpName[opcode]);\n        dump_instrumentation_data_tools(code, data->tools, i, out);\n        dump_instrumentation_data_lines(code, data->lines, i, out);\n        dump_instrumentation_data_line_tools(code, data->line_tools, i, out);\n        dump_instrumentation_data_per_instruction(code, data, i, out);\n        fprintf(out, \"\\n\");\n        ;\n    }\n    if (!starred && star >= 0) {\n        fprintf(out, \"Error offset not at valid instruction offset: %d\\n\", star);\n        fprintf(out, \"    \");\n        dump_instrumentation_data_tools(code, data->tools, star, out);\n        dump_instrumentation_data_lines(code, data->lines, star, out);\n        dump_instrumentation_data_line_tools(code, data->line_tools, star, out);\n        dump_instrumentation_data_per_instruction(code, data, star, out);\n        fprintf(out, \"\\n\");\n    }\n}\n\n#define CHECK(test) do { \\\n    if (!(test)) { \\\n        dump_instrumentation_data(code, i, stderr); \\\n    } \\\n    assert(test); \\\n} while (0)\n\nstatic bool\nvalid_opcode(int opcode)\n{\n    if (opcode > 0 &&\n        opcode != RESERVED &&\n        opcode < 255 &&\n        _PyOpcode_OpName[opcode] &&\n        _PyOpcode_OpName[opcode][0] != '<')\n    {\n       return true;\n    }\n    return false;\n}\n\nstatic void\nsanity_check_instrumentation(PyCodeObject *code)\n{\n    _PyCoMonitoringData *data = code->_co_monitoring;\n    if (data == NULL) {\n        return;\n    }\n    _Py_Monitors active_monitors = PyInterpreterState_Get()->monitors;\n    if (code->_co_monitoring) {\n        _Py_Monitors local_monitors = code->_co_monitoring->local_monitors;\n        active_monitors = monitors_or(active_monitors, local_monitors);\n    }\n    assert(monitors_equals(\n        code->_co_monitoring->active_monitors,\n        active_monitors)\n    );\n    int code_len = (int)Py_SIZE(code);\n    for (int i = 0; i < code_len;) {\n        int opcode = _PyCode_CODE(code)[i].op.code;\n        int base_opcode = _Py_GetBaseOpcode(code, i);\n        CHECK(valid_opcode(opcode));\n        CHECK(valid_opcode(base_opcode));\n        if (opcode == INSTRUMENTED_INSTRUCTION) {\n            opcode = data->per_instruction_opcodes[i];\n            if (!is_instrumented(opcode)) {\n                CHECK(_PyOpcode_Deopt[opcode] == opcode);\n            }\n            if (data->per_instruction_tools) {\n                uint8_t tools = active_monitors.tools[PY_MONITORING_EVENT_INSTRUCTION];\n                CHECK((tools & data->per_instruction_tools[i]) == data->per_instruction_tools[i]);\n            }\n        }\n        if (opcode == INSTRUMENTED_LINE) {\n            CHECK(data->lines);\n            CHECK(valid_opcode(data->lines[i].original_opcode));\n            opcode = data->lines[i].original_opcode;\n            CHECK(opcode != END_FOR);\n            CHECK(opcode != RESUME);\n            CHECK(opcode != INSTRUMENTED_RESUME);\n            if (!is_instrumented(opcode)) {\n                CHECK(_PyOpcode_Deopt[opcode] == opcode);\n            }\n            CHECK(opcode != INSTRUMENTED_LINE);\n        }\n        else if (data->lines && !is_instrumented(opcode)) {\n            CHECK(data->lines[i].original_opcode == 0 ||\n                  data->lines[i].original_opcode == base_opcode ||\n                  DE_INSTRUMENT[data->lines[i].original_opcode] == base_opcode);\n        }\n        if (is_instrumented(opcode)) {\n            CHECK(DE_INSTRUMENT[opcode] == base_opcode);\n            int event = EVENT_FOR_OPCODE[DE_INSTRUMENT[opcode]];\n            if (event < 0) {\n                /* RESUME fixup */\n                event = _PyCode_CODE(code)[i].op.arg;\n            }\n            CHECK(active_monitors.tools[event] != 0);\n        }\n        if (data->lines && base_opcode != END_FOR) {\n            int line1 = compute_line(code, i, data->lines[i].line_delta);\n            int line2 = PyCode_Addr2Line(code, i*sizeof(_Py_CODEUNIT));\n            CHECK(line1 == line2);\n        }\n        CHECK(valid_opcode(opcode));\n        if (data->tools) {\n            uint8_t local_tools = data->tools[i];\n            if (opcode_has_event(base_opcode)) {\n                int event = EVENT_FOR_OPCODE[base_opcode];\n                if (event == -1) {\n                    /* RESUME fixup */\n                    event = _PyCode_CODE(code)[i].op.arg;\n                }\n                CHECK((active_monitors.tools[event] & local_tools) == local_tools);\n            }\n            else {\n                CHECK(local_tools == 0xff);\n            }\n        }\n        i += _PyInstruction_GetLength(code, i);\n        assert(i <= code_len);\n    }\n}\n#else\n\n#define CHECK(test) assert(test)\n\n#endif\n\n/* Get the underlying opcode, stripping instrumentation */\nint _Py_GetBaseOpcode(PyCodeObject *code, int i)\n{\n    int opcode = _PyCode_CODE(code)[i].op.code;\n    if (opcode == INSTRUMENTED_LINE) {\n        opcode = code->_co_monitoring->lines[i].original_opcode;\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        opcode = code->_co_monitoring->per_instruction_opcodes[i];\n    }\n    CHECK(opcode != INSTRUMENTED_INSTRUCTION);\n    CHECK(opcode != INSTRUMENTED_LINE);\n    int deinstrumented = DE_INSTRUMENT[opcode];\n    if (deinstrumented) {\n        return deinstrumented;\n    }\n    return _PyOpcode_Deopt[opcode];\n}\n\nstatic void\nde_instrument(PyCodeObject *code, int i, int event)\n{\n    assert(event != PY_MONITORING_EVENT_INSTRUCTION);\n    assert(event != PY_MONITORING_EVENT_LINE);\n\n    _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n    uint8_t *opcode_ptr = &instr->op.code;\n    int opcode = *opcode_ptr;\n    if (opcode == INSTRUMENTED_LINE) {\n        opcode_ptr = &code->_co_monitoring->lines[i].original_opcode;\n        opcode = *opcode_ptr;\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        opcode_ptr = &code->_co_monitoring->per_instruction_opcodes[i];\n        opcode = *opcode_ptr;\n    }\n    int deinstrumented = DE_INSTRUMENT[opcode];\n    if (deinstrumented == 0) {\n        return;\n    }\n    CHECK(_PyOpcode_Deopt[deinstrumented] == deinstrumented);\n    *opcode_ptr = deinstrumented;\n    if (_PyOpcode_Caches[deinstrumented]) {\n        instr[1].cache = adaptive_counter_warmup();\n    }\n}\n\nstatic void\nde_instrument_line(PyCodeObject *code, int i)\n{\n    _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n    uint8_t *opcode_ptr = &instr->op.code;\n    int opcode =*opcode_ptr;\n    if (opcode != INSTRUMENTED_LINE) {\n        return;\n    }\n    _PyCoLineInstrumentationData *lines = &code->_co_monitoring->lines[i];\n    int original_opcode = lines->original_opcode;\n    CHECK(original_opcode != 0);\n    CHECK(original_opcode == _PyOpcode_Deopt[original_opcode]);\n    *opcode_ptr = instr->op.code = original_opcode;\n    if (_PyOpcode_Caches[original_opcode]) {\n        instr[1].cache = adaptive_counter_warmup();\n    }\n    assert(*opcode_ptr != INSTRUMENTED_LINE);\n    assert(instr->op.code != INSTRUMENTED_LINE);\n}\n\n\nstatic void\nde_instrument_per_instruction(PyCodeObject *code, int i)\n{\n    _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n    uint8_t *opcode_ptr = &instr->op.code;\n    int opcode =*opcode_ptr;\n    if (opcode == INSTRUMENTED_LINE) {\n        opcode_ptr = &code->_co_monitoring->lines[i].original_opcode;\n        opcode = *opcode_ptr;\n    }\n    if (opcode != INSTRUMENTED_INSTRUCTION) {\n        return;\n    }\n    int original_opcode = code->_co_monitoring->per_instruction_opcodes[i];\n    CHECK(original_opcode != 0);\n    CHECK(original_opcode == _PyOpcode_Deopt[original_opcode]);\n    instr->op.code = original_opcode;\n    if (_PyOpcode_Caches[original_opcode]) {\n        instr[1].cache = adaptive_counter_warmup();\n    }\n    assert(instr->op.code != INSTRUMENTED_INSTRUCTION);\n    /* Keep things clean for sanity check */\n    code->_co_monitoring->per_instruction_opcodes[i] = 0;\n}\n\n\nstatic void\ninstrument(PyCodeObject *code, int i)\n{\n    _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n    uint8_t *opcode_ptr = &instr->op.code;\n    int opcode =*opcode_ptr;\n    if (opcode == INSTRUMENTED_LINE) {\n        _PyCoLineInstrumentationData *lines = &code->_co_monitoring->lines[i];\n        opcode_ptr = &lines->original_opcode;\n        opcode = *opcode_ptr;\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        opcode_ptr = &code->_co_monitoring->per_instruction_opcodes[i];\n        opcode = *opcode_ptr;\n        CHECK(!is_instrumented(opcode));\n        CHECK(opcode == _PyOpcode_Deopt[opcode]);\n    }\n    CHECK(opcode != 0);\n    if (!is_instrumented(opcode)) {\n        int deopt = _PyOpcode_Deopt[opcode];\n        int instrumented = INSTRUMENTED_OPCODES[deopt];\n        assert(instrumented);\n        *opcode_ptr = instrumented;\n        if (_PyOpcode_Caches[deopt]) {\n            instr[1].cache = adaptive_counter_warmup();\n        }\n    }\n}\n\nstatic void\ninstrument_line(PyCodeObject *code, int i)\n{\n    uint8_t *opcode_ptr = &_PyCode_CODE(code)[i].op.code;\n    int opcode =*opcode_ptr;\n    if (opcode == INSTRUMENTED_LINE) {\n        return;\n    }\n    _PyCoLineInstrumentationData *lines = &code->_co_monitoring->lines[i];\n    lines->original_opcode = _PyOpcode_Deopt[opcode];\n    CHECK(lines->original_opcode > 0);\n    *opcode_ptr = INSTRUMENTED_LINE;\n}\n\nstatic void\ninstrument_per_instruction(PyCodeObject *code, int i)\n{\n    _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n    uint8_t *opcode_ptr = &instr->op.code;\n    int opcode =*opcode_ptr;\n    if (opcode == INSTRUMENTED_LINE) {\n        _PyCoLineInstrumentationData *lines = &code->_co_monitoring->lines[i];\n        opcode_ptr = &lines->original_opcode;\n        opcode = *opcode_ptr;\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        return;\n    }\n    CHECK(opcode != 0);\n    if (is_instrumented(opcode)) {\n        code->_co_monitoring->per_instruction_opcodes[i] = opcode;\n    }\n    else {\n        assert(opcode != 0);\n        assert(_PyOpcode_Deopt[opcode] != 0);\n        assert(_PyOpcode_Deopt[opcode] != RESUME);\n        code->_co_monitoring->per_instruction_opcodes[i] = _PyOpcode_Deopt[opcode];\n    }\n    assert(code->_co_monitoring->per_instruction_opcodes[i] > 0);\n    *opcode_ptr = INSTRUMENTED_INSTRUCTION;\n}\n\n#ifndef NDEBUG\nstatic bool\ninstruction_has_event(PyCodeObject *code, int offset)\n{\n    _Py_CODEUNIT instr = _PyCode_CODE(code)[offset];\n    int opcode = instr.op.code;\n    if (opcode == INSTRUMENTED_LINE) {\n        opcode = code->_co_monitoring->lines[offset].original_opcode;\n    }\n    if (opcode == INSTRUMENTED_INSTRUCTION) {\n        opcode = code->_co_monitoring->per_instruction_opcodes[offset];\n    }\n    return opcode_has_event(opcode);\n}\n#endif\n\nstatic void\nremove_tools(PyCodeObject * code, int offset, int event, int tools)\n{\n    assert(event != PY_MONITORING_EVENT_LINE);\n    assert(event != PY_MONITORING_EVENT_INSTRUCTION);\n    assert(event < PY_MONITORING_INSTRUMENTED_EVENTS);\n    assert(instruction_has_event(code, offset));\n    _PyCoMonitoringData *monitoring = code->_co_monitoring;\n    if (monitoring && monitoring->tools) {\n        monitoring->tools[offset] &= ~tools;\n        if (monitoring->tools[offset] == 0) {\n            de_instrument(code, offset, event);\n        }\n    }\n    else {\n        /* Single tool */\n        uint8_t single_tool = code->_co_monitoring->active_monitors.tools[event];\n        assert(_Py_popcount32(single_tool) <= 1);\n        if (((single_tool & tools) == single_tool)) {\n            de_instrument(code, offset, event);\n        }\n    }\n}\n\n#ifndef NDEBUG\nstatic bool\ntools_is_subset_for_event(PyCodeObject * code, int event, int tools)\n{\n    int global_tools = PyInterpreterState_Get()->monitors.tools[event];\n    int local_tools = code->_co_monitoring->local_monitors.tools[event];\n    return tools == ((global_tools | local_tools) & tools);\n}\n#endif\n\nstatic void\nremove_line_tools(PyCodeObject * code, int offset, int tools)\n{\n    assert(code->_co_monitoring);\n    if (code->_co_monitoring->line_tools)\n    {\n        uint8_t *toolsptr = &code->_co_monitoring->line_tools[offset];\n        *toolsptr &= ~tools;\n        if (*toolsptr == 0 ) {\n            de_instrument_line(code, offset);\n        }\n    }\n    else {\n        /* Single tool */\n        uint8_t single_tool = code->_co_monitoring->active_monitors.tools[PY_MONITORING_EVENT_LINE];\n        assert(_Py_popcount32(single_tool) <= 1);\n        if (((single_tool & tools) == single_tool)) {\n            de_instrument_line(code, offset);\n        }\n    }\n}\n\nstatic void\nadd_tools(PyCodeObject * code, int offset, int event, int tools)\n{\n    assert(event != PY_MONITORING_EVENT_LINE);\n    assert(event != PY_MONITORING_EVENT_INSTRUCTION);\n    assert(event < PY_MONITORING_INSTRUMENTED_EVENTS);\n    assert(code->_co_monitoring);\n    if (code->_co_monitoring &&\n        code->_co_monitoring->tools\n    ) {\n        code->_co_monitoring->tools[offset] |= tools;\n    }\n    else {\n        /* Single tool */\n        assert(_Py_popcount32(tools) == 1);\n        assert(tools_is_subset_for_event(code, event, tools));\n    }\n    instrument(code, offset);\n}\n\nstatic void\nadd_line_tools(PyCodeObject * code, int offset, int tools)\n{\n    assert(tools_is_subset_for_event(code, PY_MONITORING_EVENT_LINE, tools));\n    assert(code->_co_monitoring);\n    if (code->_co_monitoring->line_tools) {\n        code->_co_monitoring->line_tools[offset] |= tools;\n    }\n    else {\n        /* Single tool */\n        assert(_Py_popcount32(tools) == 1);\n    }\n    instrument_line(code, offset);\n}\n\n\nstatic void\nadd_per_instruction_tools(PyCodeObject * code, int offset, int tools)\n{\n    assert(tools_is_subset_for_event(code, PY_MONITORING_EVENT_INSTRUCTION, tools));\n    assert(code->_co_monitoring);\n    if (code->_co_monitoring->per_instruction_tools) {\n        code->_co_monitoring->per_instruction_tools[offset] |= tools;\n    }\n    else {\n        /* Single tool */\n        assert(_Py_popcount32(tools) == 1);\n    }\n    instrument_per_instruction(code, offset);\n}\n\n\nstatic void\nremove_per_instruction_tools(PyCodeObject * code, int offset, int tools)\n{\n    assert(code->_co_monitoring);\n    if (code->_co_monitoring->per_instruction_tools) {\n        uint8_t *toolsptr = &code->_co_monitoring->per_instruction_tools[offset];\n        *toolsptr &= ~tools;\n        if (*toolsptr == 0) {\n            de_instrument_per_instruction(code, offset);\n        }\n    }\n    else {\n        /* Single tool */\n        uint8_t single_tool = code->_co_monitoring->active_monitors.tools[PY_MONITORING_EVENT_INSTRUCTION];\n        assert(_Py_popcount32(single_tool) <= 1);\n        if (((single_tool & tools) == single_tool)) {\n            de_instrument_per_instruction(code, offset);\n        }\n    }\n}\n\n\n/* Return 1 if DISABLE returned, -1 if error, 0 otherwise */\nstatic int\ncall_one_instrument(\n    PyInterpreterState *interp, PyThreadState *tstate, PyObject **args,\n    Py_ssize_t nargsf, int8_t tool, int event)\n{\n    assert(0 <= tool && tool < 8);\n    assert(tstate->tracing == 0);\n    PyObject *instrument = interp->monitoring_callables[tool][event];\n    if (instrument == NULL) {\n        return 0;\n    }\n    int old_what = tstate->what_event;\n    tstate->what_event = event;\n    tstate->tracing++;\n    PyObject *res = _PyObject_VectorcallTstate(tstate, instrument, args, nargsf, NULL);\n    tstate->tracing--;\n    tstate->what_event = old_what;\n    if (res == NULL) {\n        return -1;\n    }\n    Py_DECREF(res);\n    return (res == &_PyInstrumentation_DISABLE);\n}\n\nstatic const int8_t MOST_SIGNIFICANT_BITS[16] = {\n    -1, 0, 1, 1,\n    2, 2, 2, 2,\n    3, 3, 3, 3,\n    3, 3, 3, 3,\n};\n\n/* We could use _Py_bit_length here, but that is designed for larger (32/64)\n * bit ints, and can perform relatively poorly on platforms without the\n * necessary intrinsics. */\nstatic inline int most_significant_bit(uint8_t bits) {\n    assert(bits != 0);\n    if (bits > 15) {\n        return MOST_SIGNIFICANT_BITS[bits>>4]+4;\n    }\n    return MOST_SIGNIFICANT_BITS[bits];\n}\n\nstatic bool\nis_version_up_to_date(PyCodeObject *code, PyInterpreterState *interp)\n{\n    return interp->monitoring_version == code->_co_instrumentation_version;\n}\n\n#ifndef NDEBUG\nstatic bool\ninstrumentation_cross_checks(PyInterpreterState *interp, PyCodeObject *code)\n{\n    _Py_Monitors expected = monitors_or(\n        interp->monitors,\n        code->_co_monitoring->local_monitors);\n    return monitors_equals(code->_co_monitoring->active_monitors, expected);\n}\n#endif\n\nstatic inline uint8_t\nget_tools_for_instruction(PyCodeObject * code, int i, int event)\n{\n    uint8_t tools;\n    assert(event != PY_MONITORING_EVENT_LINE);\n    assert(event != PY_MONITORING_EVENT_INSTRUCTION);\n    assert(instrumentation_cross_checks(PyThreadState_GET()->interp, code));\n    _PyCoMonitoringData *monitoring = code->_co_monitoring;\n    if (event >= PY_MONITORING_UNGROUPED_EVENTS) {\n        assert(event == PY_MONITORING_EVENT_C_RAISE ||\n                event == PY_MONITORING_EVENT_C_RETURN);\n        event = PY_MONITORING_EVENT_CALL;\n    }\n    if (event < PY_MONITORING_INSTRUMENTED_EVENTS && monitoring->tools) {\n        tools = monitoring->tools[i];\n    }\n    else {\n        tools = code->_co_monitoring->active_monitors.tools[event];\n    }\n    CHECK(tools_is_subset_for_event(code, event, tools));\n    CHECK((tools & code->_co_monitoring->active_monitors.tools[event]) == tools);\n    return tools;\n}\n\nstatic int\ncall_instrumentation_vector(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, Py_ssize_t nargs, PyObject *args[])\n{\n    if (tstate->tracing) {\n        return 0;\n    }\n    assert(!_PyErr_Occurred(tstate));\n    assert(args[0] == NULL);\n    PyCodeObject *code = frame->f_code;\n    assert(code->_co_instrumentation_version == tstate->interp->monitoring_version);\n    assert(is_version_up_to_date(code, tstate->interp));\n    assert(instrumentation_cross_checks(tstate->interp, code));\n    assert(args[1] == NULL);\n    args[1] = (PyObject *)code;\n    int offset = (int)(instr - _PyCode_CODE(code));\n    /* Offset visible to user should be the offset in bytes, as that is the\n     * convention for APIs involving code offsets. */\n    int bytes_offset = offset * (int)sizeof(_Py_CODEUNIT);\n    PyObject *offset_obj = PyLong_FromSsize_t(bytes_offset);\n    if (offset_obj == NULL) {\n        return -1;\n    }\n    assert(args[2] == NULL);\n    args[2] = offset_obj;\n    uint8_t tools = get_tools_for_instruction(code, offset, event);\n    Py_ssize_t nargsf = nargs | PY_VECTORCALL_ARGUMENTS_OFFSET;\n    PyObject **callargs = &args[1];\n    int err = 0;\n    PyInterpreterState *interp = tstate->interp;\n    while (tools) {\n        int tool = most_significant_bit(tools);\n        assert(tool >= 0 && tool < 8);\n        assert(tools & (1 << tool));\n        tools ^= (1 << tool);\n        int res = call_one_instrument(interp, tstate, callargs, nargsf, tool, event);\n        if (res == 0) {\n            /* Nothing to do */\n        }\n        else if (res < 0) {\n            /* error */\n            err = -1;\n            break;\n        }\n        else {\n            /* DISABLE */\n            remove_tools(code, offset, event, 1 << tool);\n        }\n    }\n    Py_DECREF(offset_obj);\n    return err;\n}\n\nint\n_Py_call_instrumentation(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr)\n{\n    PyObject *args[3] = { NULL, NULL, NULL };\n    return call_instrumentation_vector(tstate, event, frame, instr, 2, args);\n}\n\nint\n_Py_call_instrumentation_arg(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg)\n{\n    PyObject *args[4] = { NULL, NULL, NULL, arg };\n    return call_instrumentation_vector(tstate, event, frame, instr, 3, args);\n}\n\nint\n_Py_call_instrumentation_2args(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1)\n{\n    PyObject *args[5] = { NULL, NULL, NULL, arg0, arg1 };\n    return call_instrumentation_vector(tstate, event, frame, instr, 4, args);\n}\n\n_Py_CODEUNIT *\n_Py_call_instrumentation_jump(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *target)\n{\n    assert(event == PY_MONITORING_EVENT_JUMP ||\n           event == PY_MONITORING_EVENT_BRANCH);\n    assert(frame->prev_instr == instr);\n    /* Event should occur after the jump */\n    frame->prev_instr = target;\n    PyCodeObject *code = frame->f_code;\n    int to = (int)(target - _PyCode_CODE(code));\n    PyObject *to_obj = PyLong_FromLong(to * (int)sizeof(_Py_CODEUNIT));\n    if (to_obj == NULL) {\n        return NULL;\n    }\n    PyObject *args[4] = { NULL, NULL, NULL, to_obj };\n    int err = call_instrumentation_vector(tstate, event, frame, instr, 3, args);\n    Py_DECREF(to_obj);\n    if (err) {\n        return NULL;\n    }\n    if (frame->prev_instr != target) {\n        /* The callback has caused a jump (by setting the line number) */\n        return frame->prev_instr;\n    }\n    /* Reset prev_instr for INSTRUMENTED_LINE */\n    frame->prev_instr = instr;\n    return target;\n}\n\nstatic void\ncall_instrumentation_vector_protected(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, Py_ssize_t nargs, PyObject *args[])\n{\n    assert(_PyErr_Occurred(tstate));\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    int err = call_instrumentation_vector(tstate, event, frame, instr, nargs, args);\n    if (err) {\n        Py_XDECREF(exc);\n    }\n    else {\n        _PyErr_SetRaisedException(tstate, exc);\n    }\n    assert(_PyErr_Occurred(tstate));\n}\n\nvoid\n_Py_call_instrumentation_exc0(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr)\n{\n    assert(_PyErr_Occurred(tstate));\n    PyObject *args[3] = { NULL, NULL, NULL };\n    call_instrumentation_vector_protected(tstate, event, frame, instr, 2, args);\n}\n\nvoid\n_Py_call_instrumentation_exc2(\n    PyThreadState *tstate, int event,\n    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1)\n{\n    assert(_PyErr_Occurred(tstate));\n    PyObject *args[5] = { NULL, NULL, NULL, arg0, arg1 };\n    call_instrumentation_vector_protected(tstate, event, frame, instr, 4, args);\n}\n\n\nint\n_Py_Instrumentation_GetLine(PyCodeObject *code, int index)\n{\n    _PyCoMonitoringData *monitoring = code->_co_monitoring;\n    assert(monitoring != NULL);\n    assert(monitoring->lines != NULL);\n    assert(index >= code->_co_firsttraceable);\n    assert(index < Py_SIZE(code));\n    _PyCoLineInstrumentationData *line_data = &monitoring->lines[index];\n    int8_t line_delta = line_data->line_delta;\n    int line = compute_line(code, index, line_delta);\n    return line;\n}\n\nint\n_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *prev)\n{\n    frame->prev_instr = instr;\n    PyCodeObject *code = frame->f_code;\n    assert(is_version_up_to_date(code, tstate->interp));\n    assert(instrumentation_cross_checks(tstate->interp, code));\n    int i = (int)(instr - _PyCode_CODE(code));\n\n    _PyCoMonitoringData *monitoring = code->_co_monitoring;\n    _PyCoLineInstrumentationData *line_data = &monitoring->lines[i];\n    uint8_t original_opcode = line_data->original_opcode;\n    if (tstate->tracing) {\n        goto done;\n    }\n    PyInterpreterState *interp = tstate->interp;\n    int8_t line_delta = line_data->line_delta;\n    int line = compute_line(code, i, line_delta);\n    assert(line >= 0);\n    int prev_index = (int)(prev - _PyCode_CODE(code));\n    int prev_line = _Py_Instrumentation_GetLine(code, prev_index);\n    if (prev_line == line) {\n        int prev_opcode = _PyCode_CODE(code)[prev_index].op.code;\n        /* RESUME and INSTRUMENTED_RESUME are needed for the operation of\n         * instrumentation, so must never be hidden by an INSTRUMENTED_LINE.\n         */\n        if (prev_opcode != RESUME && prev_opcode != INSTRUMENTED_RESUME) {\n            goto done;\n        }\n    }\n    uint8_t tools = code->_co_monitoring->line_tools != NULL ?\n        code->_co_monitoring->line_tools[i] :\n        (interp->monitors.tools[PY_MONITORING_EVENT_LINE] |\n         code->_co_monitoring->local_monitors.tools[PY_MONITORING_EVENT_LINE]\n        );\n    PyObject *line_obj = PyLong_FromSsize_t(line);\n    if (line_obj == NULL) {\n        return -1;\n    }\n    PyObject *args[3] = { NULL, (PyObject *)code, line_obj };\n    while (tools) {\n        int tool = most_significant_bit(tools);\n        assert(tool >= 0 && tool < 8);\n        assert(tools & (1 << tool));\n        tools &= ~(1 << tool);\n        int res = call_one_instrument(interp, tstate, &args[1],\n                                      2 | PY_VECTORCALL_ARGUMENTS_OFFSET,\n                                      tool, PY_MONITORING_EVENT_LINE);\n        if (res == 0) {\n            /* Nothing to do */\n        }\n        else if (res < 0) {\n            /* error */\n            Py_DECREF(line_obj);\n            return -1;\n        }\n        else {\n            /* DISABLE  */\n            remove_line_tools(code, i, 1 << tool);\n        }\n    }\n    Py_DECREF(line_obj);\ndone:\n    assert(original_opcode != 0);\n    assert(original_opcode < INSTRUMENTED_LINE);\n    assert(_PyOpcode_Deopt[original_opcode] == original_opcode);\n    return original_opcode;\n}\n\nint\n_Py_call_instrumentation_instruction(PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr)\n{\n    PyCodeObject *code = frame->f_code;\n    assert(is_version_up_to_date(code, tstate->interp));\n    assert(instrumentation_cross_checks(tstate->interp, code));\n    int offset = (int)(instr - _PyCode_CODE(code));\n    _PyCoMonitoringData *instrumentation_data = code->_co_monitoring;\n    assert(instrumentation_data->per_instruction_opcodes);\n    int next_opcode = instrumentation_data->per_instruction_opcodes[offset];\n    if (tstate->tracing) {\n        return next_opcode;\n    }\n    PyInterpreterState *interp = tstate->interp;\n    uint8_t tools = instrumentation_data->per_instruction_tools != NULL ?\n        instrumentation_data->per_instruction_tools[offset] :\n        (interp->monitors.tools[PY_MONITORING_EVENT_INSTRUCTION] |\n         code->_co_monitoring->local_monitors.tools[PY_MONITORING_EVENT_INSTRUCTION]\n        );\n    int bytes_offset = offset * (int)sizeof(_Py_CODEUNIT);\n    PyObject *offset_obj = PyLong_FromSsize_t(bytes_offset);\n    if (offset_obj == NULL) {\n        return -1;\n    }\n    PyObject *args[3] = { NULL, (PyObject *)code, offset_obj };\n    while (tools) {\n        int tool = most_significant_bit(tools);\n        assert(tool >= 0 && tool < 8);\n        assert(tools & (1 << tool));\n        tools &= ~(1 << tool);\n        int res = call_one_instrument(interp, tstate, &args[1],\n                                      2 | PY_VECTORCALL_ARGUMENTS_OFFSET,\n                                      tool, PY_MONITORING_EVENT_INSTRUCTION);\n        if (res == 0) {\n            /* Nothing to do */\n        }\n        else if (res < 0) {\n            /* error */\n            Py_DECREF(offset_obj);\n            return -1;\n        }\n        else {\n            /* DISABLE  */\n            remove_per_instruction_tools(code, offset, 1 << tool);\n        }\n    }\n    Py_DECREF(offset_obj);\n    assert(next_opcode != 0);\n    return next_opcode;\n}\n\n\nPyObject *\n_PyMonitoring_RegisterCallback(int tool_id, int event_id, PyObject *obj)\n{\n    PyInterpreterState *is = _PyInterpreterState_Get();\n    assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);\n    assert(0 <= event_id && event_id < PY_MONITORING_EVENTS);\n    PyObject *callback = is->monitoring_callables[tool_id][event_id];\n    is->monitoring_callables[tool_id][event_id] = Py_XNewRef(obj);\n    return callback;\n}\n\nstatic void\ninitialize_tools(PyCodeObject *code)\n{\n    uint8_t* tools = code->_co_monitoring->tools;\n    assert(tools != NULL);\n    int code_len = (int)Py_SIZE(code);\n    for (int i = 0; i < code_len; i++) {\n        _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n        int opcode = instr->op.code;\n        if (opcode == INSTRUMENTED_LINE) {\n            opcode = code->_co_monitoring->lines[i].original_opcode;\n        }\n        bool instrumented = is_instrumented(opcode);\n        if (instrumented) {\n            opcode = DE_INSTRUMENT[opcode];\n            assert(opcode != 0);\n        }\n        opcode = _PyOpcode_Deopt[opcode];\n        if (opcode_has_event(opcode)) {\n            if (instrumented) {\n                int8_t event;\n                if (opcode == RESUME) {\n                    event = instr->op.arg != 0;\n                }\n                else {\n                    event = EVENT_FOR_OPCODE[opcode];\n                    assert(event > 0);\n                }\n                assert(event >= 0);\n                assert(event < PY_MONITORING_INSTRUMENTED_EVENTS);\n                tools[i] = code->_co_monitoring->active_monitors.tools[event];\n                CHECK(tools[i] != 0);\n            }\n            else {\n                tools[i] = 0;\n            }\n        }\n#ifdef Py_DEBUG\n        /* Initialize tools for invalid locations to all ones to try to catch errors */\n        else {\n            tools[i] = 0xff;\n        }\n        for (int j = 1; j <= _PyOpcode_Caches[opcode]; j++) {\n            tools[i+j] = 0xff;\n        }\n#endif\n        i += _PyOpcode_Caches[opcode];\n    }\n}\n\n#define NO_LINE -128\n\nstatic void\ninitialize_lines(PyCodeObject *code)\n{\n    _PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines;\n    assert(line_data != NULL);\n    int code_len = (int)Py_SIZE(code);\n    PyCodeAddressRange range;\n    _PyCode_InitAddressRange(code, &range);\n    for (int i = 0; i < code->_co_firsttraceable && i < code_len; i++) {\n        line_data[i].original_opcode = 0;\n        line_data[i].line_delta = -127;\n    }\n    int current_line = -1;\n    for (int i = code->_co_firsttraceable; i < code_len; ) {\n        int opcode = _Py_GetBaseOpcode(code, i);\n        int line = _PyCode_CheckLineNumber(i*(int)sizeof(_Py_CODEUNIT), &range);\n        line_data[i].line_delta = compute_line_delta(code, i, line);\n        int length = _PyInstruction_GetLength(code, i);\n        switch (opcode) {\n            case END_ASYNC_FOR:\n            case END_FOR:\n            case END_SEND:\n            case RESUME:\n                /* END_FOR cannot start a line, as it is skipped by FOR_ITER\n                 * END_SEND cannot start a line, as it is skipped by SEND\n                 * RESUME must not be instrumented with INSTRUMENT_LINE */\n                line_data[i].original_opcode = 0;\n                break;\n            default:\n                /* Set original_opcode to the opcode iff the instruction\n                 * starts a line, and thus should be instrumented.\n                 * This saves having to perform this check every time the\n                 * we turn instrumentation on or off, and serves as a sanity\n                 * check when debugging.\n                 */\n                if (line != current_line && line >= 0) {\n                    line_data[i].original_opcode = opcode;\n                }\n                else {\n                    line_data[i].original_opcode = 0;\n                }\n                current_line = line;\n        }\n        for (int j = 1; j < length; j++) {\n            line_data[i+j].original_opcode = 0;\n            line_data[i+j].line_delta = NO_LINE;\n        }\n        i += length;\n    }\n    for (int i = code->_co_firsttraceable; i < code_len; ) {\n        int opcode = _Py_GetBaseOpcode(code, i);\n        int oparg = 0;\n        while (opcode == EXTENDED_ARG) {\n            oparg = (oparg << 8) | _PyCode_CODE(code)[i].op.arg;\n            i++;\n            opcode = _Py_GetBaseOpcode(code, i);\n        }\n        oparg = (oparg << 8) | _PyCode_CODE(code)[i].op.arg;\n        i += _PyInstruction_GetLength(code, i);\n        int target = -1;\n        switch (opcode) {\n            case POP_JUMP_IF_FALSE:\n            case POP_JUMP_IF_TRUE:\n            case POP_JUMP_IF_NONE:\n            case POP_JUMP_IF_NOT_NONE:\n            case JUMP_FORWARD:\n            {\n                target = i + oparg;\n                break;\n            }\n            case FOR_ITER:\n            case SEND:\n            {\n                /* Skip over END_FOR/END_SEND */\n                target = i + oparg + 1;\n                break;\n            }\n            case JUMP_BACKWARD:\n            case JUMP_BACKWARD_NO_INTERRUPT:\n            {\n                target = i - oparg;\n                break;\n            }\n            default:\n                continue;\n        }\n        assert(target >= 0);\n        if (line_data[target].line_delta != NO_LINE) {\n            line_data[target].original_opcode = _Py_GetBaseOpcode(code, target);\n        }\n    }\n    /* Scan exception table */\n    unsigned char *start = (unsigned char *)PyBytes_AS_STRING(code->co_exceptiontable);\n    unsigned char *end = start + PyBytes_GET_SIZE(code->co_exceptiontable);\n    unsigned char *scan = start;\n    while (scan < end) {\n        int start_offset, size, handler;\n        scan = parse_varint(scan, &start_offset);\n        assert(start_offset >= 0 && start_offset < code_len);\n        scan = parse_varint(scan, &size);\n        assert(size >= 0 && start_offset+size <= code_len);\n        scan = parse_varint(scan, &handler);\n        assert(handler >= 0 && handler < code_len);\n        int depth_and_lasti;\n        scan = parse_varint(scan, &depth_and_lasti);\n        int original_opcode = _Py_GetBaseOpcode(code, handler);\n        /* Skip if not the start of a line.\n         * END_ASYNC_FOR is a bit special as it marks the end of\n         * an `async for` loop, which should not generate its own\n         * line event. */\n        if (line_data[handler].line_delta != NO_LINE &&\n            original_opcode != END_ASYNC_FOR) {\n            line_data[handler].original_opcode = original_opcode;\n        }\n    }\n}\n\nstatic void\ninitialize_line_tools(PyCodeObject *code, _Py_Monitors *all_events)\n{\n    uint8_t *line_tools = code->_co_monitoring->line_tools;\n    assert(line_tools != NULL);\n    int code_len = (int)Py_SIZE(code);\n    for (int i = 0; i < code_len; i++) {\n        line_tools[i] = all_events->tools[PY_MONITORING_EVENT_LINE];\n    }\n}\n\nstatic int\nallocate_instrumentation_data(PyCodeObject *code)\n{\n\n    if (code->_co_monitoring == NULL) {\n        code->_co_monitoring = PyMem_Malloc(sizeof(_PyCoMonitoringData));\n        if (code->_co_monitoring == NULL) {\n            PyErr_NoMemory();\n            return -1;\n        }\n        code->_co_monitoring->local_monitors = (_Py_Monitors){ 0 };\n        code->_co_monitoring->active_monitors = (_Py_Monitors){ 0 };\n        code->_co_monitoring->tools = NULL;\n        code->_co_monitoring->lines = NULL;\n        code->_co_monitoring->line_tools = NULL;\n        code->_co_monitoring->per_instruction_opcodes = NULL;\n        code->_co_monitoring->per_instruction_tools = NULL;\n    }\n    return 0;\n}\n\nstatic int\nupdate_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp)\n{\n    int code_len = (int)Py_SIZE(code);\n    if (allocate_instrumentation_data(code)) {\n        return -1;\n    }\n    _Py_Monitors all_events = monitors_or(\n        interp->monitors,\n        code->_co_monitoring->local_monitors);\n    bool multitools = multiple_tools(&all_events);\n    if (code->_co_monitoring->tools == NULL && multitools) {\n        code->_co_monitoring->tools = PyMem_Malloc(code_len);\n        if (code->_co_monitoring->tools == NULL) {\n            PyErr_NoMemory();\n            return -1;\n        }\n        initialize_tools(code);\n    }\n    if (all_events.tools[PY_MONITORING_EVENT_LINE]) {\n        if (code->_co_monitoring->lines == NULL) {\n            code->_co_monitoring->lines = PyMem_Malloc(code_len * sizeof(_PyCoLineInstrumentationData));\n            if (code->_co_monitoring->lines == NULL) {\n                PyErr_NoMemory();\n                return -1;\n            }\n            initialize_lines(code);\n        }\n        if (multitools && code->_co_monitoring->line_tools == NULL) {\n            code->_co_monitoring->line_tools = PyMem_Malloc(code_len);\n            if (code->_co_monitoring->line_tools == NULL) {\n                PyErr_NoMemory();\n                return -1;\n            }\n            initialize_line_tools(code, &all_events);\n        }\n    }\n    if (all_events.tools[PY_MONITORING_EVENT_INSTRUCTION]) {\n        if (code->_co_monitoring->per_instruction_opcodes == NULL) {\n            code->_co_monitoring->per_instruction_opcodes = PyMem_Malloc(code_len * sizeof(_PyCoLineInstrumentationData));\n            if (code->_co_monitoring->per_instruction_opcodes == NULL) {\n                PyErr_NoMemory();\n                return -1;\n            }\n            /* This may not be necessary, as we can initialize this memory lazily, but it helps catch errors. */\n            for (int i = 0; i < code_len; i++) {\n                code->_co_monitoring->per_instruction_opcodes[i] = 0;\n            }\n        }\n        if (multitools && code->_co_monitoring->per_instruction_tools == NULL) {\n            code->_co_monitoring->per_instruction_tools = PyMem_Malloc(code_len);\n            if (code->_co_monitoring->per_instruction_tools == NULL) {\n                PyErr_NoMemory();\n                return -1;\n            }\n            /* This may not be necessary, as we can initialize this memory lazily, but it helps catch errors. */\n            for (int i = 0; i < code_len; i++) {\n                code->_co_monitoring->per_instruction_tools[i] = 0;\n            }\n        }\n    }\n    return 0;\n}\n\nstatic const uint8_t super_instructions[256] = {\n    [LOAD_FAST__LOAD_CONST] = 1,\n    [LOAD_CONST__LOAD_FAST] = 1,\n};\n\n/* Should use instruction metadata for this */\nstatic bool\nis_super_instruction(uint8_t opcode) {\n    return super_instructions[opcode] != 0;\n}\n\nint\n_Py_Instrument(PyCodeObject *code, PyInterpreterState *interp)\n{\n    if (is_version_up_to_date(code, interp)) {\n        assert(\n            interp->monitoring_version == 0 ||\n            instrumentation_cross_checks(interp, code)\n        );\n        return 0;\n    }\n    int code_len = (int)Py_SIZE(code);\n    if (update_instrumentation_data(code, interp)) {\n        return -1;\n    }\n    _Py_Monitors active_events = monitors_or(\n        interp->monitors,\n        code->_co_monitoring->local_monitors);\n    _Py_Monitors new_events;\n    _Py_Monitors removed_events;\n\n    bool restarted = interp->last_restart_version > code->_co_instrumentation_version;\n    if (restarted) {\n        removed_events = code->_co_monitoring->active_monitors;\n        new_events = active_events;\n    }\n    else {\n        removed_events = monitors_sub(code->_co_monitoring->active_monitors, active_events);\n        new_events = monitors_sub(active_events, code->_co_monitoring->active_monitors);\n        assert(monitors_are_empty(monitors_and(new_events, removed_events)));\n    }\n    code->_co_monitoring->active_monitors = active_events;\n    code->_co_instrumentation_version = interp->monitoring_version;\n    if (monitors_are_empty(new_events) && monitors_are_empty(removed_events)) {\n#ifdef INSTRUMENT_DEBUG\n        sanity_check_instrumentation(code);\n#endif\n        return 0;\n    }\n    /* Insert instrumentation */\n    for (int i = 0; i < code_len; i+= _PyInstruction_GetLength(code, i)) {\n        _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];\n        if (is_super_instruction(instr->op.code)) {\n            instr->op.code = _PyOpcode_Deopt[instr->op.code];\n        }\n        CHECK(instr->op.code != 0);\n        int base_opcode = _Py_GetBaseOpcode(code, i);\n        if (opcode_has_event(base_opcode)) {\n            int8_t event;\n            if (base_opcode == RESUME) {\n                event = instr->op.arg > 0;\n            }\n            else {\n                event = EVENT_FOR_OPCODE[base_opcode];\n                assert(event > 0);\n            }\n            uint8_t removed_tools = removed_events.tools[event];\n            if (removed_tools) {\n                remove_tools(code, i, event, removed_tools);\n            }\n            uint8_t new_tools = new_events.tools[event];\n            if (new_tools) {\n                add_tools(code, i, event, new_tools);\n            }\n        }\n    }\n\n    // GH-103845: We need to remove both the line and instruction instrumentation before\n    // adding new ones, otherwise we may remove the newly added instrumentation.\n\n    uint8_t removed_line_tools = removed_events.tools[PY_MONITORING_EVENT_LINE];\n    uint8_t removed_per_instruction_tools = removed_events.tools[PY_MONITORING_EVENT_INSTRUCTION];\n\n    if (removed_line_tools) {\n        _PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines;\n        for (int i = code->_co_firsttraceable; i < code_len;) {\n            if (line_data[i].original_opcode) {\n                if (removed_line_tools) {\n                    remove_line_tools(code, i, removed_line_tools);\n                }\n            }\n            i += _PyInstruction_GetLength(code, i);\n        }\n    }\n    if (removed_per_instruction_tools) {\n        for (int i = code->_co_firsttraceable; i < code_len;) {\n            int opcode = _Py_GetBaseOpcode(code, i);\n            if (opcode == RESUME || opcode == END_FOR) {\n                i += _PyInstruction_GetLength(code, i);\n                continue;\n            }\n            if (removed_per_instruction_tools) {\n                remove_per_instruction_tools(code, i, removed_per_instruction_tools);\n            }\n            i += _PyInstruction_GetLength(code, i);\n        }\n    }\n\n    uint8_t new_line_tools = new_events.tools[PY_MONITORING_EVENT_LINE];\n    uint8_t new_per_instruction_tools = new_events.tools[PY_MONITORING_EVENT_INSTRUCTION];\n\n    if (new_line_tools) {\n        _PyCoLineInstrumentationData *line_data = code->_co_monitoring->lines;\n        for (int i = code->_co_firsttraceable; i < code_len;) {\n            if (line_data[i].original_opcode) {\n                if (new_line_tools) {\n                    add_line_tools(code, i, new_line_tools);\n                }\n            }\n            i += _PyInstruction_GetLength(code, i);\n        }\n    }\n    if (new_per_instruction_tools) {\n        for (int i = code->_co_firsttraceable; i < code_len;) {\n            int opcode = _Py_GetBaseOpcode(code, i);\n            if (opcode == RESUME || opcode == END_FOR) {\n                i += _PyInstruction_GetLength(code, i);\n                continue;\n            }\n            if (new_per_instruction_tools) {\n                add_per_instruction_tools(code, i, new_per_instruction_tools);\n            }\n            i += _PyInstruction_GetLength(code, i);\n        }\n    }\n#ifdef INSTRUMENT_DEBUG\n    sanity_check_instrumentation(code);\n#endif\n    return 0;\n}\n\n#define C_RETURN_EVENTS \\\n    ((1 << PY_MONITORING_EVENT_C_RETURN) | \\\n     (1 << PY_MONITORING_EVENT_C_RAISE))\n\n#define C_CALL_EVENTS \\\n    (C_RETURN_EVENTS | (1 << PY_MONITORING_EVENT_CALL))\n\n\nstatic int\ninstrument_all_executing_code_objects(PyInterpreterState *interp) {\n    _PyRuntimeState *runtime = &_PyRuntime;\n    HEAD_LOCK(runtime);\n    PyThreadState* ts = PyInterpreterState_ThreadHead(interp);\n    HEAD_UNLOCK(runtime);\n    while (ts) {\n        _PyInterpreterFrame *frame = ts->cframe->current_frame;\n        while (frame) {\n            if (frame->owner != FRAME_OWNED_BY_CSTACK) {\n                if (_Py_Instrument(frame->f_code, interp)) {\n                    return -1;\n                }\n            }\n            frame = frame->previous;\n        }\n        HEAD_LOCK(runtime);\n        ts = PyThreadState_Next(ts);\n        HEAD_UNLOCK(runtime);\n    }\n    return 0;\n}\n\nstatic void\nset_events(_Py_Monitors *m, int tool_id, _PyMonitoringEventSet events)\n{\n    assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);\n    for (int e = 0; e < PY_MONITORING_UNGROUPED_EVENTS; e++) {\n        uint8_t *tools = &m->tools[e];\n        int val = (events >> e) & 1;\n        *tools &= ~(1 << tool_id);\n        *tools |= (val << tool_id);\n    }\n}\n\nstatic int\ncheck_tool(PyInterpreterState *interp, int tool_id)\n{\n    if (tool_id < PY_MONITORING_SYS_PROFILE_ID &&\n        interp->monitoring_tool_names[tool_id] == NULL)\n    {\n        PyErr_Format(PyExc_ValueError, \"tool %d is not in use\", tool_id);\n        return -1;\n    }\n    return 0;\n}\n\nint\n_PyMonitoring_SetEvents(int tool_id, _PyMonitoringEventSet events)\n{\n    assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    assert(events < (1 << PY_MONITORING_UNGROUPED_EVENTS));\n    if (check_tool(interp, tool_id)) {\n        return -1;\n    }\n    uint32_t existing_events = get_events(&interp->monitors, tool_id);\n    if (existing_events == events) {\n        return 0;\n    }\n    set_events(&interp->monitors, tool_id, events);\n    interp->monitoring_version++;\n    return instrument_all_executing_code_objects(interp);\n}\n\nint\n_PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEventSet events)\n{\n    assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS);\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    assert(events < (1 << PY_MONITORING_UNGROUPED_EVENTS));\n    if (check_tool(interp, tool_id)) {\n        return -1;\n    }\n    if (allocate_instrumentation_data(code)) {\n        return -1;\n    }\n    _Py_Monitors *local = &code->_co_monitoring->local_monitors;\n    uint32_t existing_events = get_events(local, tool_id);\n    if (existing_events == events) {\n        return 0;\n    }\n    set_events(local, tool_id, events);\n    if (is_version_up_to_date(code, interp)) {\n        /* Force instrumentation update */\n        code->_co_instrumentation_version = UINT64_MAX;\n    }\n    if (_Py_Instrument(code, interp)) {\n        return -1;\n    }\n    return 0;\n}\n\n/*[clinic input]\nmodule monitoring\n[clinic start generated code]*/\n/*[clinic end generated code: output=da39a3ee5e6b4b0d input=37257f5987a360cf]*/\n/*[clinic end generated code]*/\n\n#include \"clinic/instrumentation.c.h\"\n\nstatic int\ncheck_valid_tool(int tool_id)\n{\n    if (tool_id < 0 || tool_id >= PY_MONITORING_SYS_PROFILE_ID) {\n        PyErr_Format(PyExc_ValueError, \"invalid tool %d (must be between 0 and 5)\", tool_id);\n        return -1;\n    }\n    return 0;\n}\n\n/*[clinic input]\nmonitoring.use_tool_id\n\n    tool_id: int\n    name: object\n    /\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_use_tool_id_impl(PyObject *module, int tool_id, PyObject *name)\n/*[clinic end generated code: output=30d76dc92b7cd653 input=ebc453761c621be1]*/\n{\n    if (check_valid_tool(tool_id))  {\n        return NULL;\n    }\n    if (!PyUnicode_Check(name)) {\n        PyErr_SetString(PyExc_ValueError, \"tool name must be a str\");\n        return NULL;\n    }\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    if (interp->monitoring_tool_names[tool_id] != NULL) {\n        PyErr_Format(PyExc_ValueError, \"tool %d is already in use\", tool_id);\n        return NULL;\n    }\n    interp->monitoring_tool_names[tool_id] = Py_NewRef(name);\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nmonitoring.free_tool_id\n\n    tool_id: int\n    /\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_free_tool_id_impl(PyObject *module, int tool_id)\n/*[clinic end generated code: output=86c2d2a1219a8591 input=a23fb6be3a8618e9]*/\n{\n    if (check_valid_tool(tool_id))  {\n        return NULL;\n    }\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    Py_CLEAR(interp->monitoring_tool_names[tool_id]);\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nmonitoring.get_tool\n\n    tool_id: int\n    /\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_get_tool_impl(PyObject *module, int tool_id)\n/*[clinic end generated code: output=1c05a98b404a9a16 input=eeee9bebd0bcae9d]*/\n\n/*[clinic end generated code]*/\n{\n    if (check_valid_tool(tool_id))  {\n        return NULL;\n    }\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    PyObject *name = interp->monitoring_tool_names[tool_id];\n    if (name == NULL) {\n        Py_RETURN_NONE;\n    }\n    return Py_NewRef(name);\n}\n\n/*[clinic input]\nmonitoring.register_callback\n\n\n    tool_id: int\n    event: int\n    func: object\n    /\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_register_callback_impl(PyObject *module, int tool_id, int event,\n                                  PyObject *func)\n/*[clinic end generated code: output=e64daa363004030c input=df6d70ea4cf81007]*/\n{\n    if (check_valid_tool(tool_id))  {\n        return NULL;\n    }\n    if (_Py_popcount32(event) != 1) {\n        PyErr_SetString(PyExc_ValueError, \"The callback can only be set for one event at a time\");\n        return NULL;\n    }\n    int event_id = _Py_bit_length(event)-1;\n    if (event_id < 0 || event_id >= PY_MONITORING_EVENTS) {\n        PyErr_Format(PyExc_ValueError, \"invalid event %d\", event);\n        return NULL;\n    }\n    if (func == Py_None) {\n        func = NULL;\n    }\n    func = _PyMonitoring_RegisterCallback(tool_id, event_id, func);\n    if (func == NULL) {\n        Py_RETURN_NONE;\n    }\n    return func;\n}\n\n/*[clinic input]\nmonitoring.get_events -> int\n\n    tool_id: int\n    /\n\n[clinic start generated code]*/\n\nstatic int\nmonitoring_get_events_impl(PyObject *module, int tool_id)\n/*[clinic end generated code: output=4450cc13f826c8c0 input=a64b238f76c4b2f7]*/\n{\n    if (check_valid_tool(tool_id))  {\n        return -1;\n    }\n    _Py_Monitors *m = &_PyInterpreterState_Get()->monitors;\n    _PyMonitoringEventSet event_set = get_events(m, tool_id);\n    return event_set;\n}\n\n/*[clinic input]\nmonitoring.set_events\n\n    tool_id: int\n    event_set: int\n    /\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_set_events_impl(PyObject *module, int tool_id, int event_set)\n/*[clinic end generated code: output=1916c1e49cfb5bdb input=a77ba729a242142b]*/\n{\n    if (check_valid_tool(tool_id))  {\n        return NULL;\n    }\n    if (event_set < 0 || event_set >= (1 << PY_MONITORING_EVENTS)) {\n        PyErr_Format(PyExc_ValueError, \"invalid event set 0x%x\", event_set);\n        return NULL;\n    }\n    if ((event_set & C_RETURN_EVENTS) && (event_set & C_CALL_EVENTS) != C_CALL_EVENTS) {\n        PyErr_Format(PyExc_ValueError, \"cannot set C_RETURN or C_RAISE events independently\");\n        return NULL;\n    }\n    event_set &= ~C_RETURN_EVENTS;\n    if (_PyMonitoring_SetEvents(tool_id, event_set)) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nmonitoring.get_local_events -> int\n\n    tool_id: int\n    code: object\n    /\n\n[clinic start generated code]*/\n\nstatic int\nmonitoring_get_local_events_impl(PyObject *module, int tool_id,\n                                 PyObject *code)\n/*[clinic end generated code: output=d3e92c1c9c1de8f9 input=bb0f927530386a94]*/\n{\n    if (!PyCode_Check(code)) {\n        PyErr_Format(\n            PyExc_TypeError,\n            \"code must be a code object\"\n        );\n        return -1;\n    }\n    if (check_valid_tool(tool_id))  {\n        return -1;\n    }\n    _PyMonitoringEventSet event_set = 0;\n    _PyCoMonitoringData *data = ((PyCodeObject *)code)->_co_monitoring;\n    if (data != NULL) {\n        for (int e = 0; e < PY_MONITORING_UNGROUPED_EVENTS; e++) {\n            if ((data->local_monitors.tools[e] >> tool_id) & 1) {\n                event_set |= (1 << e);\n            }\n        }\n    }\n    return event_set;\n}\n\n/*[clinic input]\nmonitoring.set_local_events\n\n    tool_id: int\n    code: object\n    event_set: int\n    /\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_set_local_events_impl(PyObject *module, int tool_id,\n                                 PyObject *code, int event_set)\n/*[clinic end generated code: output=68cc755a65dfea99 input=5655ecd78d937a29]*/\n{\n    if (!PyCode_Check(code)) {\n        PyErr_Format(\n            PyExc_TypeError,\n            \"code must be a code object\"\n        );\n        return NULL;\n    }\n    if (check_valid_tool(tool_id))  {\n        return NULL;\n    }\n    if (event_set < 0 || event_set >= (1 << PY_MONITORING_EVENTS)) {\n        PyErr_Format(PyExc_ValueError, \"invalid event set 0x%x\", event_set);\n        return NULL;\n    }\n    if ((event_set & C_RETURN_EVENTS) && (event_set & C_CALL_EVENTS) != C_CALL_EVENTS) {\n        PyErr_Format(PyExc_ValueError, \"cannot set C_RETURN or C_RAISE events independently\");\n        return NULL;\n    }\n    event_set &= ~C_RETURN_EVENTS;\n    if (_PyMonitoring_SetLocalEvents((PyCodeObject*)code, tool_id, event_set)) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nmonitoring.restart_events\n\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring_restart_events_impl(PyObject *module)\n/*[clinic end generated code: output=e025dd5ba33314c4 input=add8a855063c8008]*/\n{\n    /* We want to ensure that:\n     * last restart version > instrumented version for all code objects\n     * last restart version < current version\n     */\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    interp->last_restart_version = interp->monitoring_version + 1;\n    interp->monitoring_version = interp->last_restart_version + 1;\n    if (instrument_all_executing_code_objects(interp)) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\nstatic int\nadd_power2_constant(PyObject *obj, const char *name, int i)\n{\n    PyObject *val = PyLong_FromLong(1<<i);\n    if (val == NULL) {\n        return -1;\n    }\n    int err = PyObject_SetAttrString(obj, name, val);\n    Py_DECREF(val);\n    return err;\n}\n\nstatic const char *const event_names [] = {\n    [PY_MONITORING_EVENT_PY_START] = \"PY_START\",\n    [PY_MONITORING_EVENT_PY_RESUME] = \"PY_RESUME\",\n    [PY_MONITORING_EVENT_PY_RETURN] = \"PY_RETURN\",\n    [PY_MONITORING_EVENT_PY_YIELD] = \"PY_YIELD\",\n    [PY_MONITORING_EVENT_CALL] = \"CALL\",\n    [PY_MONITORING_EVENT_LINE] = \"LINE\",\n    [PY_MONITORING_EVENT_INSTRUCTION] = \"INSTRUCTION\",\n    [PY_MONITORING_EVENT_JUMP] = \"JUMP\",\n    [PY_MONITORING_EVENT_BRANCH] = \"BRANCH\",\n    [PY_MONITORING_EVENT_C_RETURN] = \"C_RETURN\",\n    [PY_MONITORING_EVENT_PY_THROW] = \"PY_THROW\",\n    [PY_MONITORING_EVENT_RAISE] = \"RAISE\",\n    [PY_MONITORING_EVENT_EXCEPTION_HANDLED] = \"EXCEPTION_HANDLED\",\n    [PY_MONITORING_EVENT_C_RAISE] = \"C_RAISE\",\n    [PY_MONITORING_EVENT_PY_UNWIND] = \"PY_UNWIND\",\n    [PY_MONITORING_EVENT_STOP_ITERATION] = \"STOP_ITERATION\",\n};\n\n/*[clinic input]\nmonitoring._all_events\n[clinic start generated code]*/\n\nstatic PyObject *\nmonitoring__all_events_impl(PyObject *module)\n/*[clinic end generated code: output=6b7581e2dbb690f6 input=62ee9672c17b7f0e]*/\n{\n    PyInterpreterState *interp = _PyInterpreterState_Get();\n    PyObject *res = PyDict_New();\n    if (res == NULL) {\n        return NULL;\n    }\n    for (int e = 0; e < PY_MONITORING_UNGROUPED_EVENTS; e++) {\n        uint8_t tools = interp->monitors.tools[e];\n        if (tools == 0) {\n            continue;\n        }\n        PyObject *tools_obj = PyLong_FromLong(tools);\n        assert(tools_obj != NULL);\n        int err = PyDict_SetItemString(res, event_names[e], tools_obj);\n        Py_DECREF(tools_obj);\n        if (err < 0) {\n            Py_DECREF(res);\n            return NULL;\n        }\n    }\n    return res;\n}\n\nstatic PyMethodDef methods[] = {\n    MONITORING_USE_TOOL_ID_METHODDEF\n    MONITORING_FREE_TOOL_ID_METHODDEF\n    MONITORING_GET_TOOL_METHODDEF\n    MONITORING_REGISTER_CALLBACK_METHODDEF\n    MONITORING_GET_EVENTS_METHODDEF\n    MONITORING_SET_EVENTS_METHODDEF\n    MONITORING_GET_LOCAL_EVENTS_METHODDEF\n    MONITORING_SET_LOCAL_EVENTS_METHODDEF\n    MONITORING_RESTART_EVENTS_METHODDEF\n    MONITORING__ALL_EVENTS_METHODDEF\n    {NULL, NULL}  // sentinel\n};\n\nstatic struct PyModuleDef monitoring_module = {\n    PyModuleDef_HEAD_INIT,\n    .m_name = \"sys.monitoring\",\n    .m_size = -1, /* multiple \"initialization\" just copies the module dict. */\n    .m_methods = methods,\n};\n\nPyObject *_Py_CreateMonitoringObject(void)\n{\n    PyObject *mod = _PyModule_CreateInitialized(&monitoring_module, PYTHON_API_VERSION);\n    if (mod == NULL) {\n        return NULL;\n    }\n    if (PyObject_SetAttrString(mod, \"DISABLE\", &_PyInstrumentation_DISABLE)) {\n        goto error;\n    }\n    if (PyObject_SetAttrString(mod, \"MISSING\", &_PyInstrumentation_MISSING)) {\n        goto error;\n    }\n    PyObject *events = _PyNamespace_New(NULL);\n    if (events == NULL) {\n        goto error;\n    }\n    int err = PyObject_SetAttrString(mod, \"events\", events);\n    Py_DECREF(events);\n    if (err) {\n        goto error;\n    }\n    for (int i = 0; i < PY_MONITORING_EVENTS; i++) {\n        if (add_power2_constant(events, event_names[i], i)) {\n            goto error;\n        }\n    }\n    err = PyObject_SetAttrString(events, \"NO_EVENTS\", _PyLong_GetZero());\n    if (err) goto error;\n    PyObject *val = PyLong_FromLong(PY_MONITORING_DEBUGGER_ID);\n    err = PyObject_SetAttrString(mod, \"DEBUGGER_ID\", val);\n    Py_DECREF(val);\n    if (err) goto error;\n    val = PyLong_FromLong(PY_MONITORING_COVERAGE_ID);\n    err = PyObject_SetAttrString(mod, \"COVERAGE_ID\", val);\n    Py_DECREF(val);\n    if (err) goto error;\n    val = PyLong_FromLong(PY_MONITORING_PROFILER_ID);\n    err = PyObject_SetAttrString(mod, \"PROFILER_ID\", val);\n    Py_DECREF(val);\n    if (err) goto error;\n    val = PyLong_FromLong(PY_MONITORING_OPTIMIZER_ID);\n    err = PyObject_SetAttrString(mod, \"OPTIMIZER_ID\", val);\n    Py_DECREF(val);\n    if (err) goto error;\n    return mod;\nerror:\n    Py_DECREF(mod);\n    return NULL;\n}\n"
  },
  {
    "path": "Legacy_Tracing.c",
    "content": "/* Support for legacy tracing on top of PEP 669 instrumentation\n * Provides callables to forward PEP 669 events to legacy events.\n */\n\n#include <stddef.h>\n#include \"Python.h\"\n#include \"opcode.h\"\n#include \"pycore_ceval.h\"\n#include \"pycore_object.h\"\n#include \"pycore_sysmodule.h\"\n\ntypedef struct _PyLegacyEventHandler {\n    PyObject_HEAD\n    vectorcallfunc vectorcall;\n    int event;\n} _PyLegacyEventHandler;\n\n/* The Py_tracefunc function expects the following arguments:\n *   obj: the trace object (PyObject *)\n *   frame: the current frame (PyFrameObject *)\n *   kind: the kind of event, see PyTrace_XXX #defines (int)\n *   arg: The arg (a PyObject *)\n */\n\nstatic PyObject *\ncall_profile_func(_PyLegacyEventHandler *self, PyObject *arg)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (tstate->c_profilefunc == NULL) {\n        Py_RETURN_NONE;\n    }\n    PyFrameObject *frame = PyEval_GetFrame();\n    if (frame == NULL) {\n        PyErr_SetString(PyExc_SystemError,\n                        \"Missing frame when calling profile function.\");\n        return NULL;\n    }\n    Py_INCREF(frame);\n    int err = tstate->c_profilefunc(tstate->c_profileobj, frame, self->event, arg);\n    Py_DECREF(frame);\n    if (err) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\nstatic PyObject *\nsys_profile_func2(\n    _PyLegacyEventHandler *self, PyObject *const *args,\n    size_t nargsf, PyObject *kwnames\n) {\n    assert(kwnames == NULL);\n    assert(PyVectorcall_NARGS(nargsf) == 2);\n    return call_profile_func(self, Py_None);\n}\n\nstatic PyObject *\nsys_profile_func3(\n    _PyLegacyEventHandler *self, PyObject *const *args,\n    size_t nargsf, PyObject *kwnames\n) {\n    assert(kwnames == NULL);\n    assert(PyVectorcall_NARGS(nargsf) == 3);\n    return call_profile_func(self, args[2]);\n}\n\nstatic PyObject *\nsys_profile_call_or_return(\n    _PyLegacyEventHandler *self, PyObject *const *args,\n    size_t nargsf, PyObject *kwnames\n) {\n    assert(kwnames == NULL);\n    assert(PyVectorcall_NARGS(nargsf) == 4);\n    PyObject *callable = args[2];\n    if (PyCFunction_Check(callable)) {\n        return call_profile_func(self, callable);\n    }\n    if (Py_TYPE(callable) == &PyMethodDescr_Type) {\n        PyObject *self_arg = args[3];\n        /* For backwards compatibility need to\n         * convert to builtin method */\n\n        /* If no arg, skip */\n        if (self_arg == &_PyInstrumentation_MISSING) {\n            Py_RETURN_NONE;\n        }\n        PyObject *meth = Py_TYPE(callable)->tp_descr_get(\n            callable, self_arg, (PyObject*)Py_TYPE(self_arg));\n        if (meth == NULL) {\n            return NULL;\n        }\n        PyObject *res =  call_profile_func(self, meth);\n        Py_DECREF(meth);\n        return res;\n    }\n    Py_RETURN_NONE;\n}\n\nstatic PyObject *\ncall_trace_func(_PyLegacyEventHandler *self, PyObject *arg)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (tstate->c_tracefunc == NULL) {\n        Py_RETURN_NONE;\n    }\n    PyFrameObject *frame = PyEval_GetFrame();\n    if (frame == NULL) {\n        PyErr_SetString(PyExc_SystemError,\n                        \"Missing frame when calling trace function.\");\n        return NULL;\n    }\n    Py_INCREF(frame);\n    int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, arg);\n    Py_DECREF(frame);\n    if (err) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\nstatic PyObject *\nsys_trace_exception_func(\n    _PyLegacyEventHandler *self, PyObject *const *args,\n    size_t nargsf, PyObject *kwnames\n) {\n    assert(kwnames == NULL);\n    assert(PyVectorcall_NARGS(nargsf) == 3);\n    PyObject *exc = args[2];\n    assert(PyExceptionInstance_Check(exc));\n    PyObject *type = (PyObject *)Py_TYPE(exc);\n    PyObject *tb = PyException_GetTraceback(exc);\n    if (tb == NULL) {\n        tb = Py_NewRef(Py_None);\n    }\n    PyObject *tuple = PyTuple_Pack(3, type, exc, tb);\n    Py_DECREF(tb);\n    if (tuple == NULL) {\n        return NULL;\n    }\n    PyObject *res = call_trace_func(self, tuple);\n    Py_DECREF(tuple);\n    return res;\n}\n\nstatic PyObject *\nsys_trace_func2(\n    _PyLegacyEventHandler *self, PyObject *const *args,\n    size_t nargsf, PyObject *kwnames\n) {\n    assert(kwnames == NULL);\n    assert(PyVectorcall_NARGS(nargsf) == 2);\n    return call_trace_func(self, Py_None);\n}\n\nstatic PyObject *\nsys_trace_return(\n    _PyLegacyEventHandler *self, PyObject *const *args,\n    size_t nargsf, PyObject *kwnames\n) {\n    assert(!PyErr_Occurred());\n    assert(kwnames == NULL);\n    assert(PyVectorcall_NARGS(nargsf) == 3);\n    assert(PyCode_Check(args[0]));\n    PyObject *val = args[2];\n    PyObject *res = call_trace_func(self, val);\n    return res;\n}\n\nstatic PyObject *\nsys_trace_yield(\n    _PyLegacyEventHandler *self, PyObject *const *args,\n    size_t nargsf, PyObject *kwnames\n) {\n    assert(kwnames == NULL);\n    assert(PyVectorcall_NARGS(nargsf) == 3);\n    return call_trace_func(self, args[2]);\n}\n\nstatic PyObject *\nsys_trace_instruction_func(\n    _PyLegacyEventHandler *self, PyObject *const *args,\n    size_t nargsf, PyObject *kwnames\n) {\n    assert(kwnames == NULL);\n    assert(PyVectorcall_NARGS(nargsf) == 2);\n    PyFrameObject *frame = PyEval_GetFrame();\n    if (frame == NULL) {\n        PyErr_SetString(PyExc_SystemError,\n                        \"Missing frame when calling trace function.\");\n        return NULL;\n    }\n    if (!frame->f_trace_opcodes) {\n        Py_RETURN_NONE;\n    }\n    Py_INCREF(frame);\n    PyThreadState *tstate = _PyThreadState_GET();\n    int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, Py_None);\n    frame->f_lineno = 0;\n    Py_DECREF(frame);\n    if (err) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\nstatic PyObject *\ntrace_line(\n    PyThreadState *tstate, _PyLegacyEventHandler *self,\n    PyFrameObject *frame, int line\n) {\n    if (!frame->f_trace_lines) {\n        Py_RETURN_NONE;\n    }\n    if (line < 0) {\n        Py_RETURN_NONE;\n    }\n    Py_INCREF(frame);\n    frame->f_lineno = line;\n    int err = tstate->c_tracefunc(tstate->c_traceobj, frame, self->event, Py_None);\n    frame->f_lineno = 0;\n    Py_DECREF(frame);\n    if (err) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\nstatic PyObject *\nsys_trace_line_func(\n    _PyLegacyEventHandler *self, PyObject *const *args,\n    size_t nargsf, PyObject *kwnames\n) {\n    assert(kwnames == NULL);\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (tstate->c_tracefunc == NULL) {\n        Py_RETURN_NONE;\n    }\n    assert(PyVectorcall_NARGS(nargsf) == 2);\n    int line = _PyLong_AsInt(args[1]);\n    assert(line >= 0);\n    PyFrameObject *frame = PyEval_GetFrame();\n    if (frame == NULL) {\n        PyErr_SetString(PyExc_SystemError,\n                        \"Missing frame when calling trace function.\");\n        return NULL;\n    }\n    assert(args[0] == (PyObject *)frame->f_frame->f_code);\n    return trace_line(tstate, self, frame, line);\n}\n\n/* sys.settrace generates line events for all backward\n * edges, even if on the same line.\n * Handle that case here */\nstatic PyObject *\nsys_trace_jump_func(\n    _PyLegacyEventHandler *self, PyObject *const *args,\n    size_t nargsf, PyObject *kwnames\n) {\n    assert(kwnames == NULL);\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (tstate->c_tracefunc == NULL) {\n        Py_RETURN_NONE;\n    }\n    assert(PyVectorcall_NARGS(nargsf) == 3);\n    int from = _PyLong_AsInt(args[1])/sizeof(_Py_CODEUNIT);\n    assert(from >= 0);\n    int to = _PyLong_AsInt(args[2])/sizeof(_Py_CODEUNIT);\n    assert(to >= 0);\n    if (to > from) {\n        /* Forward jump */\n        return &_PyInstrumentation_DISABLE;\n    }\n    PyCodeObject *code = (PyCodeObject *)args[0];\n    assert(PyCode_Check(code));\n    /* We can call _Py_Instrumentation_GetLine because we always set\n    * line events for tracing */\n    int to_line = _Py_Instrumentation_GetLine(code, to);\n    int from_line = _Py_Instrumentation_GetLine(code, from);\n    if (to_line != from_line) {\n        /* Will be handled by target INSTRUMENTED_LINE */\n        return &_PyInstrumentation_DISABLE;\n    }\n    PyFrameObject *frame = PyEval_GetFrame();\n    if (frame == NULL) {\n        PyErr_SetString(PyExc_SystemError,\n                        \"Missing frame when calling trace function.\");\n        return NULL;\n    }\n    assert(code == frame->f_frame->f_code);\n    if (!frame->f_trace_lines) {\n        Py_RETURN_NONE;\n    }\n    return trace_line(tstate, self, frame, to_line);\n}\n\nPyTypeObject _PyLegacyEventHandler_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"sys.legacy_event_handler\",\n    sizeof(_PyLegacyEventHandler),\n    .tp_dealloc = (destructor)PyObject_Free,\n    .tp_vectorcall_offset = offsetof(_PyLegacyEventHandler, vectorcall),\n    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |\n        Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_DISALLOW_INSTANTIATION,\n    .tp_call = PyVectorcall_Call,\n};\n\nstatic int\nset_callbacks(int tool, vectorcallfunc vectorcall, int legacy_event, int event1, int event2)\n{\n    _PyLegacyEventHandler *callback =\n        PyObject_NEW(_PyLegacyEventHandler, &_PyLegacyEventHandler_Type);\n    if (callback == NULL) {\n        return -1;\n    }\n    callback->vectorcall = vectorcall;\n    callback->event = legacy_event;\n    Py_XDECREF(_PyMonitoring_RegisterCallback(tool, event1, (PyObject *)callback));\n    if (event2 >= 0) {\n        Py_XDECREF(_PyMonitoring_RegisterCallback(tool, event2, (PyObject *)callback));\n    }\n    Py_DECREF(callback);\n    return 0;\n}\n\n#ifndef NDEBUG\n/* Ensure that tstate is valid: sanity check for PyEval_AcquireThread() and\n   PyEval_RestoreThread(). Detect if tstate memory was freed. It can happen\n   when a thread continues to run after Python finalization, especially\n   daemon threads. */\nstatic int\nis_tstate_valid(PyThreadState *tstate)\n{\n    assert(!_PyMem_IsPtrFreed(tstate));\n    assert(!_PyMem_IsPtrFreed(tstate->interp));\n    return 1;\n}\n#endif\n\nint\n_PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)\n{\n    assert(is_tstate_valid(tstate));\n    /* The caller must hold the GIL */\n    assert(PyGILState_Check());\n\n    /* Call _PySys_Audit() in the context of the current thread state,\n       even if tstate is not the current thread state. */\n    PyThreadState *current_tstate = _PyThreadState_GET();\n    if (_PySys_Audit(current_tstate, \"sys.setprofile\", NULL) < 0) {\n        return -1;\n    }\n    /* Setup PEP 669 monitoring callbacks and events. */\n    if (!tstate->interp->sys_profile_initialized) {\n        tstate->interp->sys_profile_initialized = true;\n        if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,\n            (vectorcallfunc)sys_profile_func2, PyTrace_CALL,\n                        PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,\n            (vectorcallfunc)sys_profile_func3, PyTrace_RETURN,\n                        PY_MONITORING_EVENT_PY_RETURN, PY_MONITORING_EVENT_PY_YIELD)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,\n            (vectorcallfunc)sys_profile_func2, PyTrace_RETURN,\n                        PY_MONITORING_EVENT_PY_UNWIND, -1)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,\n            (vectorcallfunc)sys_profile_call_or_return, PyTrace_C_CALL,\n                        PY_MONITORING_EVENT_CALL, -1)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,\n            (vectorcallfunc)sys_profile_call_or_return, PyTrace_C_RETURN,\n                        PY_MONITORING_EVENT_C_RETURN, -1)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_PROFILE_ID,\n            (vectorcallfunc)sys_profile_call_or_return, PyTrace_C_EXCEPTION,\n                        PY_MONITORING_EVENT_C_RAISE, -1)) {\n            return -1;\n        }\n    }\n\n    int delta = (func != NULL) - (tstate->c_profilefunc != NULL);\n    tstate->c_profilefunc = func;\n    PyObject *old_profileobj = tstate->c_profileobj;\n    tstate->c_profileobj = Py_XNewRef(arg);\n    Py_XDECREF(old_profileobj);\n    tstate->interp->sys_profiling_threads += delta;\n    assert(tstate->interp->sys_profiling_threads >= 0);\n\n    uint32_t events = 0;\n    if (tstate->interp->sys_profiling_threads) {\n        events =\n            (1 << PY_MONITORING_EVENT_PY_START) | (1 << PY_MONITORING_EVENT_PY_RESUME) |\n            (1 << PY_MONITORING_EVENT_PY_RETURN) | (1 << PY_MONITORING_EVENT_PY_YIELD) |\n            (1 << PY_MONITORING_EVENT_CALL) | (1 << PY_MONITORING_EVENT_PY_UNWIND);\n    }\n    return _PyMonitoring_SetEvents(PY_MONITORING_SYS_PROFILE_ID, events);\n}\n\nint\n_PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)\n{\n    assert(is_tstate_valid(tstate));\n    /* The caller must hold the GIL */\n    assert(PyGILState_Check());\n\n    /* Call _PySys_Audit() in the context of the current thread state,\n       even if tstate is not the current thread state. */\n    PyThreadState *current_tstate = _PyThreadState_GET();\n    if (_PySys_Audit(current_tstate, \"sys.settrace\", NULL) < 0) {\n        return -1;\n    }\n\n    assert(tstate->interp->sys_tracing_threads >= 0);\n    /* Setup PEP 669 monitoring callbacks and events. */\n    if (!tstate->interp->sys_trace_initialized) {\n        tstate->interp->sys_trace_initialized = true;\n        if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,\n            (vectorcallfunc)sys_trace_func2, PyTrace_CALL,\n                        PY_MONITORING_EVENT_PY_START, PY_MONITORING_EVENT_PY_RESUME)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,\n            (vectorcallfunc)sys_trace_func2, PyTrace_CALL,\n                        PY_MONITORING_EVENT_PY_THROW, -1)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,\n            (vectorcallfunc)sys_trace_return, PyTrace_RETURN,\n                        PY_MONITORING_EVENT_PY_RETURN, -1)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,\n            (vectorcallfunc)sys_trace_yield, PyTrace_RETURN,\n                        PY_MONITORING_EVENT_PY_YIELD, -1)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,\n            (vectorcallfunc)sys_trace_exception_func, PyTrace_EXCEPTION,\n                        PY_MONITORING_EVENT_RAISE, PY_MONITORING_EVENT_STOP_ITERATION)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,\n            (vectorcallfunc)sys_trace_line_func, PyTrace_LINE,\n                        PY_MONITORING_EVENT_LINE, -1)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,\n            (vectorcallfunc)sys_trace_func2, PyTrace_RETURN,\n                        PY_MONITORING_EVENT_PY_UNWIND, -1)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,\n            (vectorcallfunc)sys_trace_jump_func, PyTrace_LINE,\n                        PY_MONITORING_EVENT_JUMP, -1)) {\n            return -1;\n        }\n        if (set_callbacks(PY_MONITORING_SYS_TRACE_ID,\n            (vectorcallfunc)sys_trace_instruction_func, PyTrace_OPCODE,\n                        PY_MONITORING_EVENT_INSTRUCTION, -1)) {\n            return -1;\n        }\n    }\n\n    int delta = (func != NULL) - (tstate->c_tracefunc != NULL);\n    tstate->c_tracefunc = func;\n    PyObject *old_traceobj = tstate->c_traceobj;\n    tstate->c_traceobj = Py_XNewRef(arg);\n    Py_XDECREF(old_traceobj);\n    tstate->interp->sys_tracing_threads += delta;\n    assert(tstate->interp->sys_tracing_threads >= 0);\n\n    uint32_t events = 0;\n    if (tstate->interp->sys_tracing_threads) {\n        events =\n            (1 << PY_MONITORING_EVENT_PY_START) | (1 << PY_MONITORING_EVENT_PY_RESUME) |\n            (1 << PY_MONITORING_EVENT_PY_RETURN) | (1 << PY_MONITORING_EVENT_PY_YIELD) |\n            (1 << PY_MONITORING_EVENT_RAISE) | (1 << PY_MONITORING_EVENT_LINE) |\n            (1 << PY_MONITORING_EVENT_JUMP) | (1 << PY_MONITORING_EVENT_BRANCH) |\n            (1 << PY_MONITORING_EVENT_PY_UNWIND) | (1 << PY_MONITORING_EVENT_PY_THROW) |\n            (1 << PY_MONITORING_EVENT_STOP_ITERATION) |\n            (1 << PY_MONITORING_EVENT_EXCEPTION_HANDLED);\n        if (tstate->interp->f_opcode_trace_set) {\n            events |= (1 << PY_MONITORING_EVENT_INSTRUCTION);\n        }\n    }\n    return _PyMonitoring_SetEvents(PY_MONITORING_SYS_TRACE_ID, events);\n}\n"
  },
  {
    "path": "MakeOpCodeTargets.py",
    "content": "#! /usr/bin/env python\n\"\"\"Generate C code for the jump table of the threaded code interpreter\n(for compilers supporting computed gotos or \"labels-as-values\", such as gcc).\n\"\"\"\n\nimport os\nimport sys\n\n\n# 2023-04-27(warsaw): Pre-Python 3.12, this would catch ImportErrors and try to\n# import imp, and then use imp.load_module().  The imp module was removed in\n# Python 3.12 (and long deprecated before that), and it's unclear under what\n# conditions this import will now fail, so the fallback was simply removed.\nfrom importlib.machinery import SourceFileLoader\n\ndef find_module(modname):\n    \"\"\"Finds and returns a module in the local dist/checkout.\n    \"\"\"\n    modpath = os.path.join(\n        os.path.dirname(os.path.dirname(__file__)), \"Lib\", modname + \".py\")\n    return SourceFileLoader(modname, modpath).load_module()\n\n\ndef write_contents(f):\n    \"\"\"Write C code contents to the target file object.\n    \"\"\"\n    opcode = find_module('opcode')\n    targets = ['_unknown_opcode'] * 256\n    for opname, op in opcode.opmap.items():\n        if not opcode.is_pseudo(op):\n            targets[op] = \"TARGET_%s\" % opname\n    next_op = 1\n    for opname in opcode._specialized_instructions:\n        while targets[next_op] != '_unknown_opcode':\n            next_op += 1\n        targets[next_op] = \"TARGET_%s\" % opname\n    f.write(\"static void *opcode_targets[256] = {\\n\")\n    f.write(\",\\n\".join([\"    &&%s\" % s for s in targets]))\n    f.write(\"\\n};\\n\")\n\n\ndef main():\n    if len(sys.argv) >= 3:\n        sys.exit(\"Too many arguments\")\n    if len(sys.argv) == 2:\n        target = sys.argv[1]\n    else:\n        target = \"Python/opcode_targets.h\"\n    with open(target, \"w\") as f:\n        write_contents(f)\n    print(\"Jump table written into %s\" % target)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "MarShal.c",
    "content": "\n/* Write Python objects to files and read them back.\n   This is primarily intended for writing and reading compiled Python code,\n   even though dicts, lists, sets and frozensets, not commonly seen in\n   code objects, are supported.\n   Version 3 of this protocol properly supports circular links\n   and sharing. */\n\n#define PY_SSIZE_T_CLEAN\n\n#include \"Python.h\"\n#include \"pycore_call.h\"          // _PyObject_CallNoArgs()\n#include \"pycore_code.h\"          // _PyCode_New()\n#include \"pycore_long.h\"          // _PyLong_DigitCount\n#include \"pycore_hashtable.h\"     // _Py_hashtable_t\n#include \"marshal.h\"              // Py_MARSHAL_VERSION\n\n/*[clinic input]\nmodule marshal\n[clinic start generated code]*/\n/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c982b7930dee17db]*/\n\n#include \"clinic/marshal.c.h\"\n\n/* High water mark to determine when the marshalled object is dangerously deep\n * and risks coring the interpreter.  When the object stack gets this deep,\n * raise an exception instead of continuing.\n * On Windows debug builds, reduce this value.\n *\n * BUG: https://bugs.python.org/issue33720\n * On Windows PGO builds, the r_object function overallocates its stack and\n * can cause a stack overflow. We reduce the maximum depth for all Windows\n * releases to protect against this.\n * #if defined(MS_WINDOWS) && defined(_DEBUG)\n */\n#if defined(MS_WINDOWS)\n#define MAX_MARSHAL_STACK_DEPTH 1000\n#elif defined(__wasi__)\n#define MAX_MARSHAL_STACK_DEPTH 1500\n#else\n#define MAX_MARSHAL_STACK_DEPTH 2000\n#endif\n\n#define TYPE_NULL               '0'\n#define TYPE_NONE               'N'\n#define TYPE_FALSE              'F'\n#define TYPE_TRUE               'T'\n#define TYPE_STOPITER           'S'\n#define TYPE_ELLIPSIS           '.'\n#define TYPE_INT                'i'\n/* TYPE_INT64 is not generated anymore.\n   Supported for backward compatibility only. */\n#define TYPE_INT64              'I'\n#define TYPE_FLOAT              'f'\n#define TYPE_BINARY_FLOAT       'g'\n#define TYPE_COMPLEX            'x'\n#define TYPE_BINARY_COMPLEX     'y'\n#define TYPE_LONG               'l'\n#define TYPE_STRING             's'\n#define TYPE_INTERNED           't'\n#define TYPE_REF                'r'\n#define TYPE_TUPLE              '('\n#define TYPE_LIST               '['\n#define TYPE_DICT               '{'\n#define TYPE_CODE               'c'\n#define TYPE_UNICODE            'u'\n#define TYPE_UNKNOWN            '?'\n#define TYPE_SET                '<'\n#define TYPE_FROZENSET          '>'\n#define FLAG_REF                '\\x80' /* with a type, add obj to index */\n\n#define TYPE_ASCII              'a'\n#define TYPE_ASCII_INTERNED     'A'\n#define TYPE_SMALL_TUPLE        ')'\n#define TYPE_SHORT_ASCII        'z'\n#define TYPE_SHORT_ASCII_INTERNED 'Z'\n\n#define WFERR_OK 0\n#define WFERR_UNMARSHALLABLE 1\n#define WFERR_NESTEDTOODEEP 2\n#define WFERR_NOMEMORY 3\n\ntypedef struct {\n    FILE *fp;\n    int error;  /* see WFERR_* values */\n    int depth;\n    PyObject *str;\n    char *ptr;\n    const char *end;\n    char *buf;\n    _Py_hashtable_t *hashtable;\n    int version;\n} WFILE;\n\n#define w_byte(c, p) do {                               \\\n        if ((p)->ptr != (p)->end || w_reserve((p), 1))  \\\n            *(p)->ptr++ = (c);                          \\\n    } while(0)\n\nstatic void\nw_flush(WFILE *p)\n{\n    assert(p->fp != NULL);\n    fwrite(p->buf, 1, p->ptr - p->buf, p->fp);\n    p->ptr = p->buf;\n}\n\nstatic int\nw_reserve(WFILE *p, Py_ssize_t needed)\n{\n    Py_ssize_t pos, size, delta;\n    if (p->ptr == NULL)\n        return 0; /* An error already occurred */\n    if (p->fp != NULL) {\n        w_flush(p);\n        return needed <= p->end - p->ptr;\n    }\n    assert(p->str != NULL);\n    pos = p->ptr - p->buf;\n    size = PyBytes_GET_SIZE(p->str);\n    if (size > 16*1024*1024)\n        delta = (size >> 3);            /* 12.5% overallocation */\n    else\n        delta = size + 1024;\n    delta = Py_MAX(delta, needed);\n    if (delta > PY_SSIZE_T_MAX - size) {\n        p->error = WFERR_NOMEMORY;\n        return 0;\n    }\n    size += delta;\n    if (_PyBytes_Resize(&p->str, size) != 0) {\n        p->end = p->ptr = p->buf = NULL;\n        return 0;\n    }\n    else {\n        p->buf = PyBytes_AS_STRING(p->str);\n        p->ptr = p->buf + pos;\n        p->end = p->buf + size;\n        return 1;\n    }\n}\n\nstatic void\nw_string(const void *s, Py_ssize_t n, WFILE *p)\n{\n    Py_ssize_t m;\n    if (!n || p->ptr == NULL)\n        return;\n    m = p->end - p->ptr;\n    if (p->fp != NULL) {\n        if (n <= m) {\n            memcpy(p->ptr, s, n);\n            p->ptr += n;\n        }\n        else {\n            w_flush(p);\n            fwrite(s, 1, n, p->fp);\n        }\n    }\n    else {\n        if (n <= m || w_reserve(p, n - m)) {\n            memcpy(p->ptr, s, n);\n            p->ptr += n;\n        }\n    }\n}\n\nstatic void\nw_short(int x, WFILE *p)\n{\n    w_byte((char)( x      & 0xff), p);\n    w_byte((char)((x>> 8) & 0xff), p);\n}\n\nstatic void\nw_long(long x, WFILE *p)\n{\n    w_byte((char)( x      & 0xff), p);\n    w_byte((char)((x>> 8) & 0xff), p);\n    w_byte((char)((x>>16) & 0xff), p);\n    w_byte((char)((x>>24) & 0xff), p);\n}\n\n#define SIZE32_MAX  0x7FFFFFFF\n\n#if SIZEOF_SIZE_T > 4\n# define W_SIZE(n, p)  do {                     \\\n        if ((n) > SIZE32_MAX) {                 \\\n            (p)->depth--;                       \\\n            (p)->error = WFERR_UNMARSHALLABLE;  \\\n            return;                             \\\n        }                                       \\\n        w_long((long)(n), p);                   \\\n    } while(0)\n#else\n# define W_SIZE  w_long\n#endif\n\nstatic void\nw_pstring(const void *s, Py_ssize_t n, WFILE *p)\n{\n        W_SIZE(n, p);\n        w_string(s, n, p);\n}\n\nstatic void\nw_short_pstring(const void *s, Py_ssize_t n, WFILE *p)\n{\n    w_byte(Py_SAFE_DOWNCAST(n, Py_ssize_t, unsigned char), p);\n    w_string(s, n, p);\n}\n\n/* We assume that Python ints are stored internally in base some power of\n   2**15; for the sake of portability we'll always read and write them in base\n   exactly 2**15. */\n\n#define PyLong_MARSHAL_SHIFT 15\n#define PyLong_MARSHAL_BASE ((short)1 << PyLong_MARSHAL_SHIFT)\n#define PyLong_MARSHAL_MASK (PyLong_MARSHAL_BASE - 1)\n#if PyLong_SHIFT % PyLong_MARSHAL_SHIFT != 0\n#error \"PyLong_SHIFT must be a multiple of PyLong_MARSHAL_SHIFT\"\n#endif\n#define PyLong_MARSHAL_RATIO (PyLong_SHIFT / PyLong_MARSHAL_SHIFT)\n\n#define W_TYPE(t, p) do { \\\n    w_byte((t) | flag, (p)); \\\n} while(0)\n\nstatic void\nw_PyLong(const PyLongObject *ob, char flag, WFILE *p)\n{\n    Py_ssize_t i, j, n, l;\n    digit d;\n\n    W_TYPE(TYPE_LONG, p);\n    if (_PyLong_IsZero(ob)) {\n        w_long((long)0, p);\n        return;\n    }\n\n    /* set l to number of base PyLong_MARSHAL_BASE digits */\n    n = _PyLong_DigitCount(ob);\n    l = (n-1) * PyLong_MARSHAL_RATIO;\n    d = ob->long_value.ob_digit[n-1];\n    assert(d != 0); /* a PyLong is always normalized */\n    do {\n        d >>= PyLong_MARSHAL_SHIFT;\n        l++;\n    } while (d != 0);\n    if (l > SIZE32_MAX) {\n        p->depth--;\n        p->error = WFERR_UNMARSHALLABLE;\n        return;\n    }\n    w_long((long)(_PyLong_IsNegative(ob) ? -l : l), p);\n\n    for (i=0; i < n-1; i++) {\n        d = ob->long_value.ob_digit[i];\n        for (j=0; j < PyLong_MARSHAL_RATIO; j++) {\n            w_short(d & PyLong_MARSHAL_MASK, p);\n            d >>= PyLong_MARSHAL_SHIFT;\n        }\n        assert (d == 0);\n    }\n    d = ob->long_value.ob_digit[n-1];\n    do {\n        w_short(d & PyLong_MARSHAL_MASK, p);\n        d >>= PyLong_MARSHAL_SHIFT;\n    } while (d != 0);\n}\n\nstatic void\nw_float_bin(double v, WFILE *p)\n{\n    char buf[8];\n    if (PyFloat_Pack8(v, buf, 1) < 0) {\n        p->error = WFERR_UNMARSHALLABLE;\n        return;\n    }\n    w_string(buf, 8, p);\n}\n\nstatic void\nw_float_str(double v, WFILE *p)\n{\n    char *buf = PyOS_double_to_string(v, 'g', 17, 0, NULL);\n    if (!buf) {\n        p->error = WFERR_NOMEMORY;\n        return;\n    }\n    w_short_pstring(buf, strlen(buf), p);\n    PyMem_Free(buf);\n}\n\nstatic int\nw_ref(PyObject *v, char *flag, WFILE *p)\n{\n    _Py_hashtable_entry_t *entry;\n    int w;\n\n    if (p->version < 3 || p->hashtable == NULL)\n        return 0; /* not writing object references */\n\n    /* If it has only one reference, it definitely isn't shared.\n     * But we use TYPE_REF always for interned string, to PYC file stable\n     * as possible.\n     */\n    if (Py_REFCNT(v) == 1 &&\n            !(PyUnicode_CheckExact(v) && PyUnicode_CHECK_INTERNED(v))) {\n        return 0;\n    }\n\n    entry = _Py_hashtable_get_entry(p->hashtable, v);\n    if (entry != NULL) {\n        /* write the reference index to the stream */\n        w = (int)(uintptr_t)entry->value;\n        /* we don't store \"long\" indices in the dict */\n        assert(0 <= w && w <= 0x7fffffff);\n        w_byte(TYPE_REF, p);\n        w_long(w, p);\n        return 1;\n    } else {\n        size_t s = p->hashtable->nentries;\n        /* we don't support long indices */\n        if (s >= 0x7fffffff) {\n            PyErr_SetString(PyExc_ValueError, \"too many objects\");\n            goto err;\n        }\n        w = (int)s;\n        if (_Py_hashtable_set(p->hashtable, Py_NewRef(v),\n                              (void *)(uintptr_t)w) < 0) {\n            Py_DECREF(v);\n            goto err;\n        }\n        *flag |= FLAG_REF;\n        return 0;\n    }\nerr:\n    p->error = WFERR_UNMARSHALLABLE;\n    return 1;\n}\n\nstatic void\nw_complex_object(PyObject *v, char flag, WFILE *p);\n\nstatic void\nw_object(PyObject *v, WFILE *p)\n{\n    char flag = '\\0';\n\n    p->depth++;\n\n    if (p->depth > MAX_MARSHAL_STACK_DEPTH) {\n        p->error = WFERR_NESTEDTOODEEP;\n    }\n    else if (v == NULL) {\n        w_byte(TYPE_NULL, p);\n    }\n    else if (v == Py_None) {\n        w_byte(TYPE_NONE, p);\n    }\n    else if (v == PyExc_StopIteration) {\n        w_byte(TYPE_STOPITER, p);\n    }\n    else if (v == Py_Ellipsis) {\n        w_byte(TYPE_ELLIPSIS, p);\n    }\n    else if (v == Py_False) {\n        w_byte(TYPE_FALSE, p);\n    }\n    else if (v == Py_True) {\n        w_byte(TYPE_TRUE, p);\n    }\n    else if (!w_ref(v, &flag, p))\n        w_complex_object(v, flag, p);\n\n    p->depth--;\n}\n\nstatic void\nw_complex_object(PyObject *v, char flag, WFILE *p)\n{\n    Py_ssize_t i, n;\n\n    if (PyLong_CheckExact(v)) {\n        int overflow;\n        long x = PyLong_AsLongAndOverflow(v, &overflow);\n        if (overflow) {\n            w_PyLong((PyLongObject *)v, flag, p);\n        }\n        else {\n#if SIZEOF_LONG > 4\n            long y = Py_ARITHMETIC_RIGHT_SHIFT(long, x, 31);\n            if (y && y != -1) {\n                /* Too large for TYPE_INT */\n                w_PyLong((PyLongObject*)v, flag, p);\n            }\n            else\n#endif\n            {\n                W_TYPE(TYPE_INT, p);\n                w_long(x, p);\n            }\n        }\n    }\n    else if (PyFloat_CheckExact(v)) {\n        if (p->version > 1) {\n            W_TYPE(TYPE_BINARY_FLOAT, p);\n            w_float_bin(PyFloat_AS_DOUBLE(v), p);\n        }\n        else {\n            W_TYPE(TYPE_FLOAT, p);\n            w_float_str(PyFloat_AS_DOUBLE(v), p);\n        }\n    }\n    else if (PyComplex_CheckExact(v)) {\n        if (p->version > 1) {\n            W_TYPE(TYPE_BINARY_COMPLEX, p);\n            w_float_bin(PyComplex_RealAsDouble(v), p);\n            w_float_bin(PyComplex_ImagAsDouble(v), p);\n        }\n        else {\n            W_TYPE(TYPE_COMPLEX, p);\n            w_float_str(PyComplex_RealAsDouble(v), p);\n            w_float_str(PyComplex_ImagAsDouble(v), p);\n        }\n    }\n    else if (PyBytes_CheckExact(v)) {\n        W_TYPE(TYPE_STRING, p);\n        w_pstring(PyBytes_AS_STRING(v), PyBytes_GET_SIZE(v), p);\n    }\n    else if (PyUnicode_CheckExact(v)) {\n        if (p->version >= 4 && PyUnicode_IS_ASCII(v)) {\n            int is_short = PyUnicode_GET_LENGTH(v) < 256;\n            if (is_short) {\n                if (PyUnicode_CHECK_INTERNED(v))\n                    W_TYPE(TYPE_SHORT_ASCII_INTERNED, p);\n                else\n                    W_TYPE(TYPE_SHORT_ASCII, p);\n                w_short_pstring(PyUnicode_1BYTE_DATA(v),\n                                PyUnicode_GET_LENGTH(v), p);\n            }\n            else {\n                if (PyUnicode_CHECK_INTERNED(v))\n                    W_TYPE(TYPE_ASCII_INTERNED, p);\n                else\n                    W_TYPE(TYPE_ASCII, p);\n                w_pstring(PyUnicode_1BYTE_DATA(v),\n                          PyUnicode_GET_LENGTH(v), p);\n            }\n        }\n        else {\n            PyObject *utf8;\n            utf8 = PyUnicode_AsEncodedString(v, \"utf8\", \"surrogatepass\");\n            if (utf8 == NULL) {\n                p->depth--;\n                p->error = WFERR_UNMARSHALLABLE;\n                return;\n            }\n            if (p->version >= 3 &&  PyUnicode_CHECK_INTERNED(v))\n                W_TYPE(TYPE_INTERNED, p);\n            else\n                W_TYPE(TYPE_UNICODE, p);\n            w_pstring(PyBytes_AS_STRING(utf8), PyBytes_GET_SIZE(utf8), p);\n            Py_DECREF(utf8);\n        }\n    }\n    else if (PyTuple_CheckExact(v)) {\n        n = PyTuple_GET_SIZE(v);\n        if (p->version >= 4 && n < 256) {\n            W_TYPE(TYPE_SMALL_TUPLE, p);\n            w_byte((unsigned char)n, p);\n        }\n        else {\n            W_TYPE(TYPE_TUPLE, p);\n            W_SIZE(n, p);\n        }\n        for (i = 0; i < n; i++) {\n            w_object(PyTuple_GET_ITEM(v, i), p);\n        }\n    }\n    else if (PyList_CheckExact(v)) {\n        W_TYPE(TYPE_LIST, p);\n        n = PyList_GET_SIZE(v);\n        W_SIZE(n, p);\n        for (i = 0; i < n; i++) {\n            w_object(PyList_GET_ITEM(v, i), p);\n        }\n    }\n    else if (PyDict_CheckExact(v)) {\n        Py_ssize_t pos;\n        PyObject *key, *value;\n        W_TYPE(TYPE_DICT, p);\n        /* This one is NULL object terminated! */\n        pos = 0;\n        while (PyDict_Next(v, &pos, &key, &value)) {\n            w_object(key, p);\n            w_object(value, p);\n        }\n        w_object((PyObject *)NULL, p);\n    }\n    else if (PyAnySet_CheckExact(v)) {\n        PyObject *value;\n        Py_ssize_t pos = 0;\n        Py_hash_t hash;\n\n        if (PyFrozenSet_CheckExact(v))\n            W_TYPE(TYPE_FROZENSET, p);\n        else\n            W_TYPE(TYPE_SET, p);\n        n = PySet_GET_SIZE(v);\n        W_SIZE(n, p);\n        // bpo-37596: To support reproducible builds, sets and frozensets need\n        // to have their elements serialized in a consistent order (even when\n        // they have been scrambled by hash randomization). To ensure this, we\n        // use an order equivalent to sorted(v, key=marshal.dumps):\n        PyObject *pairs = PyList_New(n);\n        if (pairs == NULL) {\n            p->error = WFERR_NOMEMORY;\n            return;\n        }\n        Py_ssize_t i = 0;\n        while (_PySet_NextEntry(v, &pos, &value, &hash)) {\n            PyObject *dump = PyMarshal_WriteObjectToString(value, p->version);\n            if (dump == NULL) {\n                p->error = WFERR_UNMARSHALLABLE;\n                Py_DECREF(pairs);\n                return;\n            }\n            PyObject *pair = PyTuple_Pack(2, dump, value);\n            Py_DECREF(dump);\n            if (pair == NULL) {\n                p->error = WFERR_NOMEMORY;\n                Py_DECREF(pairs);\n                return;\n            }\n            PyList_SET_ITEM(pairs, i++, pair);\n        }\n        assert(i == n);\n        if (PyList_Sort(pairs)) {\n            p->error = WFERR_NOMEMORY;\n            Py_DECREF(pairs);\n            return;\n        }\n        for (Py_ssize_t i = 0; i < n; i++) {\n            PyObject *pair = PyList_GET_ITEM(pairs, i);\n            value = PyTuple_GET_ITEM(pair, 1);\n            w_object(value, p);\n        }\n        Py_DECREF(pairs);\n    }\n    else if (PyCode_Check(v)) {\n        PyCodeObject *co = (PyCodeObject *)v;\n        PyObject *co_code = _PyCode_GetCode(co);\n        if (co_code == NULL) {\n            p->error = WFERR_NOMEMORY;\n            return;\n        }\n        W_TYPE(TYPE_CODE, p);\n        w_long(co->co_argcount, p);\n        w_long(co->co_posonlyargcount, p);\n        w_long(co->co_kwonlyargcount, p);\n        w_long(co->co_stacksize, p);\n        w_long(co->co_flags, p);\n        w_object(co_code, p);\n        w_object(co->co_consts, p);\n        w_object(co->co_names, p);\n        w_object(co->co_localsplusnames, p);\n        w_object(co->co_localspluskinds, p);\n        w_object(co->co_filename, p);\n        w_object(co->co_name, p);\n        w_object(co->co_qualname, p);\n        w_long(co->co_firstlineno, p);\n        w_object(co->co_linetable, p);\n        w_object(co->co_exceptiontable, p);\n        Py_DECREF(co_code);\n    }\n    else if (PyObject_CheckBuffer(v)) {\n        /* Write unknown bytes-like objects as a bytes object */\n        Py_buffer view;\n        if (PyObject_GetBuffer(v, &view, PyBUF_SIMPLE) != 0) {\n            w_byte(TYPE_UNKNOWN, p);\n            p->depth--;\n            p->error = WFERR_UNMARSHALLABLE;\n            return;\n        }\n        W_TYPE(TYPE_STRING, p);\n        w_pstring(view.buf, view.len, p);\n        PyBuffer_Release(&view);\n    }\n    else {\n        W_TYPE(TYPE_UNKNOWN, p);\n        p->error = WFERR_UNMARSHALLABLE;\n    }\n}\n\nstatic void\nw_decref_entry(void *key)\n{\n    PyObject *entry_key = (PyObject *)key;\n    Py_XDECREF(entry_key);\n}\n\nstatic int\nw_init_refs(WFILE *wf, int version)\n{\n    if (version >= 3) {\n        wf->hashtable = _Py_hashtable_new_full(_Py_hashtable_hash_ptr,\n                                               _Py_hashtable_compare_direct,\n                                               w_decref_entry, NULL, NULL);\n        if (wf->hashtable == NULL) {\n            PyErr_NoMemory();\n            return -1;\n        }\n    }\n    return 0;\n}\n\nstatic void\nw_clear_refs(WFILE *wf)\n{\n    if (wf->hashtable != NULL) {\n        _Py_hashtable_destroy(wf->hashtable);\n    }\n}\n\n/* version currently has no effect for writing ints. */\n/* Note that while the documentation states that this function\n * can error, currently it never does. Setting an exception in\n * this function should be regarded as an API-breaking change.\n */\nvoid\nPyMarshal_WriteLongToFile(long x, FILE *fp, int version)\n{\n    char buf[4];\n    WFILE wf;\n    memset(&wf, 0, sizeof(wf));\n    wf.fp = fp;\n    wf.ptr = wf.buf = buf;\n    wf.end = wf.ptr + sizeof(buf);\n    wf.error = WFERR_OK;\n    wf.version = version;\n    w_long(x, &wf);\n    w_flush(&wf);\n}\n\nvoid\nPyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version)\n{\n    char buf[BUFSIZ];\n    WFILE wf;\n    if (PySys_Audit(\"marshal.dumps\", \"Oi\", x, version) < 0) {\n        return; /* caller must check PyErr_Occurred() */\n    }\n    memset(&wf, 0, sizeof(wf));\n    wf.fp = fp;\n    wf.ptr = wf.buf = buf;\n    wf.end = wf.ptr + sizeof(buf);\n    wf.error = WFERR_OK;\n    wf.version = version;\n    if (w_init_refs(&wf, version)) {\n        return; /* caller must check PyErr_Occurred() */\n    }\n    w_object(x, &wf);\n    w_clear_refs(&wf);\n    w_flush(&wf);\n}\n\ntypedef struct {\n    FILE *fp;\n    int depth;\n    PyObject *readable;  /* Stream-like object being read from */\n    const char *ptr;\n    const char *end;\n    char *buf;\n    Py_ssize_t buf_size;\n    PyObject *refs;  /* a list */\n} RFILE;\n\nstatic const char *\nr_string(Py_ssize_t n, RFILE *p)\n{\n    Py_ssize_t read = -1;\n\n    if (p->ptr != NULL) {\n        /* Fast path for loads() */\n        const char *res = p->ptr;\n        Py_ssize_t left = p->end - p->ptr;\n        if (left < n) {\n            PyErr_SetString(PyExc_EOFError,\n                            \"marshal data too short\");\n            return NULL;\n        }\n        p->ptr += n;\n        return res;\n    }\n    if (p->buf == NULL) {\n        p->buf = PyMem_Malloc(n);\n        if (p->buf == NULL) {\n            PyErr_NoMemory();\n            return NULL;\n        }\n        p->buf_size = n;\n    }\n    else if (p->buf_size < n) {\n        char *tmp = PyMem_Realloc(p->buf, n);\n        if (tmp == NULL) {\n            PyErr_NoMemory();\n            return NULL;\n        }\n        p->buf = tmp;\n        p->buf_size = n;\n    }\n\n    if (!p->readable) {\n        assert(p->fp != NULL);\n        read = fread(p->buf, 1, n, p->fp);\n    }\n    else {\n        PyObject *res, *mview;\n        Py_buffer buf;\n\n        if (PyBuffer_FillInfo(&buf, NULL, p->buf, n, 0, PyBUF_CONTIG) == -1)\n            return NULL;\n        mview = PyMemoryView_FromBuffer(&buf);\n        if (mview == NULL)\n            return NULL;\n\n        res = _PyObject_CallMethod(p->readable, &_Py_ID(readinto), \"N\", mview);\n        if (res != NULL) {\n            read = PyNumber_AsSsize_t(res, PyExc_ValueError);\n            Py_DECREF(res);\n        }\n    }\n    if (read != n) {\n        if (!PyErr_Occurred()) {\n            if (read > n)\n                PyErr_Format(PyExc_ValueError,\n                             \"read() returned too much data: \"\n                             \"%zd bytes requested, %zd returned\",\n                             n, read);\n            else\n                PyErr_SetString(PyExc_EOFError,\n                                \"EOF read where not expected\");\n        }\n        return NULL;\n    }\n    return p->buf;\n}\n\nstatic int\nr_byte(RFILE *p)\n{\n    int c = EOF;\n\n    if (p->ptr != NULL) {\n        if (p->ptr < p->end)\n            c = (unsigned char) *p->ptr++;\n        return c;\n    }\n    if (!p->readable) {\n        assert(p->fp);\n        c = getc(p->fp);\n    }\n    else {\n        const char *ptr = r_string(1, p);\n        if (ptr != NULL)\n            c = *(const unsigned char *) ptr;\n    }\n    return c;\n}\n\nstatic int\nr_short(RFILE *p)\n{\n    short x = -1;\n    const unsigned char *buffer;\n\n    buffer = (const unsigned char *) r_string(2, p);\n    if (buffer != NULL) {\n        x = buffer[0];\n        x |= buffer[1] << 8;\n        /* Sign-extension, in case short greater than 16 bits */\n        x |= -(x & 0x8000);\n    }\n    return x;\n}\n\nstatic long\nr_long(RFILE *p)\n{\n    long x = -1;\n    const unsigned char *buffer;\n\n    buffer = (const unsigned char *) r_string(4, p);\n    if (buffer != NULL) {\n        x = buffer[0];\n        x |= (long)buffer[1] << 8;\n        x |= (long)buffer[2] << 16;\n        x |= (long)buffer[3] << 24;\n#if SIZEOF_LONG > 4\n        /* Sign extension for 64-bit machines */\n        x |= -(x & 0x80000000L);\n#endif\n    }\n    return x;\n}\n\n/* r_long64 deals with the TYPE_INT64 code. */\nstatic PyObject *\nr_long64(RFILE *p)\n{\n    const unsigned char *buffer = (const unsigned char *) r_string(8, p);\n    if (buffer == NULL) {\n        return NULL;\n    }\n    return _PyLong_FromByteArray(buffer, 8,\n                                 1 /* little endian */,\n                                 1 /* signed */);\n}\n\nstatic PyObject *\nr_PyLong(RFILE *p)\n{\n    PyLongObject *ob;\n    long n, size, i;\n    int j, md, shorts_in_top_digit;\n    digit d;\n\n    n = r_long(p);\n    if (PyErr_Occurred())\n        return NULL;\n    if (n == 0)\n        return (PyObject *)_PyLong_New(0);\n    if (n < -SIZE32_MAX || n > SIZE32_MAX) {\n        PyErr_SetString(PyExc_ValueError,\n                       \"bad marshal data (long size out of range)\");\n        return NULL;\n    }\n\n    size = 1 + (Py_ABS(n) - 1) / PyLong_MARSHAL_RATIO;\n    shorts_in_top_digit = 1 + (Py_ABS(n) - 1) % PyLong_MARSHAL_RATIO;\n    ob = _PyLong_New(size);\n    if (ob == NULL)\n        return NULL;\n\n    _PyLong_SetSignAndDigitCount(ob, n < 0 ? -1 : 1, size);\n\n    for (i = 0; i < size-1; i++) {\n        d = 0;\n        for (j=0; j < PyLong_MARSHAL_RATIO; j++) {\n            md = r_short(p);\n            if (PyErr_Occurred()) {\n                Py_DECREF(ob);\n                return NULL;\n            }\n            if (md < 0 || md > PyLong_MARSHAL_BASE)\n                goto bad_digit;\n            d += (digit)md << j*PyLong_MARSHAL_SHIFT;\n        }\n        ob->long_value.ob_digit[i] = d;\n    }\n\n    d = 0;\n    for (j=0; j < shorts_in_top_digit; j++) {\n        md = r_short(p);\n        if (PyErr_Occurred()) {\n            Py_DECREF(ob);\n            return NULL;\n        }\n        if (md < 0 || md > PyLong_MARSHAL_BASE)\n            goto bad_digit;\n        /* topmost marshal digit should be nonzero */\n        if (md == 0 && j == shorts_in_top_digit - 1) {\n            Py_DECREF(ob);\n            PyErr_SetString(PyExc_ValueError,\n                \"bad marshal data (unnormalized long data)\");\n            return NULL;\n        }\n        d += (digit)md << j*PyLong_MARSHAL_SHIFT;\n    }\n    if (PyErr_Occurred()) {\n        Py_DECREF(ob);\n        return NULL;\n    }\n    /* top digit should be nonzero, else the resulting PyLong won't be\n       normalized */\n    ob->long_value.ob_digit[size-1] = d;\n    return (PyObject *)ob;\n  bad_digit:\n    Py_DECREF(ob);\n    PyErr_SetString(PyExc_ValueError,\n                    \"bad marshal data (digit out of range in long)\");\n    return NULL;\n}\n\nstatic double\nr_float_bin(RFILE *p)\n{\n    const char *buf = r_string(8, p);\n    if (buf == NULL)\n        return -1;\n    return PyFloat_Unpack8(buf, 1);\n}\n\n/* Issue #33720: Disable inlining for reducing the C stack consumption\n   on PGO builds. */\nPy_NO_INLINE static double\nr_float_str(RFILE *p)\n{\n    int n;\n    char buf[256];\n    const char *ptr;\n    n = r_byte(p);\n    if (n == EOF) {\n        PyErr_SetString(PyExc_EOFError,\n            \"EOF read where object expected\");\n        return -1;\n    }\n    ptr = r_string(n, p);\n    if (ptr == NULL) {\n        return -1;\n    }\n    memcpy(buf, ptr, n);\n    buf[n] = '\\0';\n    return PyOS_string_to_double(buf, NULL, NULL);\n}\n\n/* allocate the reflist index for a new object. Return -1 on failure */\nstatic Py_ssize_t\nr_ref_reserve(int flag, RFILE *p)\n{\n    if (flag) { /* currently only FLAG_REF is defined */\n        Py_ssize_t idx = PyList_GET_SIZE(p->refs);\n        if (idx >= 0x7ffffffe) {\n            PyErr_SetString(PyExc_ValueError, \"bad marshal data (index list too large)\");\n            return -1;\n        }\n        if (PyList_Append(p->refs, Py_None) < 0)\n            return -1;\n        return idx;\n    } else\n        return 0;\n}\n\n/* insert the new object 'o' to the reflist at previously\n * allocated index 'idx'.\n * 'o' can be NULL, in which case nothing is done.\n * if 'o' was non-NULL, and the function succeeds, 'o' is returned.\n * if 'o' was non-NULL, and the function fails, 'o' is released and\n * NULL returned. This simplifies error checking at the call site since\n * a single test for NULL for the function result is enough.\n */\nstatic PyObject *\nr_ref_insert(PyObject *o, Py_ssize_t idx, int flag, RFILE *p)\n{\n    if (o != NULL && flag) { /* currently only FLAG_REF is defined */\n        PyObject *tmp = PyList_GET_ITEM(p->refs, idx);\n        PyList_SET_ITEM(p->refs, idx, Py_NewRef(o));\n        Py_DECREF(tmp);\n    }\n    return o;\n}\n\n/* combination of both above, used when an object can be\n * created whenever it is seen in the file, as opposed to\n * after having loaded its sub-objects.\n */\nstatic PyObject *\nr_ref(PyObject *o, int flag, RFILE *p)\n{\n    assert(flag & FLAG_REF);\n    if (o == NULL)\n        return NULL;\n    if (PyList_Append(p->refs, o) < 0) {\n        Py_DECREF(o); /* release the new object */\n        return NULL;\n    }\n    return o;\n}\n\nstatic PyObject *\nr_object(RFILE *p)\n{\n    /* NULL is a valid return value, it does not necessarily means that\n       an exception is set. */\n    PyObject *v, *v2;\n    Py_ssize_t idx = 0;\n    long i, n;\n    int type, code = r_byte(p);\n    int flag, is_interned = 0;\n    PyObject *retval = NULL;\n\n    if (code == EOF) {\n        PyErr_SetString(PyExc_EOFError,\n                        \"EOF read where object expected\");\n        return NULL;\n    }\n\n    p->depth++;\n\n    if (p->depth > MAX_MARSHAL_STACK_DEPTH) {\n        p->depth--;\n        PyErr_SetString(PyExc_ValueError, \"recursion limit exceeded\");\n        return NULL;\n    }\n\n    flag = code & FLAG_REF;\n    type = code & ~FLAG_REF;\n\n#define R_REF(O) do{\\\n    if (flag) \\\n        O = r_ref(O, flag, p);\\\n} while (0)\n\n    switch (type) {\n\n    case TYPE_NULL:\n        break;\n\n    case TYPE_NONE:\n        retval = Py_NewRef(Py_None);\n        break;\n\n    case TYPE_STOPITER:\n        retval = Py_NewRef(PyExc_StopIteration);\n        break;\n\n    case TYPE_ELLIPSIS:\n        retval = Py_NewRef(Py_Ellipsis);\n        break;\n\n    case TYPE_FALSE:\n        retval = Py_NewRef(Py_False);\n        break;\n\n    case TYPE_TRUE:\n        retval = Py_NewRef(Py_True);\n        break;\n\n    case TYPE_INT:\n        n = r_long(p);\n        retval = PyErr_Occurred() ? NULL : PyLong_FromLong(n);\n        R_REF(retval);\n        break;\n\n    case TYPE_INT64:\n        retval = r_long64(p);\n        R_REF(retval);\n        break;\n\n    case TYPE_LONG:\n        retval = r_PyLong(p);\n        R_REF(retval);\n        break;\n\n    case TYPE_FLOAT:\n        {\n            double x = r_float_str(p);\n            if (x == -1.0 && PyErr_Occurred())\n                break;\n            retval = PyFloat_FromDouble(x);\n            R_REF(retval);\n            break;\n        }\n\n    case TYPE_BINARY_FLOAT:\n        {\n            double x = r_float_bin(p);\n            if (x == -1.0 && PyErr_Occurred())\n                break;\n            retval = PyFloat_FromDouble(x);\n            R_REF(retval);\n            break;\n        }\n\n    case TYPE_COMPLEX:\n        {\n            Py_complex c;\n            c.real = r_float_str(p);\n            if (c.real == -1.0 && PyErr_Occurred())\n                break;\n            c.imag = r_float_str(p);\n            if (c.imag == -1.0 && PyErr_Occurred())\n                break;\n            retval = PyComplex_FromCComplex(c);\n            R_REF(retval);\n            break;\n        }\n\n    case TYPE_BINARY_COMPLEX:\n        {\n            Py_complex c;\n            c.real = r_float_bin(p);\n            if (c.real == -1.0 && PyErr_Occurred())\n                break;\n            c.imag = r_float_bin(p);\n            if (c.imag == -1.0 && PyErr_Occurred())\n                break;\n            retval = PyComplex_FromCComplex(c);\n            R_REF(retval);\n            break;\n        }\n\n    case TYPE_STRING:\n        {\n            const char *ptr;\n            n = r_long(p);\n            if (PyErr_Occurred())\n                break;\n            if (n < 0 || n > SIZE32_MAX) {\n                PyErr_SetString(PyExc_ValueError, \"bad marshal data (bytes object size out of range)\");\n                break;\n            }\n            v = PyBytes_FromStringAndSize((char *)NULL, n);\n            if (v == NULL)\n                break;\n            ptr = r_string(n, p);\n            if (ptr == NULL) {\n                Py_DECREF(v);\n                break;\n            }\n            memcpy(PyBytes_AS_STRING(v), ptr, n);\n            retval = v;\n            R_REF(retval);\n            break;\n        }\n\n    case TYPE_ASCII_INTERNED:\n        is_interned = 1;\n        /* fall through */\n    case TYPE_ASCII:\n        n = r_long(p);\n        if (PyErr_Occurred())\n            break;\n        if (n < 0 || n > SIZE32_MAX) {\n            PyErr_SetString(PyExc_ValueError, \"bad marshal data (string size out of range)\");\n            break;\n        }\n        goto _read_ascii;\n\n    case TYPE_SHORT_ASCII_INTERNED:\n        is_interned = 1;\n        /* fall through */\n    case TYPE_SHORT_ASCII:\n        n = r_byte(p);\n        if (n == EOF) {\n            PyErr_SetString(PyExc_EOFError,\n                \"EOF read where object expected\");\n            break;\n        }\n    _read_ascii:\n        {\n            const char *ptr;\n            ptr = r_string(n, p);\n            if (ptr == NULL)\n                break;\n            v = PyUnicode_FromKindAndData(PyUnicode_1BYTE_KIND, ptr, n);\n            if (v == NULL)\n                break;\n            if (is_interned)\n                PyUnicode_InternInPlace(&v);\n            retval = v;\n            R_REF(retval);\n            break;\n        }\n\n    case TYPE_INTERNED:\n        is_interned = 1;\n        /* fall through */\n    case TYPE_UNICODE:\n        {\n        const char *buffer;\n\n        n = r_long(p);\n        if (PyErr_Occurred())\n            break;\n        if (n < 0 || n > SIZE32_MAX) {\n            PyErr_SetString(PyExc_ValueError, \"bad marshal data (string size out of range)\");\n            break;\n        }\n        if (n != 0) {\n            buffer = r_string(n, p);\n            if (buffer == NULL)\n                break;\n            v = PyUnicode_DecodeUTF8(buffer, n, \"surrogatepass\");\n        }\n        else {\n            v = PyUnicode_New(0, 0);\n        }\n        if (v == NULL)\n            break;\n        if (is_interned)\n            PyUnicode_InternInPlace(&v);\n        retval = v;\n        R_REF(retval);\n        break;\n        }\n\n    case TYPE_SMALL_TUPLE:\n        n = (unsigned char) r_byte(p);\n        if (PyErr_Occurred())\n            break;\n        goto _read_tuple;\n    case TYPE_TUPLE:\n        n = r_long(p);\n        if (PyErr_Occurred())\n            break;\n        if (n < 0 || n > SIZE32_MAX) {\n            PyErr_SetString(PyExc_ValueError, \"bad marshal data (tuple size out of range)\");\n            break;\n        }\n    _read_tuple:\n        v = PyTuple_New(n);\n        R_REF(v);\n        if (v == NULL)\n            break;\n\n        for (i = 0; i < n; i++) {\n            v2 = r_object(p);\n            if ( v2 == NULL ) {\n                if (!PyErr_Occurred())\n                    PyErr_SetString(PyExc_TypeError,\n                        \"NULL object in marshal data for tuple\");\n                Py_SETREF(v, NULL);\n                break;\n            }\n            PyTuple_SET_ITEM(v, i, v2);\n        }\n        retval = v;\n        break;\n\n    case TYPE_LIST:\n        n = r_long(p);\n        if (PyErr_Occurred())\n            break;\n        if (n < 0 || n > SIZE32_MAX) {\n            PyErr_SetString(PyExc_ValueError, \"bad marshal data (list size out of range)\");\n            break;\n        }\n        v = PyList_New(n);\n        R_REF(v);\n        if (v == NULL)\n            break;\n        for (i = 0; i < n; i++) {\n            v2 = r_object(p);\n            if ( v2 == NULL ) {\n                if (!PyErr_Occurred())\n                    PyErr_SetString(PyExc_TypeError,\n                        \"NULL object in marshal data for list\");\n                Py_SETREF(v, NULL);\n                break;\n            }\n            PyList_SET_ITEM(v, i, v2);\n        }\n        retval = v;\n        break;\n\n    case TYPE_DICT:\n        v = PyDict_New();\n        R_REF(v);\n        if (v == NULL)\n            break;\n        for (;;) {\n            PyObject *key, *val;\n            key = r_object(p);\n            if (key == NULL)\n                break;\n            val = r_object(p);\n            if (val == NULL) {\n                Py_DECREF(key);\n                break;\n            }\n            if (PyDict_SetItem(v, key, val) < 0) {\n                Py_DECREF(key);\n                Py_DECREF(val);\n                break;\n            }\n            Py_DECREF(key);\n            Py_DECREF(val);\n        }\n        if (PyErr_Occurred()) {\n            Py_SETREF(v, NULL);\n        }\n        retval = v;\n        break;\n\n    case TYPE_SET:\n    case TYPE_FROZENSET:\n        n = r_long(p);\n        if (PyErr_Occurred())\n            break;\n        if (n < 0 || n > SIZE32_MAX) {\n            PyErr_SetString(PyExc_ValueError, \"bad marshal data (set size out of range)\");\n            break;\n        }\n\n        if (n == 0 && type == TYPE_FROZENSET) {\n            /* call frozenset() to get the empty frozenset singleton */\n            v = _PyObject_CallNoArgs((PyObject*)&PyFrozenSet_Type);\n            if (v == NULL)\n                break;\n            R_REF(v);\n            retval = v;\n        }\n        else {\n            v = (type == TYPE_SET) ? PySet_New(NULL) : PyFrozenSet_New(NULL);\n            if (type == TYPE_SET) {\n                R_REF(v);\n            } else {\n                /* must use delayed registration of frozensets because they must\n                 * be init with a refcount of 1\n                 */\n                idx = r_ref_reserve(flag, p);\n                if (idx < 0)\n                    Py_CLEAR(v); /* signal error */\n            }\n            if (v == NULL)\n                break;\n\n            for (i = 0; i < n; i++) {\n                v2 = r_object(p);\n                if ( v2 == NULL ) {\n                    if (!PyErr_Occurred())\n                        PyErr_SetString(PyExc_TypeError,\n                            \"NULL object in marshal data for set\");\n                    Py_SETREF(v, NULL);\n                    break;\n                }\n                if (PySet_Add(v, v2) == -1) {\n                    Py_DECREF(v);\n                    Py_DECREF(v2);\n                    v = NULL;\n                    break;\n                }\n                Py_DECREF(v2);\n            }\n            if (type != TYPE_SET)\n                v = r_ref_insert(v, idx, flag, p);\n            retval = v;\n        }\n        break;\n\n    case TYPE_CODE:\n        {\n            int argcount;\n            int posonlyargcount;\n            int kwonlyargcount;\n            int stacksize;\n            int flags;\n            PyObject *code = NULL;\n            PyObject *consts = NULL;\n            PyObject *names = NULL;\n            PyObject *localsplusnames = NULL;\n            PyObject *localspluskinds = NULL;\n            PyObject *filename = NULL;\n            PyObject *name = NULL;\n            PyObject *qualname = NULL;\n            int firstlineno;\n            PyObject* linetable = NULL;\n            PyObject *exceptiontable = NULL;\n\n            idx = r_ref_reserve(flag, p);\n            if (idx < 0)\n                break;\n\n            v = NULL;\n\n            /* XXX ignore long->int overflows for now */\n            argcount = (int)r_long(p);\n            if (PyErr_Occurred())\n                goto code_error;\n            posonlyargcount = (int)r_long(p);\n            if (PyErr_Occurred()) {\n                goto code_error;\n            }\n            kwonlyargcount = (int)r_long(p);\n            if (PyErr_Occurred())\n                goto code_error;\n            stacksize = (int)r_long(p);\n            if (PyErr_Occurred())\n                goto code_error;\n            flags = (int)r_long(p);\n            if (PyErr_Occurred())\n                goto code_error;\n            code = r_object(p);\n            if (code == NULL)\n                goto code_error;\n            consts = r_object(p);\n            if (consts == NULL)\n                goto code_error;\n            names = r_object(p);\n            if (names == NULL)\n                goto code_error;\n            localsplusnames = r_object(p);\n            if (localsplusnames == NULL)\n                goto code_error;\n            localspluskinds = r_object(p);\n            if (localspluskinds == NULL)\n                goto code_error;\n            filename = r_object(p);\n            if (filename == NULL)\n                goto code_error;\n            name = r_object(p);\n            if (name == NULL)\n                goto code_error;\n            qualname = r_object(p);\n            if (qualname == NULL)\n                goto code_error;\n            firstlineno = (int)r_long(p);\n            if (firstlineno == -1 && PyErr_Occurred())\n                break;\n            linetable = r_object(p);\n            if (linetable == NULL)\n                goto code_error;\n            exceptiontable = r_object(p);\n            if (exceptiontable == NULL)\n                goto code_error;\n\n            struct _PyCodeConstructor con = {\n                .filename = filename,\n                .name = name,\n                .qualname = qualname,\n                .flags = flags,\n\n                .code = code,\n                .firstlineno = firstlineno,\n                .linetable = linetable,\n\n                .consts = consts,\n                .names = names,\n\n                .localsplusnames = localsplusnames,\n                .localspluskinds = localspluskinds,\n\n                .argcount = argcount,\n                .posonlyargcount = posonlyargcount,\n                .kwonlyargcount = kwonlyargcount,\n\n                .stacksize = stacksize,\n\n                .exceptiontable = exceptiontable,\n            };\n\n            if (_PyCode_Validate(&con) < 0) {\n                goto code_error;\n            }\n\n            v = (PyObject *)_PyCode_New(&con);\n            if (v == NULL) {\n                goto code_error;\n            }\n\n            v = r_ref_insert(v, idx, flag, p);\n\n          code_error:\n            Py_XDECREF(code);\n            Py_XDECREF(consts);\n            Py_XDECREF(names);\n            Py_XDECREF(localsplusnames);\n            Py_XDECREF(localspluskinds);\n            Py_XDECREF(filename);\n            Py_XDECREF(name);\n            Py_XDECREF(qualname);\n            Py_XDECREF(linetable);\n            Py_XDECREF(exceptiontable);\n        }\n        retval = v;\n        break;\n\n    case TYPE_REF:\n        n = r_long(p);\n        if (n < 0 || n >= PyList_GET_SIZE(p->refs)) {\n            if (n == -1 && PyErr_Occurred())\n                break;\n            PyErr_SetString(PyExc_ValueError, \"bad marshal data (invalid reference)\");\n            break;\n        }\n        v = PyList_GET_ITEM(p->refs, n);\n        if (v == Py_None) {\n            PyErr_SetString(PyExc_ValueError, \"bad marshal data (invalid reference)\");\n            break;\n        }\n        retval = Py_NewRef(v);\n        break;\n\n    default:\n        /* Bogus data got written, which isn't ideal.\n           This will let you keep working and recover. */\n        PyErr_SetString(PyExc_ValueError, \"bad marshal data (unknown type code)\");\n        break;\n\n    }\n    p->depth--;\n    return retval;\n}\n\nstatic PyObject *\nread_object(RFILE *p)\n{\n    PyObject *v;\n    if (PyErr_Occurred()) {\n        fprintf(stderr, \"XXX readobject called with exception set\\n\");\n        return NULL;\n    }\n    if (p->ptr && p->end) {\n        if (PySys_Audit(\"marshal.loads\", \"y#\", p->ptr, (Py_ssize_t)(p->end - p->ptr)) < 0) {\n            return NULL;\n        }\n    } else if (p->fp || p->readable) {\n        if (PySys_Audit(\"marshal.load\", NULL) < 0) {\n            return NULL;\n        }\n    }\n    v = r_object(p);\n    if (v == NULL && !PyErr_Occurred())\n        PyErr_SetString(PyExc_TypeError, \"NULL object in marshal data for object\");\n    return v;\n}\n\nint\nPyMarshal_ReadShortFromFile(FILE *fp)\n{\n    RFILE rf;\n    int res;\n    assert(fp);\n    rf.readable = NULL;\n    rf.fp = fp;\n    rf.end = rf.ptr = NULL;\n    rf.buf = NULL;\n    res = r_short(&rf);\n    if (rf.buf != NULL)\n        PyMem_Free(rf.buf);\n    return res;\n}\n\nlong\nPyMarshal_ReadLongFromFile(FILE *fp)\n{\n    RFILE rf;\n    long res;\n    rf.fp = fp;\n    rf.readable = NULL;\n    rf.ptr = rf.end = NULL;\n    rf.buf = NULL;\n    res = r_long(&rf);\n    if (rf.buf != NULL)\n        PyMem_Free(rf.buf);\n    return res;\n}\n\n/* Return size of file in bytes; < 0 if unknown or INT_MAX if too big */\nstatic off_t\ngetfilesize(FILE *fp)\n{\n    struct _Py_stat_struct st;\n    if (_Py_fstat_noraise(fileno(fp), &st) != 0)\n        return -1;\n#if SIZEOF_OFF_T == 4\n    else if (st.st_size >= INT_MAX)\n        return (off_t)INT_MAX;\n#endif\n    else\n        return (off_t)st.st_size;\n}\n\n/* If we can get the size of the file up-front, and it's reasonably small,\n * read it in one gulp and delegate to ...FromString() instead.  Much quicker\n * than reading a byte at a time from file; speeds .pyc imports.\n * CAUTION:  since this may read the entire remainder of the file, don't\n * call it unless you know you're done with the file.\n */\nPyObject *\nPyMarshal_ReadLastObjectFromFile(FILE *fp)\n{\n/* REASONABLE_FILE_LIMIT is by defn something big enough for Tkinter.pyc. */\n#define REASONABLE_FILE_LIMIT (1L << 18)\n    off_t filesize;\n    filesize = getfilesize(fp);\n    if (filesize > 0 && filesize <= REASONABLE_FILE_LIMIT) {\n        char* pBuf = (char *)PyMem_Malloc(filesize);\n        if (pBuf != NULL) {\n            size_t n = fread(pBuf, 1, (size_t)filesize, fp);\n            PyObject* v = PyMarshal_ReadObjectFromString(pBuf, n);\n            PyMem_Free(pBuf);\n            return v;\n        }\n\n    }\n    /* We don't have fstat, or we do but the file is larger than\n     * REASONABLE_FILE_LIMIT or malloc failed -- read a byte at a time.\n     */\n    return PyMarshal_ReadObjectFromFile(fp);\n\n#undef REASONABLE_FILE_LIMIT\n}\n\nPyObject *\nPyMarshal_ReadObjectFromFile(FILE *fp)\n{\n    RFILE rf;\n    PyObject *result;\n    rf.fp = fp;\n    rf.readable = NULL;\n    rf.depth = 0;\n    rf.ptr = rf.end = NULL;\n    rf.buf = NULL;\n    rf.refs = PyList_New(0);\n    if (rf.refs == NULL)\n        return NULL;\n    result = read_object(&rf);\n    Py_DECREF(rf.refs);\n    if (rf.buf != NULL)\n        PyMem_Free(rf.buf);\n    return result;\n}\n\nPyObject *\nPyMarshal_ReadObjectFromString(const char *str, Py_ssize_t len)\n{\n    RFILE rf;\n    PyObject *result;\n    rf.fp = NULL;\n    rf.readable = NULL;\n    rf.ptr = str;\n    rf.end = str + len;\n    rf.buf = NULL;\n    rf.depth = 0;\n    rf.refs = PyList_New(0);\n    if (rf.refs == NULL)\n        return NULL;\n    result = read_object(&rf);\n    Py_DECREF(rf.refs);\n    if (rf.buf != NULL)\n        PyMem_Free(rf.buf);\n    return result;\n}\n\nPyObject *\nPyMarshal_WriteObjectToString(PyObject *x, int version)\n{\n    WFILE wf;\n\n    if (PySys_Audit(\"marshal.dumps\", \"Oi\", x, version) < 0) {\n        return NULL;\n    }\n    memset(&wf, 0, sizeof(wf));\n    wf.str = PyBytes_FromStringAndSize((char *)NULL, 50);\n    if (wf.str == NULL)\n        return NULL;\n    wf.ptr = wf.buf = PyBytes_AS_STRING(wf.str);\n    wf.end = wf.ptr + PyBytes_GET_SIZE(wf.str);\n    wf.error = WFERR_OK;\n    wf.version = version;\n    if (w_init_refs(&wf, version)) {\n        Py_DECREF(wf.str);\n        return NULL;\n    }\n    w_object(x, &wf);\n    w_clear_refs(&wf);\n    if (wf.str != NULL) {\n        const char *base = PyBytes_AS_STRING(wf.str);\n        if (_PyBytes_Resize(&wf.str, (Py_ssize_t)(wf.ptr - base)) < 0)\n            return NULL;\n    }\n    if (wf.error != WFERR_OK) {\n        Py_XDECREF(wf.str);\n        if (wf.error == WFERR_NOMEMORY)\n            PyErr_NoMemory();\n        else\n            PyErr_SetString(PyExc_ValueError,\n              (wf.error==WFERR_UNMARSHALLABLE)?\"unmarshallable object\"\n               :\"object too deeply nested to marshal\");\n        return NULL;\n    }\n    return wf.str;\n}\n\n/* And an interface for Python programs... */\n/*[clinic input]\nmarshal.dump\n\n    value: object\n        Must be a supported type.\n    file: object\n        Must be a writeable binary file.\n    version: int(c_default=\"Py_MARSHAL_VERSION\") = version\n        Indicates the data format that dump should use.\n    /\n\nWrite the value on the open file.\n\nIf the value has (or contains an object that has) an unsupported type, a\nValueError exception is raised - but garbage data will also be written\nto the file. The object will not be properly read back by load().\n[clinic start generated code]*/\n\nstatic PyObject *\nmarshal_dump_impl(PyObject *module, PyObject *value, PyObject *file,\n                  int version)\n/*[clinic end generated code: output=aaee62c7028a7cb2 input=6c7a3c23c6fef556]*/\n{\n    /* XXX Quick hack -- need to do this differently */\n    PyObject *s;\n    PyObject *res;\n\n    s = PyMarshal_WriteObjectToString(value, version);\n    if (s == NULL)\n        return NULL;\n    res = _PyObject_CallMethodOneArg(file, &_Py_ID(write), s);\n    Py_DECREF(s);\n    return res;\n}\n\n/*[clinic input]\nmarshal.load\n\n    file: object\n        Must be readable binary file.\n    /\n\nRead one value from the open file and return it.\n\nIf no valid value is read (e.g. because the data has a different Python\nversion's incompatible marshal format), raise EOFError, ValueError or\nTypeError.\n\nNote: If an object containing an unsupported type was marshalled with\ndump(), load() will substitute None for the unmarshallable type.\n[clinic start generated code]*/\n\nstatic PyObject *\nmarshal_load(PyObject *module, PyObject *file)\n/*[clinic end generated code: output=f8e5c33233566344 input=c85c2b594cd8124a]*/\n{\n    PyObject *data, *result;\n    RFILE rf;\n\n    /*\n     * Make a call to the read method, but read zero bytes.\n     * This is to ensure that the object passed in at least\n     * has a read method which returns bytes.\n     * This can be removed if we guarantee good error handling\n     * for r_string()\n     */\n    data = _PyObject_CallMethod(file, &_Py_ID(read), \"i\", 0);\n    if (data == NULL)\n        return NULL;\n    if (!PyBytes_Check(data)) {\n        PyErr_Format(PyExc_TypeError,\n                     \"file.read() returned not bytes but %.100s\",\n                     Py_TYPE(data)->tp_name);\n        result = NULL;\n    }\n    else {\n        rf.depth = 0;\n        rf.fp = NULL;\n        rf.readable = file;\n        rf.ptr = rf.end = NULL;\n        rf.buf = NULL;\n        if ((rf.refs = PyList_New(0)) != NULL) {\n            result = read_object(&rf);\n            Py_DECREF(rf.refs);\n            if (rf.buf != NULL)\n                PyMem_Free(rf.buf);\n        } else\n            result = NULL;\n    }\n    Py_DECREF(data);\n    return result;\n}\n\n/*[clinic input]\nmarshal.dumps\n\n    value: object\n        Must be a supported type.\n    version: int(c_default=\"Py_MARSHAL_VERSION\") = version\n        Indicates the data format that dumps should use.\n    /\n\nReturn the bytes object that would be written to a file by dump(value, file).\n\nRaise a ValueError exception if value has (or contains an object that has) an\nunsupported type.\n[clinic start generated code]*/\n\nstatic PyObject *\nmarshal_dumps_impl(PyObject *module, PyObject *value, int version)\n/*[clinic end generated code: output=9c200f98d7256cad input=a2139ea8608e9b27]*/\n{\n    return PyMarshal_WriteObjectToString(value, version);\n}\n\n/*[clinic input]\nmarshal.loads\n\n    bytes: Py_buffer\n    /\n\nConvert the bytes-like object to a value.\n\nIf no valid value is found, raise EOFError, ValueError or TypeError.  Extra\nbytes in the input are ignored.\n[clinic start generated code]*/\n\nstatic PyObject *\nmarshal_loads_impl(PyObject *module, Py_buffer *bytes)\n/*[clinic end generated code: output=9fc65985c93d1bb1 input=6f426518459c8495]*/\n{\n    RFILE rf;\n    char *s = bytes->buf;\n    Py_ssize_t n = bytes->len;\n    PyObject* result;\n    rf.fp = NULL;\n    rf.readable = NULL;\n    rf.ptr = s;\n    rf.end = s + n;\n    rf.depth = 0;\n    if ((rf.refs = PyList_New(0)) == NULL)\n        return NULL;\n    result = read_object(&rf);\n    Py_DECREF(rf.refs);\n    return result;\n}\n\nstatic PyMethodDef marshal_methods[] = {\n    MARSHAL_DUMP_METHODDEF\n    MARSHAL_LOAD_METHODDEF\n    MARSHAL_DUMPS_METHODDEF\n    MARSHAL_LOADS_METHODDEF\n    {NULL,              NULL}           /* sentinel */\n};\n\n\nPyDoc_STRVAR(module_doc,\n\"This module contains functions that can read and write Python values in\\n\\\na binary format. The format is specific to Python, but independent of\\n\\\nmachine architecture issues.\\n\\\n\\n\\\nNot all Python object types are supported; in general, only objects\\n\\\nwhose value is independent from a particular invocation of Python can be\\n\\\nwritten and read by this module. The following types are supported:\\n\\\nNone, integers, floating point numbers, strings, bytes, bytearrays,\\n\\\ntuples, lists, sets, dictionaries, and code objects, where it\\n\\\nshould be understood that tuples, lists and dictionaries are only\\n\\\nsupported as long as the values contained therein are themselves\\n\\\nsupported; and recursive lists and dictionaries should not be written\\n\\\n(they will cause infinite loops).\\n\\\n\\n\\\nVariables:\\n\\\n\\n\\\nversion -- indicates the format that the module uses. Version 0 is the\\n\\\n    historical format, version 1 shares interned strings and version 2\\n\\\n    uses a binary format for floating point numbers.\\n\\\n    Version 3 shares common object references (New in version 3.4).\\n\\\n\\n\\\nFunctions:\\n\\\n\\n\\\ndump() -- write value to a file\\n\\\nload() -- read value from a file\\n\\\ndumps() -- marshal value as a bytes object\\n\\\nloads() -- read value from a bytes-like object\");\n\n\nstatic int\nmarshal_module_exec(PyObject *mod)\n{\n    if (PyModule_AddIntConstant(mod, \"version\", Py_MARSHAL_VERSION) < 0) {\n        return -1;\n    }\n    return 0;\n}\n\nstatic PyModuleDef_Slot marshalmodule_slots[] = {\n    {Py_mod_exec, marshal_module_exec},\n    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},\n    {0, NULL}\n};\n\nstatic struct PyModuleDef marshalmodule = {\n    PyModuleDef_HEAD_INIT,\n    .m_name = \"marshal\",\n    .m_doc = module_doc,\n    .m_methods = marshal_methods,\n    .m_slots = marshalmodule_slots,\n};\n\nPyMODINIT_FUNC\nPyMarshal_Init(void)\n{\n    return PyModuleDef_Init(&marshalmodule);\n}\n"
  },
  {
    "path": "ModSupport.c",
    "content": "\n/* Module support implementation */\n\n#include \"Python.h\"\n#include \"pycore_abstract.h\"   // _PyIndex_Check()\n#include \"pycore_object.h\"     // _PyType_IsReady()\n\ntypedef double va_double;\n\nstatic PyObject *va_build_value(const char *, va_list);\n\n\nint\n_Py_convert_optional_to_ssize_t(PyObject *obj, void *result)\n{\n    Py_ssize_t limit;\n    if (obj == Py_None) {\n        return 1;\n    }\n    else if (_PyIndex_Check(obj)) {\n        limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);\n        if (limit == -1 && PyErr_Occurred()) {\n            return 0;\n        }\n    }\n    else {\n        PyErr_Format(PyExc_TypeError,\n                     \"argument should be integer or None, not '%.200s'\",\n                     Py_TYPE(obj)->tp_name);\n        return 0;\n    }\n    *((Py_ssize_t *)result) = limit;\n    return 1;\n}\n\n\n/* Helper for mkvalue() to scan the length of a format */\n\nstatic Py_ssize_t\ncountformat(const char *format, char endchar)\n{\n    Py_ssize_t count = 0;\n    int level = 0;\n    while (level > 0 || *format != endchar) {\n        switch (*format) {\n        case '\\0':\n            /* Premature end */\n            PyErr_SetString(PyExc_SystemError,\n                            \"unmatched paren in format\");\n            return -1;\n        case '(':\n        case '[':\n        case '{':\n            if (level == 0) {\n                count++;\n            }\n            level++;\n            break;\n        case ')':\n        case ']':\n        case '}':\n            level--;\n            break;\n        case '#':\n        case '&':\n        case ',':\n        case ':':\n        case ' ':\n        case '\\t':\n            break;\n        default:\n            if (level == 0) {\n                count++;\n            }\n        }\n        format++;\n    }\n    return count;\n}\n\n\n/* Generic function to create a value -- the inverse of getargs() */\n/* After an original idea and first implementation by Steven Miale */\n\nstatic PyObject *do_mktuple(const char**, va_list *, char, Py_ssize_t);\nstatic int do_mkstack(PyObject **, const char**, va_list *, char, Py_ssize_t);\nstatic PyObject *do_mklist(const char**, va_list *, char, Py_ssize_t);\nstatic PyObject *do_mkdict(const char**, va_list *, char, Py_ssize_t);\nstatic PyObject *do_mkvalue(const char**, va_list *);\n\n\nstatic void\ndo_ignore(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n)\n{\n    assert(PyErr_Occurred());\n    PyObject *v = PyTuple_New(n);\n    for (Py_ssize_t i = 0; i < n; i++) {\n        PyObject *exc = PyErr_GetRaisedException();\n        PyObject *w = do_mkvalue(p_format, p_va);\n        PyErr_SetRaisedException(exc);\n        if (w != NULL) {\n            if (v != NULL) {\n                PyTuple_SET_ITEM(v, i, w);\n            }\n            else {\n                Py_DECREF(w);\n            }\n        }\n    }\n    Py_XDECREF(v);\n    if (**p_format != endchar) {\n        PyErr_SetString(PyExc_SystemError,\n                        \"Unmatched paren in format\");\n        return;\n    }\n    if (endchar) {\n        ++*p_format;\n    }\n}\n\nstatic PyObject *\ndo_mkdict(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n)\n{\n    PyObject *d;\n    Py_ssize_t i;\n    if (n < 0)\n        return NULL;\n    if (n % 2) {\n        PyErr_SetString(PyExc_SystemError,\n                        \"Bad dict format\");\n        do_ignore(p_format, p_va, endchar, n);\n        return NULL;\n    }\n    /* Note that we can't bail immediately on error as this will leak\n       refcounts on any 'N' arguments. */\n    if ((d = PyDict_New()) == NULL) {\n        do_ignore(p_format, p_va, endchar, n);\n        return NULL;\n    }\n    for (i = 0; i < n; i+= 2) {\n        PyObject *k, *v;\n\n        k = do_mkvalue(p_format, p_va);\n        if (k == NULL) {\n            do_ignore(p_format, p_va, endchar, n - i - 1);\n            Py_DECREF(d);\n            return NULL;\n        }\n        v = do_mkvalue(p_format, p_va);\n        if (v == NULL || PyDict_SetItem(d, k, v) < 0) {\n            do_ignore(p_format, p_va, endchar, n - i - 2);\n            Py_DECREF(k);\n            Py_XDECREF(v);\n            Py_DECREF(d);\n            return NULL;\n        }\n        Py_DECREF(k);\n        Py_DECREF(v);\n    }\n    if (**p_format != endchar) {\n        Py_DECREF(d);\n        PyErr_SetString(PyExc_SystemError,\n                        \"Unmatched paren in format\");\n        return NULL;\n    }\n    if (endchar)\n        ++*p_format;\n    return d;\n}\n\nstatic PyObject *\ndo_mklist(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n)\n{\n    PyObject *v;\n    Py_ssize_t i;\n    if (n < 0)\n        return NULL;\n    /* Note that we can't bail immediately on error as this will leak\n       refcounts on any 'N' arguments. */\n    v = PyList_New(n);\n    if (v == NULL) {\n        do_ignore(p_format, p_va, endchar, n);\n        return NULL;\n    }\n    for (i = 0; i < n; i++) {\n        PyObject *w = do_mkvalue(p_format, p_va);\n        if (w == NULL) {\n            do_ignore(p_format, p_va, endchar, n - i - 1);\n            Py_DECREF(v);\n            return NULL;\n        }\n        PyList_SET_ITEM(v, i, w);\n    }\n    if (**p_format != endchar) {\n        Py_DECREF(v);\n        PyErr_SetString(PyExc_SystemError,\n                        \"Unmatched paren in format\");\n        return NULL;\n    }\n    if (endchar)\n        ++*p_format;\n    return v;\n}\n\nstatic int\ndo_mkstack(PyObject **stack, const char **p_format, va_list *p_va,\n           char endchar, Py_ssize_t n)\n{\n    Py_ssize_t i;\n\n    if (n < 0) {\n        return -1;\n    }\n    /* Note that we can't bail immediately on error as this will leak\n       refcounts on any 'N' arguments. */\n    for (i = 0; i < n; i++) {\n        PyObject *w = do_mkvalue(p_format, p_va);\n        if (w == NULL) {\n            do_ignore(p_format, p_va, endchar, n - i - 1);\n            goto error;\n        }\n        stack[i] = w;\n    }\n    if (**p_format != endchar) {\n        PyErr_SetString(PyExc_SystemError,\n                        \"Unmatched paren in format\");\n        goto error;\n    }\n    if (endchar) {\n        ++*p_format;\n    }\n    return 0;\n\nerror:\n    n = i;\n    for (i=0; i < n; i++) {\n        Py_DECREF(stack[i]);\n    }\n    return -1;\n}\n\nstatic PyObject *\ndo_mktuple(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n)\n{\n    PyObject *v;\n    Py_ssize_t i;\n    if (n < 0)\n        return NULL;\n    /* Note that we can't bail immediately on error as this will leak\n       refcounts on any 'N' arguments. */\n    if ((v = PyTuple_New(n)) == NULL) {\n        do_ignore(p_format, p_va, endchar, n);\n        return NULL;\n    }\n    for (i = 0; i < n; i++) {\n        PyObject *w = do_mkvalue(p_format, p_va);\n        if (w == NULL) {\n            do_ignore(p_format, p_va, endchar, n - i - 1);\n            Py_DECREF(v);\n            return NULL;\n        }\n        PyTuple_SET_ITEM(v, i, w);\n    }\n    if (**p_format != endchar) {\n        Py_DECREF(v);\n        PyErr_SetString(PyExc_SystemError,\n                        \"Unmatched paren in format\");\n        return NULL;\n    }\n    if (endchar)\n        ++*p_format;\n    return v;\n}\n\nstatic PyObject *\ndo_mkvalue(const char **p_format, va_list *p_va)\n{\n    for (;;) {\n        switch (*(*p_format)++) {\n        case '(':\n            return do_mktuple(p_format, p_va, ')',\n                              countformat(*p_format, ')'));\n\n        case '[':\n            return do_mklist(p_format, p_va, ']',\n                             countformat(*p_format, ']'));\n\n        case '{':\n            return do_mkdict(p_format, p_va, '}',\n                             countformat(*p_format, '}'));\n\n        case 'b':\n        case 'B':\n        case 'h':\n        case 'i':\n            return PyLong_FromLong((long)va_arg(*p_va, int));\n\n        case 'H':\n            return PyLong_FromLong((long)va_arg(*p_va, unsigned int));\n\n        case 'I':\n        {\n            unsigned int n;\n            n = va_arg(*p_va, unsigned int);\n            return PyLong_FromUnsignedLong(n);\n        }\n\n        case 'n':\n#if SIZEOF_SIZE_T!=SIZEOF_LONG\n            return PyLong_FromSsize_t(va_arg(*p_va, Py_ssize_t));\n#endif\n            /* Fall through from 'n' to 'l' if Py_ssize_t is long */\n        case 'l':\n            return PyLong_FromLong(va_arg(*p_va, long));\n\n        case 'k':\n        {\n            unsigned long n;\n            n = va_arg(*p_va, unsigned long);\n            return PyLong_FromUnsignedLong(n);\n        }\n\n        case 'L':\n            return PyLong_FromLongLong((long long)va_arg(*p_va, long long));\n\n        case 'K':\n            return PyLong_FromUnsignedLongLong((long long)va_arg(*p_va, unsigned long long));\n\n        case 'u':\n        {\n            PyObject *v;\n            const wchar_t *u = va_arg(*p_va, wchar_t*);\n            Py_ssize_t n;\n            if (**p_format == '#') {\n                ++*p_format;\n                n = va_arg(*p_va, Py_ssize_t);\n            }\n            else\n                n = -1;\n            if (u == NULL) {\n                v = Py_NewRef(Py_None);\n            }\n            else {\n                if (n < 0)\n                    n = wcslen(u);\n                v = PyUnicode_FromWideChar(u, n);\n            }\n            return v;\n        }\n        case 'f':\n        case 'd':\n            return PyFloat_FromDouble(\n                (double)va_arg(*p_va, va_double));\n\n        case 'D':\n            return PyComplex_FromCComplex(\n                *((Py_complex *)va_arg(*p_va, Py_complex *)));\n\n        case 'c':\n        {\n            char p[1];\n            p[0] = (char)va_arg(*p_va, int);\n            return PyBytes_FromStringAndSize(p, 1);\n        }\n        case 'C':\n        {\n            int i = va_arg(*p_va, int);\n            return PyUnicode_FromOrdinal(i);\n        }\n\n        case 's':\n        case 'z':\n        case 'U':   /* XXX deprecated alias */\n        {\n            PyObject *v;\n            const char *str = va_arg(*p_va, const char *);\n            Py_ssize_t n;\n            if (**p_format == '#') {\n                ++*p_format;\n                n = va_arg(*p_va, Py_ssize_t);\n            }\n            else\n                n = -1;\n            if (str == NULL) {\n                v = Py_NewRef(Py_None);\n            }\n            else {\n                if (n < 0) {\n                    size_t m = strlen(str);\n                    if (m > PY_SSIZE_T_MAX) {\n                        PyErr_SetString(PyExc_OverflowError,\n                            \"string too long for Python string\");\n                        return NULL;\n                    }\n                    n = (Py_ssize_t)m;\n                }\n                v = PyUnicode_FromStringAndSize(str, n);\n            }\n            return v;\n        }\n\n        case 'y':\n        {\n            PyObject *v;\n            const char *str = va_arg(*p_va, const char *);\n            Py_ssize_t n;\n            if (**p_format == '#') {\n                ++*p_format;\n                n = va_arg(*p_va, Py_ssize_t);\n            }\n            else\n                n = -1;\n            if (str == NULL) {\n                v = Py_NewRef(Py_None);\n            }\n            else {\n                if (n < 0) {\n                    size_t m = strlen(str);\n                    if (m > PY_SSIZE_T_MAX) {\n                        PyErr_SetString(PyExc_OverflowError,\n                            \"string too long for Python bytes\");\n                        return NULL;\n                    }\n                    n = (Py_ssize_t)m;\n                }\n                v = PyBytes_FromStringAndSize(str, n);\n            }\n            return v;\n        }\n\n        case 'N':\n        case 'S':\n        case 'O':\n        if (**p_format == '&') {\n            typedef PyObject *(*converter)(void *);\n            converter func = va_arg(*p_va, converter);\n            void *arg = va_arg(*p_va, void *);\n            ++*p_format;\n            return (*func)(arg);\n        }\n        else {\n            PyObject *v;\n            v = va_arg(*p_va, PyObject *);\n            if (v != NULL) {\n                if (*(*p_format - 1) != 'N')\n                    Py_INCREF(v);\n            }\n            else if (!PyErr_Occurred())\n                /* If a NULL was passed\n                 * because a call that should\n                 * have constructed a value\n                 * failed, that's OK, and we\n                 * pass the error on; but if\n                 * no error occurred it's not\n                 * clear that the caller knew\n                 * what she was doing. */\n                PyErr_SetString(PyExc_SystemError,\n                    \"NULL object passed to Py_BuildValue\");\n            return v;\n        }\n\n        case ':':\n        case ',':\n        case ' ':\n        case '\\t':\n            break;\n\n        default:\n            PyErr_SetString(PyExc_SystemError,\n                \"bad format char passed to Py_BuildValue\");\n            return NULL;\n\n        }\n    }\n}\n\n\nPyObject *\nPy_BuildValue(const char *format, ...)\n{\n    va_list va;\n    PyObject* retval;\n    va_start(va, format);\n    retval = va_build_value(format, va);\n    va_end(va);\n    return retval;\n}\n\nPyAPI_FUNC(PyObject *) /* abi only */\n_Py_BuildValue_SizeT(const char *format, ...)\n{\n    va_list va;\n    PyObject* retval;\n    va_start(va, format);\n    retval = va_build_value(format, va);\n    va_end(va);\n    return retval;\n}\n\nPyObject *\nPy_VaBuildValue(const char *format, va_list va)\n{\n    return va_build_value(format, va);\n}\n\nPyAPI_FUNC(PyObject *) /* abi only */\n_Py_VaBuildValue_SizeT(const char *format, va_list va)\n{\n    return va_build_value(format, va);\n}\n\nstatic PyObject *\nva_build_value(const char *format, va_list va)\n{\n    const char *f = format;\n    Py_ssize_t n = countformat(f, '\\0');\n    va_list lva;\n    PyObject *retval;\n\n    if (n < 0)\n        return NULL;\n    if (n == 0) {\n        Py_RETURN_NONE;\n    }\n    va_copy(lva, va);\n    if (n == 1) {\n        retval = do_mkvalue(&f, &lva);\n    } else {\n        retval = do_mktuple(&f, &lva, '\\0', n);\n    }\n    va_end(lva);\n    return retval;\n}\n\nPyObject **\n_Py_VaBuildStack(PyObject **small_stack, Py_ssize_t small_stack_len,\n                const char *format, va_list va, Py_ssize_t *p_nargs)\n{\n    const char *f;\n    Py_ssize_t n;\n    va_list lva;\n    PyObject **stack;\n    int res;\n\n    n = countformat(format, '\\0');\n    if (n < 0) {\n        *p_nargs = 0;\n        return NULL;\n    }\n\n    if (n == 0) {\n        *p_nargs = 0;\n        return small_stack;\n    }\n\n    if (n <= small_stack_len) {\n        stack = small_stack;\n    }\n    else {\n        stack = PyMem_Malloc(n * sizeof(stack[0]));\n        if (stack == NULL) {\n            PyErr_NoMemory();\n            return NULL;\n        }\n    }\n\n    va_copy(lva, va);\n    f = format;\n    res = do_mkstack(stack, &f, &lva, '\\0', n);\n    va_end(lva);\n\n    if (res < 0) {\n        if (stack != small_stack) {\n            PyMem_Free(stack);\n        }\n        return NULL;\n    }\n\n    *p_nargs = n;\n    return stack;\n}\n\n\nint\nPyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value)\n{\n    if (!PyModule_Check(mod)) {\n        PyErr_SetString(PyExc_TypeError,\n                        \"PyModule_AddObjectRef() first argument \"\n                        \"must be a module\");\n        return -1;\n    }\n    if (!value) {\n        if (!PyErr_Occurred()) {\n            PyErr_SetString(PyExc_SystemError,\n                            \"PyModule_AddObjectRef() must be called \"\n                            \"with an exception raised if value is NULL\");\n        }\n        return -1;\n    }\n\n    PyObject *dict = PyModule_GetDict(mod);\n    if (dict == NULL) {\n        /* Internal error -- modules must have a dict! */\n        PyErr_Format(PyExc_SystemError, \"module '%s' has no __dict__\",\n                     PyModule_GetName(mod));\n        return -1;\n    }\n\n    if (PyDict_SetItemString(dict, name, value)) {\n        return -1;\n    }\n    return 0;\n}\n\n\nint\nPyModule_AddObject(PyObject *mod, const char *name, PyObject *value)\n{\n    int res = PyModule_AddObjectRef(mod, name, value);\n    if (res == 0) {\n        Py_DECREF(value);\n    }\n    return res;\n}\n\nint\nPyModule_AddIntConstant(PyObject *m, const char *name, long value)\n{\n    PyObject *obj = PyLong_FromLong(value);\n    if (!obj) {\n        return -1;\n    }\n    int res = PyModule_AddObjectRef(m, name, obj);\n    Py_DECREF(obj);\n    return res;\n}\n\nint\nPyModule_AddStringConstant(PyObject *m, const char *name, const char *value)\n{\n    PyObject *obj = PyUnicode_FromString(value);\n    if (!obj) {\n        return -1;\n    }\n    int res = PyModule_AddObjectRef(m, name, obj);\n    Py_DECREF(obj);\n    return res;\n}\n\nint\nPyModule_AddType(PyObject *module, PyTypeObject *type)\n{\n    if (!_PyType_IsReady(type) && PyType_Ready(type) < 0) {\n        return -1;\n    }\n\n    const char *name = _PyType_Name(type);\n    assert(name != NULL);\n\n    return PyModule_AddObjectRef(module, name, (PyObject *)type);\n}\n"
  },
  {
    "path": "MySnPrintf.c",
    "content": "#include \"Python.h\"\n\n/* snprintf() and vsnprintf() wrappers.\n\n   If the platform has vsnprintf, we use it, else we\n   emulate it in a half-hearted way.  Even if the platform has it, we wrap\n   it because platforms differ in what vsnprintf does in case the buffer\n   is too small:  C99 behavior is to return the number of characters that\n   would have been written had the buffer not been too small, and to set\n   the last byte of the buffer to \\0.  At least MS _vsnprintf returns a\n   negative value instead, and fills the entire buffer with non-\\0 data.\n   Unlike C99, our wrappers do not support passing a null buffer.\n\n   The wrappers ensure that str[size-1] is always \\0 upon return.\n\n   PyOS_snprintf and PyOS_vsnprintf never write more than size bytes\n   (including the trailing '\\0') into str.\n\n   Return value (rv):\n\n    When 0 <= rv < size, the output conversion was unexceptional, and\n    rv characters were written to str (excluding a trailing \\0 byte at\n    str[rv]).\n\n    When rv >= size, output conversion was truncated, and a buffer of\n    size rv+1 would have been needed to avoid truncation.  str[size-1]\n    is \\0 in this case.\n\n    When rv < 0, \"something bad happened\".  str[size-1] is \\0 in this\n    case too, but the rest of str is unreliable.  It could be that\n    an error in format codes was detected by libc, or on platforms\n    with a non-C99 vsnprintf simply that the buffer wasn't big enough\n    to avoid truncation, or on platforms without any vsnprintf that\n    PyMem_Malloc couldn't obtain space for a temp buffer.\n\n   CAUTION:  Unlike C99, str != NULL and size > 0 are required.\n   Also, size must be smaller than INT_MAX.\n*/\n\nint\nPyOS_snprintf(char *str, size_t size, const  char  *format, ...)\n{\n    int rc;\n    va_list va;\n\n    va_start(va, format);\n    rc = PyOS_vsnprintf(str, size, format, va);\n    va_end(va);\n    return rc;\n}\n\nint\nPyOS_vsnprintf(char *str, size_t size, const char  *format, va_list va)\n{\n    assert(str != NULL);\n    assert(size > 0);\n    assert(size <= (INT_MAX - 1));\n    assert(format != NULL);\n\n    int len;  /* # bytes written, excluding \\0 */\n    /* We take a size_t as input but return an int.  Sanity check\n     * our input so that it won't cause an overflow in the\n     * vsnprintf return value.  */\n    if (size > INT_MAX - 1) {\n        len = -666;\n        goto Done;\n    }\n\n#if defined(_MSC_VER)\n    len = _vsnprintf(str, size, format, va);\n#else\n    len = vsnprintf(str, size, format, va);\n#endif\n\nDone:\n    if (size > 0) {\n        str[size-1] = '\\0';\n    }\n    return len;\n}\n"
  },
  {
    "path": "MyStrtoul.c",
    "content": "#include \"Python.h\"\n#include \"pycore_long.h\"          // _PyLong_DigitValue\n\n#if defined(__sgi) && !defined(_SGI_MP_SOURCE)\n#define _SGI_MP_SOURCE\n#endif\n\n/* strtol and strtoul, renamed to avoid conflicts */\n\n\n#include <ctype.h>\n#ifdef HAVE_ERRNO_H\n#include <errno.h>\n#endif\n\n/* Static overflow check values for bases 2 through 36.\n * smallmax[base] is the largest unsigned long i such that\n * i * base doesn't overflow unsigned long.\n */\nstatic const unsigned long smallmax[] = {\n    0, /* bases 0 and 1 are invalid */\n    0,\n    ULONG_MAX / 2,\n    ULONG_MAX / 3,\n    ULONG_MAX / 4,\n    ULONG_MAX / 5,\n    ULONG_MAX / 6,\n    ULONG_MAX / 7,\n    ULONG_MAX / 8,\n    ULONG_MAX / 9,\n    ULONG_MAX / 10,\n    ULONG_MAX / 11,\n    ULONG_MAX / 12,\n    ULONG_MAX / 13,\n    ULONG_MAX / 14,\n    ULONG_MAX / 15,\n    ULONG_MAX / 16,\n    ULONG_MAX / 17,\n    ULONG_MAX / 18,\n    ULONG_MAX / 19,\n    ULONG_MAX / 20,\n    ULONG_MAX / 21,\n    ULONG_MAX / 22,\n    ULONG_MAX / 23,\n    ULONG_MAX / 24,\n    ULONG_MAX / 25,\n    ULONG_MAX / 26,\n    ULONG_MAX / 27,\n    ULONG_MAX / 28,\n    ULONG_MAX / 29,\n    ULONG_MAX / 30,\n    ULONG_MAX / 31,\n    ULONG_MAX / 32,\n    ULONG_MAX / 33,\n    ULONG_MAX / 34,\n    ULONG_MAX / 35,\n    ULONG_MAX / 36,\n};\n\n/* maximum digits that can't ever overflow for bases 2 through 36,\n * calculated by [int(math.floor(math.log(2**32, i))) for i in range(2, 37)].\n * Note that this is pessimistic if sizeof(long) > 4.\n */\n#if SIZEOF_LONG == 4\nstatic const int digitlimit[] = {\n    0,  0, 32, 20, 16, 13, 12, 11, 10, 10,  /*  0 -  9 */\n    9,  9,  8,  8,  8,  8,  8,  7,  7,  7,  /* 10 - 19 */\n    7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  /* 20 - 29 */\n    6,  6,  6,  6,  6,  6,  6};             /* 30 - 36 */\n#elif SIZEOF_LONG == 8\n/* [int(math.floor(math.log(2**64, i))) for i in range(2, 37)] */\nstatic const int digitlimit[] = {\n         0,   0, 64, 40, 32, 27, 24, 22, 21, 20,  /*  0 -  9 */\n    19,  18, 17, 17, 16, 16, 16, 15, 15, 15,  /* 10 - 19 */\n    14,  14, 14, 14, 13, 13, 13, 13, 13, 13,  /* 20 - 29 */\n    13,  12, 12, 12, 12, 12, 12};             /* 30 - 36 */\n#else\n#error \"Need table for SIZEOF_LONG\"\n#endif\n\n/*\n**      strtoul\n**              This is a general purpose routine for converting\n**              an ascii string to an integer in an arbitrary base.\n**              Leading white space is ignored.  If 'base' is zero\n**              it looks for a leading 0b, 0o or 0x to tell which\n**              base.  If these are absent it defaults to 10.\n**              Base must be 0 or between 2 and 36 (inclusive).\n**              If 'ptr' is non-NULL it will contain a pointer to\n**              the end of the scan.\n**              Errors due to bad pointers will probably result in\n**              exceptions - we don't check for them.\n*/\nunsigned long\nPyOS_strtoul(const char *str, char **ptr, int base)\n{\n    unsigned long result = 0; /* return value of the function */\n    int c;             /* current input character */\n    int ovlimit;       /* required digits to overflow */\n\n    /* skip leading white space */\n    while (*str && Py_ISSPACE(*str))\n        ++str;\n\n    /* check for leading 0b, 0o or 0x for auto-base or base 16 */\n    switch (base) {\n    case 0:             /* look for leading 0b, 0o or 0x */\n        if (*str == '0') {\n            ++str;\n            if (*str == 'x' || *str == 'X') {\n                /* there must be at least one digit after 0x */\n                if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {\n                    if (ptr)\n                        *ptr = (char *)str;\n                    return 0;\n                }\n                ++str;\n                base = 16;\n            } else if (*str == 'o' || *str == 'O') {\n                /* there must be at least one digit after 0o */\n                if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {\n                    if (ptr)\n                        *ptr = (char *)str;\n                    return 0;\n                }\n                ++str;\n                base = 8;\n            } else if (*str == 'b' || *str == 'B') {\n                /* there must be at least one digit after 0b */\n                if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {\n                    if (ptr)\n                        *ptr = (char *)str;\n                    return 0;\n                }\n                ++str;\n                base = 2;\n            } else {\n                /* skip all zeroes... */\n                while (*str == '0')\n                    ++str;\n                while (Py_ISSPACE(*str))\n                    ++str;\n                if (ptr)\n                    *ptr = (char *)str;\n                return 0;\n            }\n        }\n        else\n            base = 10;\n        break;\n\n    /* even with explicit base, skip leading 0? prefix */\n    case 16:\n        if (*str == '0') {\n            ++str;\n            if (*str == 'x' || *str == 'X') {\n                /* there must be at least one digit after 0x */\n                if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {\n                    if (ptr)\n                        *ptr = (char *)str;\n                    return 0;\n                }\n                ++str;\n            }\n        }\n        break;\n    case 8:\n        if (*str == '0') {\n            ++str;\n            if (*str == 'o' || *str == 'O') {\n                /* there must be at least one digit after 0o */\n                if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {\n                    if (ptr)\n                        *ptr = (char *)str;\n                    return 0;\n                }\n                ++str;\n            }\n        }\n        break;\n    case 2:\n        if(*str == '0') {\n            ++str;\n            if (*str == 'b' || *str == 'B') {\n                /* there must be at least one digit after 0b */\n                if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {\n                    if (ptr)\n                        *ptr = (char *)str;\n                    return 0;\n                }\n                ++str;\n            }\n        }\n        break;\n    }\n\n    /* catch silly bases */\n    if (base < 2 || base > 36) {\n        if (ptr)\n            *ptr = (char *)str;\n        return 0;\n    }\n\n    /* skip leading zeroes */\n    while (*str == '0')\n        ++str;\n\n    /* base is guaranteed to be in [2, 36] at this point */\n    ovlimit = digitlimit[base];\n\n    /* do the conversion until non-digit character encountered */\n    while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {\n        if (ovlimit > 0) /* no overflow check required */\n            result = result * base + c;\n        else { /* requires overflow check */\n            unsigned long temp_result;\n\n            if (ovlimit < 0) /* guaranteed overflow */\n                goto overflowed;\n\n            /* there could be an overflow */\n            /* check overflow just from shifting */\n            if (result > smallmax[base])\n                goto overflowed;\n\n            result *= base;\n\n            /* check overflow from the digit's value */\n            temp_result = result + c;\n            if (temp_result < result)\n                goto overflowed;\n\n            result = temp_result;\n        }\n\n        ++str;\n        --ovlimit;\n    }\n\n    /* set pointer to point to the last character scanned */\n    if (ptr)\n        *ptr = (char *)str;\n\n    return result;\n\noverflowed:\n    if (ptr) {\n        /* spool through remaining digit characters */\n        while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)\n            ++str;\n        *ptr = (char *)str;\n    }\n    errno = ERANGE;\n    return (unsigned long)-1;\n}\n\n/* Checking for overflow in PyOS_strtol is a PITA; see comments\n * about PY_ABS_LONG_MIN in longobject.c.\n */\n#define PY_ABS_LONG_MIN         (0-(unsigned long)LONG_MIN)\n\nlong\nPyOS_strtol(const char *str, char **ptr, int base)\n{\n    long result;\n    unsigned long uresult;\n    char sign;\n\n    while (*str && Py_ISSPACE(*str))\n        str++;\n\n    sign = *str;\n    if (sign == '+' || sign == '-')\n        str++;\n\n    uresult = PyOS_strtoul(str, ptr, base);\n\n    if (uresult <= (unsigned long)LONG_MAX) {\n        result = (long)uresult;\n        if (sign == '-')\n            result = -result;\n    }\n    else if (sign == '-' && uresult == PY_ABS_LONG_MIN) {\n        result = LONG_MIN;\n    }\n    else {\n        errno = ERANGE;\n        result = LONG_MAX;\n    }\n    return result;\n}\n"
  },
  {
    "path": "OpCode_MetaData.h",
    "content": "// This file is generated by Tools/cases_generator/generate_cases.py\n// from:\n//   Python/bytecodes.c\n// Do not edit!\n\n#ifndef NEED_OPCODE_METADATA\nextern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);\n#else\nint\n_PyOpcode_num_popped(int opcode, int oparg, bool jump) {\n    switch(opcode) {\n        case NOP:\n            return 0;\n        case RESUME:\n            return 0;\n        case INSTRUMENTED_RESUME:\n            return 0;\n        case LOAD_CLOSURE:\n            return 0;\n        case LOAD_FAST_CHECK:\n            return 0;\n        case LOAD_FAST:\n            return 0;\n        case LOAD_FAST_AND_CLEAR:\n            return 0;\n        case LOAD_CONST:\n            return 0;\n        case STORE_FAST:\n            return 1;\n        case LOAD_FAST__LOAD_FAST:\n            return 0+0;\n        case LOAD_FAST__LOAD_CONST:\n            return 0+0;\n        case STORE_FAST__LOAD_FAST:\n            return 1+0;\n        case STORE_FAST__STORE_FAST:\n            return 1+1;\n        case LOAD_CONST__LOAD_FAST:\n            return 0+0;\n        case POP_TOP:\n            return 1;\n        case PUSH_NULL:\n            return 0;\n        case END_FOR:\n            return 2;\n        case INSTRUMENTED_END_FOR:\n            return 2;\n        case END_SEND:\n            return 2;\n        case INSTRUMENTED_END_SEND:\n            return 2;\n        case UNARY_NEGATIVE:\n            return 1;\n        case UNARY_NOT:\n            return 1;\n        case UNARY_INVERT:\n            return 1;\n        case BINARY_OP_MULTIPLY_INT:\n            return 2;\n        case BINARY_OP_ADD_INT:\n            return 2;\n        case BINARY_OP_SUBTRACT_INT:\n            return 2;\n        case BINARY_OP_MULTIPLY_FLOAT:\n            return 2;\n        case BINARY_OP_ADD_FLOAT:\n            return 2;\n        case BINARY_OP_SUBTRACT_FLOAT:\n            return 2;\n        case BINARY_OP_ADD_UNICODE:\n            return 2;\n        case BINARY_OP_INPLACE_ADD_UNICODE:\n            return 2;\n        case BINARY_SUBSCR:\n            return 2;\n        case BINARY_SLICE:\n            return 3;\n        case STORE_SLICE:\n            return 4;\n        case BINARY_SUBSCR_LIST_INT:\n            return 2;\n        case BINARY_SUBSCR_TUPLE_INT:\n            return 2;\n        case BINARY_SUBSCR_DICT:\n            return 2;\n        case BINARY_SUBSCR_GETITEM:\n            return 2;\n        case LIST_APPEND:\n            return (oparg-1) + 2;\n        case SET_ADD:\n            return (oparg-1) + 2;\n        case STORE_SUBSCR:\n            return 3;\n        case STORE_SUBSCR_LIST_INT:\n            return 3;\n        case STORE_SUBSCR_DICT:\n            return 3;\n        case DELETE_SUBSCR:\n            return 2;\n        case CALL_INTRINSIC_1:\n            return 1;\n        case CALL_INTRINSIC_2:\n            return 2;\n        case RAISE_VARARGS:\n            return oparg;\n        case INTERPRETER_EXIT:\n            return 1;\n        case RETURN_VALUE:\n            return 1;\n        case INSTRUMENTED_RETURN_VALUE:\n            return 1;\n        case RETURN_CONST:\n            return 0;\n        case INSTRUMENTED_RETURN_CONST:\n            return 0;\n        case GET_AITER:\n            return 1;\n        case GET_ANEXT:\n            return 1;\n        case GET_AWAITABLE:\n            return 1;\n        case SEND:\n            return 2;\n        case SEND_GEN:\n            return 2;\n        case INSTRUMENTED_YIELD_VALUE:\n            return 1;\n        case YIELD_VALUE:\n            return 1;\n        case POP_EXCEPT:\n            return 1;\n        case RERAISE:\n            return oparg + 1;\n        case END_ASYNC_FOR:\n            return 2;\n        case CLEANUP_THROW:\n            return 3;\n        case LOAD_ASSERTION_ERROR:\n            return 0;\n        case LOAD_BUILD_CLASS:\n            return 0;\n        case STORE_NAME:\n            return 1;\n        case DELETE_NAME:\n            return 0;\n        case UNPACK_SEQUENCE:\n            return 1;\n        case UNPACK_SEQUENCE_TWO_TUPLE:\n            return 1;\n        case UNPACK_SEQUENCE_TUPLE:\n            return 1;\n        case UNPACK_SEQUENCE_LIST:\n            return 1;\n        case UNPACK_EX:\n            return 1;\n        case STORE_ATTR:\n            return 2;\n        case DELETE_ATTR:\n            return 1;\n        case STORE_GLOBAL:\n            return 1;\n        case DELETE_GLOBAL:\n            return 0;\n        case LOAD_LOCALS:\n            return 0;\n        case LOAD_NAME:\n            return 0;\n        case LOAD_FROM_DICT_OR_GLOBALS:\n            return 1;\n        case LOAD_GLOBAL:\n            return 0;\n        case LOAD_GLOBAL_MODULE:\n            return 0;\n        case LOAD_GLOBAL_BUILTIN:\n            return 0;\n        case DELETE_FAST:\n            return 0;\n        case MAKE_CELL:\n            return 0;\n        case DELETE_DEREF:\n            return 0;\n        case LOAD_FROM_DICT_OR_DEREF:\n            return 1;\n        case LOAD_DEREF:\n            return 0;\n        case STORE_DEREF:\n            return 1;\n        case COPY_FREE_VARS:\n            return 0;\n        case BUILD_STRING:\n            return oparg;\n        case BUILD_TUPLE:\n            return oparg;\n        case BUILD_LIST:\n            return oparg;\n        case LIST_EXTEND:\n            return (oparg-1) + 2;\n        case SET_UPDATE:\n            return (oparg-1) + 2;\n        case BUILD_SET:\n            return oparg;\n        case BUILD_MAP:\n            return oparg*2;\n        case SETUP_ANNOTATIONS:\n            return 0;\n        case BUILD_CONST_KEY_MAP:\n            return oparg + 1;\n        case DICT_UPDATE:\n            return 1;\n        case DICT_MERGE:\n            return 1;\n        case MAP_ADD:\n            return 2;\n        case INSTRUMENTED_LOAD_SUPER_ATTR:\n            return 3;\n        case LOAD_SUPER_ATTR:\n            return 3;\n        case LOAD_SUPER_ATTR_ATTR:\n            return 3;\n        case LOAD_SUPER_ATTR_METHOD:\n            return 3;\n        case LOAD_ATTR:\n            return 1;\n        case LOAD_ATTR_INSTANCE_VALUE:\n            return 1;\n        case LOAD_ATTR_MODULE:\n            return 1;\n        case LOAD_ATTR_WITH_HINT:\n            return 1;\n        case LOAD_ATTR_SLOT:\n            return 1;\n        case LOAD_ATTR_CLASS:\n            return 1;\n        case LOAD_ATTR_PROPERTY:\n            return 1;\n        case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN:\n            return 1;\n        case STORE_ATTR_INSTANCE_VALUE:\n            return 2;\n        case STORE_ATTR_WITH_HINT:\n            return 2;\n        case STORE_ATTR_SLOT:\n            return 2;\n        case COMPARE_OP:\n            return 2;\n        case COMPARE_OP_FLOAT:\n            return 2;\n        case COMPARE_OP_INT:\n            return 2;\n        case COMPARE_OP_STR:\n            return 2;\n        case IS_OP:\n            return 2;\n        case CONTAINS_OP:\n            return 2;\n        case CHECK_EG_MATCH:\n            return 2;\n        case CHECK_EXC_MATCH:\n            return 2;\n        case IMPORT_NAME:\n            return 2;\n        case IMPORT_FROM:\n            return 1;\n        case JUMP_FORWARD:\n            return 0;\n        case JUMP_BACKWARD:\n            return 0;\n        case POP_JUMP_IF_FALSE:\n            return 1;\n        case POP_JUMP_IF_TRUE:\n            return 1;\n        case POP_JUMP_IF_NOT_NONE:\n            return 1;\n        case POP_JUMP_IF_NONE:\n            return 1;\n        case JUMP_BACKWARD_NO_INTERRUPT:\n            return 0;\n        case GET_LEN:\n            return 1;\n        case MATCH_CLASS:\n            return 3;\n        case MATCH_MAPPING:\n            return 1;\n        case MATCH_SEQUENCE:\n            return 1;\n        case MATCH_KEYS:\n            return 2;\n        case GET_ITER:\n            return 1;\n        case GET_YIELD_FROM_ITER:\n            return 1;\n        case FOR_ITER:\n            return 1;\n        case INSTRUMENTED_FOR_ITER:\n            return 0;\n        case FOR_ITER_LIST:\n            return 1;\n        case FOR_ITER_TUPLE:\n            return 1;\n        case FOR_ITER_RANGE:\n            return 1;\n        case FOR_ITER_GEN:\n            return 1;\n        case BEFORE_ASYNC_WITH:\n            return 1;\n        case BEFORE_WITH:\n            return 1;\n        case WITH_EXCEPT_START:\n            return 4;\n        case PUSH_EXC_INFO:\n            return 1;\n        case LOAD_ATTR_METHOD_WITH_VALUES:\n            return 1;\n        case LOAD_ATTR_METHOD_NO_DICT:\n            return 1;\n        case LOAD_ATTR_METHOD_LAZY_DICT:\n            return 1;\n        case KW_NAMES:\n            return 0;\n        case INSTRUMENTED_CALL:\n            return 0;\n        case CALL:\n            return oparg + 2;\n        case CALL_BOUND_METHOD_EXACT_ARGS:\n            return oparg + 2;\n        case CALL_PY_EXACT_ARGS:\n            return oparg + 2;\n        case CALL_PY_WITH_DEFAULTS:\n            return oparg + 2;\n        case CALL_NO_KW_TYPE_1:\n            return oparg + 2;\n        case CALL_NO_KW_STR_1:\n            return oparg + 2;\n        case CALL_NO_KW_TUPLE_1:\n            return oparg + 2;\n        case CALL_BUILTIN_CLASS:\n            return oparg + 2;\n        case CALL_NO_KW_BUILTIN_O:\n            return oparg + 2;\n        case CALL_NO_KW_BUILTIN_FAST:\n            return oparg + 2;\n        case CALL_BUILTIN_FAST_WITH_KEYWORDS:\n            return oparg + 2;\n        case CALL_NO_KW_LEN:\n            return oparg + 2;\n        case CALL_NO_KW_ISINSTANCE:\n            return oparg + 2;\n        case CALL_NO_KW_LIST_APPEND:\n            return oparg + 2;\n        case CALL_NO_KW_METHOD_DESCRIPTOR_O:\n            return oparg + 2;\n        case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS:\n            return oparg + 2;\n        case CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS:\n            return oparg + 2;\n        case CALL_NO_KW_METHOD_DESCRIPTOR_FAST:\n            return oparg + 2;\n        case INSTRUMENTED_CALL_FUNCTION_EX:\n            return 0;\n        case CALL_FUNCTION_EX:\n            return ((oparg & 1) ? 1 : 0) + 3;\n        case MAKE_FUNCTION:\n            return ((oparg & 0x01) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x08) ? 1 : 0) + 1;\n        case RETURN_GENERATOR:\n            return 0;\n        case BUILD_SLICE:\n            return ((oparg == 3) ? 1 : 0) + 2;\n        case FORMAT_VALUE:\n            return (((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0) + 1;\n        case COPY:\n            return (oparg-1) + 1;\n        case BINARY_OP:\n            return 2;\n        case SWAP:\n            return (oparg-2) + 2;\n        case INSTRUMENTED_INSTRUCTION:\n            return 0;\n        case INSTRUMENTED_JUMP_FORWARD:\n            return 0;\n        case INSTRUMENTED_JUMP_BACKWARD:\n            return 0;\n        case INSTRUMENTED_POP_JUMP_IF_TRUE:\n            return 0;\n        case INSTRUMENTED_POP_JUMP_IF_FALSE:\n            return 0;\n        case INSTRUMENTED_POP_JUMP_IF_NONE:\n            return 0;\n        case INSTRUMENTED_POP_JUMP_IF_NOT_NONE:\n            return 0;\n        case EXTENDED_ARG:\n            return 0;\n        case CACHE:\n            return 0;\n        case RESERVED:\n            return 0;\n        default:\n            return -1;\n    }\n}\n#endif\n\n#ifndef NEED_OPCODE_METADATA\nextern int _PyOpcode_num_pushed(int opcode, int oparg, bool jump);\n#else\nint\n_PyOpcode_num_pushed(int opcode, int oparg, bool jump) {\n    switch(opcode) {\n        case NOP:\n            return 0;\n        case RESUME:\n            return 0;\n        case INSTRUMENTED_RESUME:\n            return 0;\n        case LOAD_CLOSURE:\n            return 1;\n        case LOAD_FAST_CHECK:\n            return 1;\n        case LOAD_FAST:\n            return 1;\n        case LOAD_FAST_AND_CLEAR:\n            return 1;\n        case LOAD_CONST:\n            return 1;\n        case STORE_FAST:\n            return 0;\n        case LOAD_FAST__LOAD_FAST:\n            return 1+1;\n        case LOAD_FAST__LOAD_CONST:\n            return 1+1;\n        case STORE_FAST__LOAD_FAST:\n            return 0+1;\n        case STORE_FAST__STORE_FAST:\n            return 0+0;\n        case LOAD_CONST__LOAD_FAST:\n            return 1+1;\n        case POP_TOP:\n            return 0;\n        case PUSH_NULL:\n            return 1;\n        case END_FOR:\n            return 0;\n        case INSTRUMENTED_END_FOR:\n            return 0;\n        case END_SEND:\n            return 1;\n        case INSTRUMENTED_END_SEND:\n            return 1;\n        case UNARY_NEGATIVE:\n            return 1;\n        case UNARY_NOT:\n            return 1;\n        case UNARY_INVERT:\n            return 1;\n        case BINARY_OP_MULTIPLY_INT:\n            return 1;\n        case BINARY_OP_ADD_INT:\n            return 1;\n        case BINARY_OP_SUBTRACT_INT:\n            return 1;\n        case BINARY_OP_MULTIPLY_FLOAT:\n            return 1;\n        case BINARY_OP_ADD_FLOAT:\n            return 1;\n        case BINARY_OP_SUBTRACT_FLOAT:\n            return 1;\n        case BINARY_OP_ADD_UNICODE:\n            return 1;\n        case BINARY_OP_INPLACE_ADD_UNICODE:\n            return 0;\n        case BINARY_SUBSCR:\n            return 1;\n        case BINARY_SLICE:\n            return 1;\n        case STORE_SLICE:\n            return 0;\n        case BINARY_SUBSCR_LIST_INT:\n            return 1;\n        case BINARY_SUBSCR_TUPLE_INT:\n            return 1;\n        case BINARY_SUBSCR_DICT:\n            return 1;\n        case BINARY_SUBSCR_GETITEM:\n            return 1;\n        case LIST_APPEND:\n            return (oparg-1) + 1;\n        case SET_ADD:\n            return (oparg-1) + 1;\n        case STORE_SUBSCR:\n            return 0;\n        case STORE_SUBSCR_LIST_INT:\n            return 0;\n        case STORE_SUBSCR_DICT:\n            return 0;\n        case DELETE_SUBSCR:\n            return 0;\n        case CALL_INTRINSIC_1:\n            return 1;\n        case CALL_INTRINSIC_2:\n            return 1;\n        case RAISE_VARARGS:\n            return 0;\n        case INTERPRETER_EXIT:\n            return 0;\n        case RETURN_VALUE:\n            return 0;\n        case INSTRUMENTED_RETURN_VALUE:\n            return 0;\n        case RETURN_CONST:\n            return 0;\n        case INSTRUMENTED_RETURN_CONST:\n            return 0;\n        case GET_AITER:\n            return 1;\n        case GET_ANEXT:\n            return 2;\n        case GET_AWAITABLE:\n            return 1;\n        case SEND:\n            return 2;\n        case SEND_GEN:\n            return 2;\n        case INSTRUMENTED_YIELD_VALUE:\n            return 1;\n        case YIELD_VALUE:\n            return 1;\n        case POP_EXCEPT:\n            return 0;\n        case RERAISE:\n            return oparg;\n        case END_ASYNC_FOR:\n            return 0;\n        case CLEANUP_THROW:\n            return 2;\n        case LOAD_ASSERTION_ERROR:\n            return 1;\n        case LOAD_BUILD_CLASS:\n            return 1;\n        case STORE_NAME:\n            return 0;\n        case DELETE_NAME:\n            return 0;\n        case UNPACK_SEQUENCE:\n            return oparg;\n        case UNPACK_SEQUENCE_TWO_TUPLE:\n            return oparg;\n        case UNPACK_SEQUENCE_TUPLE:\n            return oparg;\n        case UNPACK_SEQUENCE_LIST:\n            return oparg;\n        case UNPACK_EX:\n            return (oparg & 0xFF) + (oparg >> 8) + 1;\n        case STORE_ATTR:\n            return 0;\n        case DELETE_ATTR:\n            return 0;\n        case STORE_GLOBAL:\n            return 0;\n        case DELETE_GLOBAL:\n            return 0;\n        case LOAD_LOCALS:\n            return 1;\n        case LOAD_NAME:\n            return 1;\n        case LOAD_FROM_DICT_OR_GLOBALS:\n            return 1;\n        case LOAD_GLOBAL:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_GLOBAL_MODULE:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_GLOBAL_BUILTIN:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case DELETE_FAST:\n            return 0;\n        case MAKE_CELL:\n            return 0;\n        case DELETE_DEREF:\n            return 0;\n        case LOAD_FROM_DICT_OR_DEREF:\n            return 1;\n        case LOAD_DEREF:\n            return 1;\n        case STORE_DEREF:\n            return 0;\n        case COPY_FREE_VARS:\n            return 0;\n        case BUILD_STRING:\n            return 1;\n        case BUILD_TUPLE:\n            return 1;\n        case BUILD_LIST:\n            return 1;\n        case LIST_EXTEND:\n            return (oparg-1) + 1;\n        case SET_UPDATE:\n            return (oparg-1) + 1;\n        case BUILD_SET:\n            return 1;\n        case BUILD_MAP:\n            return 1;\n        case SETUP_ANNOTATIONS:\n            return 0;\n        case BUILD_CONST_KEY_MAP:\n            return 1;\n        case DICT_UPDATE:\n            return 0;\n        case DICT_MERGE:\n            return 0;\n        case MAP_ADD:\n            return 0;\n        case INSTRUMENTED_LOAD_SUPER_ATTR:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_SUPER_ATTR:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_SUPER_ATTR_ATTR:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_SUPER_ATTR_METHOD:\n            return 2;\n        case LOAD_ATTR:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_ATTR_INSTANCE_VALUE:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_ATTR_MODULE:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_ATTR_WITH_HINT:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_ATTR_SLOT:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_ATTR_CLASS:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_ATTR_PROPERTY:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case STORE_ATTR_INSTANCE_VALUE:\n            return 0;\n        case STORE_ATTR_WITH_HINT:\n            return 0;\n        case STORE_ATTR_SLOT:\n            return 0;\n        case COMPARE_OP:\n            return 1;\n        case COMPARE_OP_FLOAT:\n            return 1;\n        case COMPARE_OP_INT:\n            return 1;\n        case COMPARE_OP_STR:\n            return 1;\n        case IS_OP:\n            return 1;\n        case CONTAINS_OP:\n            return 1;\n        case CHECK_EG_MATCH:\n            return 2;\n        case CHECK_EXC_MATCH:\n            return 2;\n        case IMPORT_NAME:\n            return 1;\n        case IMPORT_FROM:\n            return 2;\n        case JUMP_FORWARD:\n            return 0;\n        case JUMP_BACKWARD:\n            return 0;\n        case POP_JUMP_IF_FALSE:\n            return 0;\n        case POP_JUMP_IF_TRUE:\n            return 0;\n        case POP_JUMP_IF_NOT_NONE:\n            return 0;\n        case POP_JUMP_IF_NONE:\n            return 0;\n        case JUMP_BACKWARD_NO_INTERRUPT:\n            return 0;\n        case GET_LEN:\n            return 2;\n        case MATCH_CLASS:\n            return 1;\n        case MATCH_MAPPING:\n            return 2;\n        case MATCH_SEQUENCE:\n            return 2;\n        case MATCH_KEYS:\n            return 3;\n        case GET_ITER:\n            return 1;\n        case GET_YIELD_FROM_ITER:\n            return 1;\n        case FOR_ITER:\n            return 2;\n        case INSTRUMENTED_FOR_ITER:\n            return 0;\n        case FOR_ITER_LIST:\n            return 2;\n        case FOR_ITER_TUPLE:\n            return 2;\n        case FOR_ITER_RANGE:\n            return 2;\n        case FOR_ITER_GEN:\n            return 2;\n        case BEFORE_ASYNC_WITH:\n            return 2;\n        case BEFORE_WITH:\n            return 2;\n        case WITH_EXCEPT_START:\n            return 5;\n        case PUSH_EXC_INFO:\n            return 2;\n        case LOAD_ATTR_METHOD_WITH_VALUES:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_ATTR_METHOD_NO_DICT:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case LOAD_ATTR_METHOD_LAZY_DICT:\n            return ((oparg & 1) ? 1 : 0) + 1;\n        case KW_NAMES:\n            return 0;\n        case INSTRUMENTED_CALL:\n            return 0;\n        case CALL:\n            return 1;\n        case CALL_BOUND_METHOD_EXACT_ARGS:\n            return 1;\n        case CALL_PY_EXACT_ARGS:\n            return 1;\n        case CALL_PY_WITH_DEFAULTS:\n            return 1;\n        case CALL_NO_KW_TYPE_1:\n            return 1;\n        case CALL_NO_KW_STR_1:\n            return 1;\n        case CALL_NO_KW_TUPLE_1:\n            return 1;\n        case CALL_BUILTIN_CLASS:\n            return 1;\n        case CALL_NO_KW_BUILTIN_O:\n            return 1;\n        case CALL_NO_KW_BUILTIN_FAST:\n            return 1;\n        case CALL_BUILTIN_FAST_WITH_KEYWORDS:\n            return 1;\n        case CALL_NO_KW_LEN:\n            return 1;\n        case CALL_NO_KW_ISINSTANCE:\n            return 1;\n        case CALL_NO_KW_LIST_APPEND:\n            return 1;\n        case CALL_NO_KW_METHOD_DESCRIPTOR_O:\n            return 1;\n        case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS:\n            return 1;\n        case CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS:\n            return 1;\n        case CALL_NO_KW_METHOD_DESCRIPTOR_FAST:\n            return 1;\n        case INSTRUMENTED_CALL_FUNCTION_EX:\n            return 0;\n        case CALL_FUNCTION_EX:\n            return 1;\n        case MAKE_FUNCTION:\n            return 1;\n        case RETURN_GENERATOR:\n            return 0;\n        case BUILD_SLICE:\n            return 1;\n        case FORMAT_VALUE:\n            return 1;\n        case COPY:\n            return (oparg-1) + 2;\n        case BINARY_OP:\n            return 1;\n        case SWAP:\n            return (oparg-2) + 2;\n        case INSTRUMENTED_INSTRUCTION:\n            return 0;\n        case INSTRUMENTED_JUMP_FORWARD:\n            return 0;\n        case INSTRUMENTED_JUMP_BACKWARD:\n            return 0;\n        case INSTRUMENTED_POP_JUMP_IF_TRUE:\n            return 0;\n        case INSTRUMENTED_POP_JUMP_IF_FALSE:\n            return 0;\n        case INSTRUMENTED_POP_JUMP_IF_NONE:\n            return 0;\n        case INSTRUMENTED_POP_JUMP_IF_NOT_NONE:\n            return 0;\n        case EXTENDED_ARG:\n            return 0;\n        case CACHE:\n            return 0;\n        case RESERVED:\n            return 0;\n        default:\n            return -1;\n    }\n}\n#endif\n\nenum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC00, INSTR_FMT_IBC000, INSTR_FMT_IBC00000000, INSTR_FMT_IBIB, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 };\nstruct opcode_metadata {\n    bool valid_entry;\n    enum InstructionFormat instr_format;\n};\n\n#ifndef NEED_OPCODE_METADATA\nextern const struct opcode_metadata _PyOpcode_opcode_metadata[256];\n#else\nconst struct opcode_metadata _PyOpcode_opcode_metadata[256] = {\n    [NOP] = { true, INSTR_FMT_IX },\n    [RESUME] = { true, INSTR_FMT_IB },\n    [INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB },\n    [LOAD_CLOSURE] = { true, INSTR_FMT_IB },\n    [LOAD_FAST_CHECK] = { true, INSTR_FMT_IB },\n    [LOAD_FAST] = { true, INSTR_FMT_IB },\n    [LOAD_FAST_AND_CLEAR] = { true, INSTR_FMT_IB },\n    [LOAD_CONST] = { true, INSTR_FMT_IB },\n    [STORE_FAST] = { true, INSTR_FMT_IB },\n    [LOAD_FAST__LOAD_FAST] = { true, INSTR_FMT_IBIB },\n    [LOAD_FAST__LOAD_CONST] = { true, INSTR_FMT_IBIB },\n    [STORE_FAST__LOAD_FAST] = { true, INSTR_FMT_IBIB },\n    [STORE_FAST__STORE_FAST] = { true, INSTR_FMT_IBIB },\n    [LOAD_CONST__LOAD_FAST] = { true, INSTR_FMT_IBIB },\n    [POP_TOP] = { true, INSTR_FMT_IX },\n    [PUSH_NULL] = { true, INSTR_FMT_IX },\n    [END_FOR] = { true, INSTR_FMT_IB },\n    [INSTRUMENTED_END_FOR] = { true, INSTR_FMT_IX },\n    [END_SEND] = { true, INSTR_FMT_IX },\n    [INSTRUMENTED_END_SEND] = { true, INSTR_FMT_IX },\n    [UNARY_NEGATIVE] = { true, INSTR_FMT_IX },\n    [UNARY_NOT] = { true, INSTR_FMT_IX },\n    [UNARY_INVERT] = { true, INSTR_FMT_IX },\n    [BINARY_OP_MULTIPLY_INT] = { true, INSTR_FMT_IBC },\n    [BINARY_OP_ADD_INT] = { true, INSTR_FMT_IBC },\n    [BINARY_OP_SUBTRACT_INT] = { true, INSTR_FMT_IBC },\n    [BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IBC },\n    [BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IBC },\n    [BINARY_OP_SUBTRACT_FLOAT] = { true, INSTR_FMT_IBC },\n    [BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IBC },\n    [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IB },\n    [BINARY_SUBSCR] = { true, INSTR_FMT_IXC },\n    [BINARY_SLICE] = { true, INSTR_FMT_IX },\n    [STORE_SLICE] = { true, INSTR_FMT_IX },\n    [BINARY_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC },\n    [BINARY_SUBSCR_TUPLE_INT] = { true, INSTR_FMT_IXC },\n    [BINARY_SUBSCR_DICT] = { true, INSTR_FMT_IXC },\n    [BINARY_SUBSCR_GETITEM] = { true, INSTR_FMT_IXC },\n    [LIST_APPEND] = { true, INSTR_FMT_IB },\n    [SET_ADD] = { true, INSTR_FMT_IB },\n    [STORE_SUBSCR] = { true, INSTR_FMT_IXC },\n    [STORE_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC },\n    [STORE_SUBSCR_DICT] = { true, INSTR_FMT_IXC },\n    [DELETE_SUBSCR] = { true, INSTR_FMT_IX },\n    [CALL_INTRINSIC_1] = { true, INSTR_FMT_IB },\n    [CALL_INTRINSIC_2] = { true, INSTR_FMT_IB },\n    [RAISE_VARARGS] = { true, INSTR_FMT_IB },\n    [INTERPRETER_EXIT] = { true, INSTR_FMT_IX },\n    [RETURN_VALUE] = { true, INSTR_FMT_IX },\n    [INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX },\n    [RETURN_CONST] = { true, INSTR_FMT_IB },\n    [INSTRUMENTED_RETURN_CONST] = { true, INSTR_FMT_IB },\n    [GET_AITER] = { true, INSTR_FMT_IX },\n    [GET_ANEXT] = { true, INSTR_FMT_IX },\n    [GET_AWAITABLE] = { true, INSTR_FMT_IB },\n    [SEND] = { true, INSTR_FMT_IBC },\n    [SEND_GEN] = { true, INSTR_FMT_IBC },\n    [INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IX },\n    [YIELD_VALUE] = { true, INSTR_FMT_IX },\n    [POP_EXCEPT] = { true, INSTR_FMT_IX },\n    [RERAISE] = { true, INSTR_FMT_IB },\n    [END_ASYNC_FOR] = { true, INSTR_FMT_IX },\n    [CLEANUP_THROW] = { true, INSTR_FMT_IX },\n    [LOAD_ASSERTION_ERROR] = { true, INSTR_FMT_IX },\n    [LOAD_BUILD_CLASS] = { true, INSTR_FMT_IX },\n    [STORE_NAME] = { true, INSTR_FMT_IB },\n    [DELETE_NAME] = { true, INSTR_FMT_IB },\n    [UNPACK_SEQUENCE] = { true, INSTR_FMT_IBC },\n    [UNPACK_SEQUENCE_TWO_TUPLE] = { true, INSTR_FMT_IBC },\n    [UNPACK_SEQUENCE_TUPLE] = { true, INSTR_FMT_IBC },\n    [UNPACK_SEQUENCE_LIST] = { true, INSTR_FMT_IBC },\n    [UNPACK_EX] = { true, INSTR_FMT_IB },\n    [STORE_ATTR] = { true, INSTR_FMT_IBC000 },\n    [DELETE_ATTR] = { true, INSTR_FMT_IB },\n    [STORE_GLOBAL] = { true, INSTR_FMT_IB },\n    [DELETE_GLOBAL] = { true, INSTR_FMT_IB },\n    [LOAD_LOCALS] = { true, INSTR_FMT_IB },\n    [LOAD_NAME] = { true, INSTR_FMT_IB },\n    [LOAD_FROM_DICT_OR_GLOBALS] = { true, INSTR_FMT_IB },\n    [LOAD_GLOBAL] = { true, INSTR_FMT_IBC000 },\n    [LOAD_GLOBAL_MODULE] = { true, INSTR_FMT_IBC000 },\n    [LOAD_GLOBAL_BUILTIN] = { true, INSTR_FMT_IBC000 },\n    [DELETE_FAST] = { true, INSTR_FMT_IB },\n    [MAKE_CELL] = { true, INSTR_FMT_IB },\n    [DELETE_DEREF] = { true, INSTR_FMT_IB },\n    [LOAD_FROM_DICT_OR_DEREF] = { true, INSTR_FMT_IB },\n    [LOAD_DEREF] = { true, INSTR_FMT_IB },\n    [STORE_DEREF] = { true, INSTR_FMT_IB },\n    [COPY_FREE_VARS] = { true, INSTR_FMT_IB },\n    [BUILD_STRING] = { true, INSTR_FMT_IB },\n    [BUILD_TUPLE] = { true, INSTR_FMT_IB },\n    [BUILD_LIST] = { true, INSTR_FMT_IB },\n    [LIST_EXTEND] = { true, INSTR_FMT_IB },\n    [SET_UPDATE] = { true, INSTR_FMT_IB },\n    [BUILD_SET] = { true, INSTR_FMT_IB },\n    [BUILD_MAP] = { true, INSTR_FMT_IB },\n    [SETUP_ANNOTATIONS] = { true, INSTR_FMT_IX },\n    [BUILD_CONST_KEY_MAP] = { true, INSTR_FMT_IB },\n    [DICT_UPDATE] = { true, INSTR_FMT_IB },\n    [DICT_MERGE] = { true, INSTR_FMT_IB },\n    [MAP_ADD] = { true, INSTR_FMT_IB },\n    [INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC00000000 },\n    [LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC },\n    [LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC },\n    [LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC },\n    [LOAD_ATTR] = { true, INSTR_FMT_IBC00000000 },\n    [LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC00000000 },\n    [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000 },\n    [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000 },\n    [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000 },\n    [LOAD_ATTR_CLASS] = { true, INSTR_FMT_IBC00000000 },\n    [LOAD_ATTR_PROPERTY] = { true, INSTR_FMT_IBC00000000 },\n    [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000 },\n    [STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000 },\n    [STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000 },\n    [STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000 },\n    [COMPARE_OP] = { true, INSTR_FMT_IBC },\n    [COMPARE_OP_FLOAT] = { true, INSTR_FMT_IBC },\n    [COMPARE_OP_INT] = { true, INSTR_FMT_IBC },\n    [COMPARE_OP_STR] = { true, INSTR_FMT_IBC },\n    [IS_OP] = { true, INSTR_FMT_IB },\n    [CONTAINS_OP] = { true, INSTR_FMT_IB },\n    [CHECK_EG_MATCH] = { true, INSTR_FMT_IX },\n    [CHECK_EXC_MATCH] = { true, INSTR_FMT_IX },\n    [IMPORT_NAME] = { true, INSTR_FMT_IB },\n    [IMPORT_FROM] = { true, INSTR_FMT_IB },\n    [JUMP_FORWARD] = { true, INSTR_FMT_IB },\n    [JUMP_BACKWARD] = { true, INSTR_FMT_IB },\n    [POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB },\n    [POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB },\n    [POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IB },\n    [POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB },\n    [JUMP_BACKWARD_NO_INTERRUPT] = { true, INSTR_FMT_IB },\n    [GET_LEN] = { true, INSTR_FMT_IX },\n    [MATCH_CLASS] = { true, INSTR_FMT_IB },\n    [MATCH_MAPPING] = { true, INSTR_FMT_IX },\n    [MATCH_SEQUENCE] = { true, INSTR_FMT_IX },\n    [MATCH_KEYS] = { true, INSTR_FMT_IX },\n    [GET_ITER] = { true, INSTR_FMT_IX },\n    [GET_YIELD_FROM_ITER] = { true, INSTR_FMT_IX },\n    [FOR_ITER] = { true, INSTR_FMT_IBC },\n    [INSTRUMENTED_FOR_ITER] = { true, INSTR_FMT_IB },\n    [FOR_ITER_LIST] = { true, INSTR_FMT_IBC },\n    [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC },\n    [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC },\n    [FOR_ITER_GEN] = { true, INSTR_FMT_IBC },\n    [BEFORE_ASYNC_WITH] = { true, INSTR_FMT_IX },\n    [BEFORE_WITH] = { true, INSTR_FMT_IX },\n    [WITH_EXCEPT_START] = { true, INSTR_FMT_IX },\n    [PUSH_EXC_INFO] = { true, INSTR_FMT_IX },\n    [LOAD_ATTR_METHOD_WITH_VALUES] = { true, INSTR_FMT_IBC00000000 },\n    [LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000 },\n    [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000 },\n    [KW_NAMES] = { true, INSTR_FMT_IB },\n    [INSTRUMENTED_CALL] = { true, INSTR_FMT_IB },\n    [CALL] = { true, INSTR_FMT_IBC00 },\n    [CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00 },\n    [CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00 },\n    [CALL_PY_WITH_DEFAULTS] = { true, INSTR_FMT_IBC00 },\n    [CALL_NO_KW_TYPE_1] = { true, INSTR_FMT_IBC00 },\n    [CALL_NO_KW_STR_1] = { true, INSTR_FMT_IBC00 },\n    [CALL_NO_KW_TUPLE_1] = { true, INSTR_FMT_IBC00 },\n    [CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00 },\n    [CALL_NO_KW_BUILTIN_O] = { true, INSTR_FMT_IBC00 },\n    [CALL_NO_KW_BUILTIN_FAST] = { true, INSTR_FMT_IBC00 },\n    [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00 },\n    [CALL_NO_KW_LEN] = { true, INSTR_FMT_IBC00 },\n    [CALL_NO_KW_ISINSTANCE] = { true, INSTR_FMT_IBC00 },\n    [CALL_NO_KW_LIST_APPEND] = { true, INSTR_FMT_IBC00 },\n    [CALL_NO_KW_METHOD_DESCRIPTOR_O] = { true, INSTR_FMT_IBC00 },\n    [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00 },\n    [CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00 },\n    [CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00 },\n    [INSTRUMENTED_CALL_FUNCTION_EX] = { true, INSTR_FMT_IX },\n    [CALL_FUNCTION_EX] = { true, INSTR_FMT_IB },\n    [MAKE_FUNCTION] = { true, INSTR_FMT_IB },\n    [RETURN_GENERATOR] = { true, INSTR_FMT_IX },\n    [BUILD_SLICE] = { true, INSTR_FMT_IB },\n    [FORMAT_VALUE] = { true, INSTR_FMT_IB },\n    [COPY] = { true, INSTR_FMT_IB },\n    [BINARY_OP] = { true, INSTR_FMT_IBC },\n    [SWAP] = { true, INSTR_FMT_IB },\n    [INSTRUMENTED_INSTRUCTION] = { true, INSTR_FMT_IX },\n    [INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB },\n    [INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IB },\n    [INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB },\n    [INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB },\n    [INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB },\n    [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IB },\n    [EXTENDED_ARG] = { true, INSTR_FMT_IB },\n    [CACHE] = { true, INSTR_FMT_IX },\n    [RESERVED] = { true, INSTR_FMT_IX },\n};\n#endif\n"
  },
  {
    "path": "OpCode_Targets.h",
    "content": "static void *opcode_targets[256] = {\n    &&TARGET_CACHE,\n    &&TARGET_POP_TOP,\n    &&TARGET_PUSH_NULL,\n    &&TARGET_INTERPRETER_EXIT,\n    &&TARGET_END_FOR,\n    &&TARGET_END_SEND,\n    &&TARGET_BINARY_OP_ADD_FLOAT,\n    &&TARGET_BINARY_OP_ADD_INT,\n    &&TARGET_BINARY_OP_ADD_UNICODE,\n    &&TARGET_NOP,\n    &&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,\n    &&TARGET_UNARY_NEGATIVE,\n    &&TARGET_UNARY_NOT,\n    &&TARGET_BINARY_OP_MULTIPLY_FLOAT,\n    &&TARGET_BINARY_OP_MULTIPLY_INT,\n    &&TARGET_UNARY_INVERT,\n    &&TARGET_BINARY_OP_SUBTRACT_FLOAT,\n    &&TARGET_RESERVED,\n    &&TARGET_BINARY_OP_SUBTRACT_INT,\n    &&TARGET_BINARY_SUBSCR_DICT,\n    &&TARGET_BINARY_SUBSCR_GETITEM,\n    &&TARGET_BINARY_SUBSCR_LIST_INT,\n    &&TARGET_BINARY_SUBSCR_TUPLE_INT,\n    &&TARGET_CALL_PY_EXACT_ARGS,\n    &&TARGET_CALL_PY_WITH_DEFAULTS,\n    &&TARGET_BINARY_SUBSCR,\n    &&TARGET_BINARY_SLICE,\n    &&TARGET_STORE_SLICE,\n    &&TARGET_CALL_BOUND_METHOD_EXACT_ARGS,\n    &&TARGET_CALL_BUILTIN_CLASS,\n    &&TARGET_GET_LEN,\n    &&TARGET_MATCH_MAPPING,\n    &&TARGET_MATCH_SEQUENCE,\n    &&TARGET_MATCH_KEYS,\n    &&TARGET_CALL_BUILTIN_FAST_WITH_KEYWORDS,\n    &&TARGET_PUSH_EXC_INFO,\n    &&TARGET_CHECK_EXC_MATCH,\n    &&TARGET_CHECK_EG_MATCH,\n    &&TARGET_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,\n    &&TARGET_CALL_NO_KW_BUILTIN_FAST,\n    &&TARGET_CALL_NO_KW_BUILTIN_O,\n    &&TARGET_CALL_NO_KW_ISINSTANCE,\n    &&TARGET_CALL_NO_KW_LEN,\n    &&TARGET_CALL_NO_KW_LIST_APPEND,\n    &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST,\n    &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,\n    &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O,\n    &&TARGET_CALL_NO_KW_STR_1,\n    &&TARGET_CALL_NO_KW_TUPLE_1,\n    &&TARGET_WITH_EXCEPT_START,\n    &&TARGET_GET_AITER,\n    &&TARGET_GET_ANEXT,\n    &&TARGET_BEFORE_ASYNC_WITH,\n    &&TARGET_BEFORE_WITH,\n    &&TARGET_END_ASYNC_FOR,\n    &&TARGET_CLEANUP_THROW,\n    &&TARGET_CALL_NO_KW_TYPE_1,\n    &&TARGET_COMPARE_OP_FLOAT,\n    &&TARGET_COMPARE_OP_INT,\n    &&TARGET_COMPARE_OP_STR,\n    &&TARGET_STORE_SUBSCR,\n    &&TARGET_DELETE_SUBSCR,\n    &&TARGET_FOR_ITER_LIST,\n    &&TARGET_FOR_ITER_TUPLE,\n    &&TARGET_FOR_ITER_RANGE,\n    &&TARGET_FOR_ITER_GEN,\n    &&TARGET_LOAD_SUPER_ATTR_ATTR,\n    &&TARGET_LOAD_SUPER_ATTR_METHOD,\n    &&TARGET_GET_ITER,\n    &&TARGET_GET_YIELD_FROM_ITER,\n    &&TARGET_LOAD_ATTR_CLASS,\n    &&TARGET_LOAD_BUILD_CLASS,\n    &&TARGET_LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN,\n    &&TARGET_LOAD_ATTR_INSTANCE_VALUE,\n    &&TARGET_LOAD_ASSERTION_ERROR,\n    &&TARGET_RETURN_GENERATOR,\n    &&TARGET_LOAD_ATTR_MODULE,\n    &&TARGET_LOAD_ATTR_PROPERTY,\n    &&TARGET_LOAD_ATTR_SLOT,\n    &&TARGET_LOAD_ATTR_WITH_HINT,\n    &&TARGET_LOAD_ATTR_METHOD_LAZY_DICT,\n    &&TARGET_LOAD_ATTR_METHOD_NO_DICT,\n    &&TARGET_LOAD_ATTR_METHOD_WITH_VALUES,\n    &&TARGET_RETURN_VALUE,\n    &&TARGET_LOAD_CONST__LOAD_FAST,\n    &&TARGET_SETUP_ANNOTATIONS,\n    &&TARGET_LOAD_FAST__LOAD_CONST,\n    &&TARGET_LOAD_LOCALS,\n    &&TARGET_LOAD_FAST__LOAD_FAST,\n    &&TARGET_POP_EXCEPT,\n    &&TARGET_STORE_NAME,\n    &&TARGET_DELETE_NAME,\n    &&TARGET_UNPACK_SEQUENCE,\n    &&TARGET_FOR_ITER,\n    &&TARGET_UNPACK_EX,\n    &&TARGET_STORE_ATTR,\n    &&TARGET_DELETE_ATTR,\n    &&TARGET_STORE_GLOBAL,\n    &&TARGET_DELETE_GLOBAL,\n    &&TARGET_SWAP,\n    &&TARGET_LOAD_CONST,\n    &&TARGET_LOAD_NAME,\n    &&TARGET_BUILD_TUPLE,\n    &&TARGET_BUILD_LIST,\n    &&TARGET_BUILD_SET,\n    &&TARGET_BUILD_MAP,\n    &&TARGET_LOAD_ATTR,\n    &&TARGET_COMPARE_OP,\n    &&TARGET_IMPORT_NAME,\n    &&TARGET_IMPORT_FROM,\n    &&TARGET_JUMP_FORWARD,\n    &&TARGET_LOAD_GLOBAL_BUILTIN,\n    &&TARGET_LOAD_GLOBAL_MODULE,\n    &&TARGET_STORE_ATTR_INSTANCE_VALUE,\n    &&TARGET_POP_JUMP_IF_FALSE,\n    &&TARGET_POP_JUMP_IF_TRUE,\n    &&TARGET_LOAD_GLOBAL,\n    &&TARGET_IS_OP,\n    &&TARGET_CONTAINS_OP,\n    &&TARGET_RERAISE,\n    &&TARGET_COPY,\n    &&TARGET_RETURN_CONST,\n    &&TARGET_BINARY_OP,\n    &&TARGET_SEND,\n    &&TARGET_LOAD_FAST,\n    &&TARGET_STORE_FAST,\n    &&TARGET_DELETE_FAST,\n    &&TARGET_LOAD_FAST_CHECK,\n    &&TARGET_POP_JUMP_IF_NOT_NONE,\n    &&TARGET_POP_JUMP_IF_NONE,\n    &&TARGET_RAISE_VARARGS,\n    &&TARGET_GET_AWAITABLE,\n    &&TARGET_MAKE_FUNCTION,\n    &&TARGET_BUILD_SLICE,\n    &&TARGET_JUMP_BACKWARD_NO_INTERRUPT,\n    &&TARGET_MAKE_CELL,\n    &&TARGET_LOAD_CLOSURE,\n    &&TARGET_LOAD_DEREF,\n    &&TARGET_STORE_DEREF,\n    &&TARGET_DELETE_DEREF,\n    &&TARGET_JUMP_BACKWARD,\n    &&TARGET_LOAD_SUPER_ATTR,\n    &&TARGET_CALL_FUNCTION_EX,\n    &&TARGET_LOAD_FAST_AND_CLEAR,\n    &&TARGET_EXTENDED_ARG,\n    &&TARGET_LIST_APPEND,\n    &&TARGET_SET_ADD,\n    &&TARGET_MAP_ADD,\n    &&TARGET_STORE_ATTR_SLOT,\n    &&TARGET_COPY_FREE_VARS,\n    &&TARGET_YIELD_VALUE,\n    &&TARGET_RESUME,\n    &&TARGET_MATCH_CLASS,\n    &&TARGET_STORE_ATTR_WITH_HINT,\n    &&TARGET_STORE_FAST__LOAD_FAST,\n    &&TARGET_FORMAT_VALUE,\n    &&TARGET_BUILD_CONST_KEY_MAP,\n    &&TARGET_BUILD_STRING,\n    &&TARGET_STORE_FAST__STORE_FAST,\n    &&TARGET_STORE_SUBSCR_DICT,\n    &&TARGET_STORE_SUBSCR_LIST_INT,\n    &&TARGET_UNPACK_SEQUENCE_LIST,\n    &&TARGET_LIST_EXTEND,\n    &&TARGET_SET_UPDATE,\n    &&TARGET_DICT_MERGE,\n    &&TARGET_DICT_UPDATE,\n    &&TARGET_UNPACK_SEQUENCE_TUPLE,\n    &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE,\n    &&TARGET_SEND_GEN,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&TARGET_CALL,\n    &&TARGET_KW_NAMES,\n    &&TARGET_CALL_INTRINSIC_1,\n    &&TARGET_CALL_INTRINSIC_2,\n    &&TARGET_LOAD_FROM_DICT_OR_GLOBALS,\n    &&TARGET_LOAD_FROM_DICT_OR_DEREF,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&_unknown_opcode,\n    &&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR,\n    &&TARGET_INSTRUMENTED_POP_JUMP_IF_NONE,\n    &&TARGET_INSTRUMENTED_POP_JUMP_IF_NOT_NONE,\n    &&TARGET_INSTRUMENTED_RESUME,\n    &&TARGET_INSTRUMENTED_CALL,\n    &&TARGET_INSTRUMENTED_RETURN_VALUE,\n    &&TARGET_INSTRUMENTED_YIELD_VALUE,\n    &&TARGET_INSTRUMENTED_CALL_FUNCTION_EX,\n    &&TARGET_INSTRUMENTED_JUMP_FORWARD,\n    &&TARGET_INSTRUMENTED_JUMP_BACKWARD,\n    &&TARGET_INSTRUMENTED_RETURN_CONST,\n    &&TARGET_INSTRUMENTED_FOR_ITER,\n    &&TARGET_INSTRUMENTED_POP_JUMP_IF_FALSE,\n    &&TARGET_INSTRUMENTED_POP_JUMP_IF_TRUE,\n    &&TARGET_INSTRUMENTED_END_FOR,\n    &&TARGET_INSTRUMENTED_END_SEND,\n    &&TARGET_INSTRUMENTED_INSTRUCTION,\n    &&TARGET_INSTRUMENTED_LINE,\n    &&_unknown_opcode\n};\n"
  },
  {
    "path": "OptiMizer.c",
    "content": "\n#include \"Python.h\"\n#include \"opcode.h\"\n#include \"pycore_interp.h\"\n#include \"pycore_opcode.h\"\n#include \"pycore_pystate.h\"\n#include \"cpython/optimizer.h\"\n#include <stdbool.h>\n#include <stdint.h>\n#include <stddef.h>\n\n/* Returns the index of the next space, or -1 if there is no\n * more space. Doesn't set an exception. */\nstatic int32_t\nget_next_free_in_executor_array(PyCodeObject *code)\n{\n    _PyExecutorArray *old = code->co_executors;\n    int size = 0;\n    int capacity = 0;\n    if (old != NULL) {\n        size = old->size;\n        capacity = old->capacity;\n        if (capacity >= 256) {\n            return -1;\n        }\n    }\n    assert(size <= capacity);\n    if (size == capacity) {\n        /* Array is full. Grow array */\n        int new_capacity = capacity ? capacity * 2 : 4;\n        _PyExecutorArray *new = PyMem_Realloc(\n            old,\n            offsetof(_PyExecutorArray, executors) +\n            new_capacity * sizeof(_PyExecutorObject *));\n        if (new == NULL) {\n            return -1;\n        }\n        new->capacity = new_capacity;\n        new->size = size;\n        code->co_executors = new;\n    }\n    assert(size < code->co_executors->capacity);\n    code->co_executors->size++;\n    return size;\n}\n\nstatic void\ninsert_executor(PyCodeObject *code, _Py_CODEUNIT *instr, int index, _PyExecutorObject *executor)\n{\n    if (instr->op.code == ENTER_EXECUTOR) {\n        assert(index == instr->op.arg);\n        _PyExecutorObject *old = code->co_executors->executors[index];\n        executor->vm_data.opcode = old->vm_data.opcode;\n        executor->vm_data.oparg = old->vm_data.oparg;\n        old->vm_data.opcode = 0;\n        Py_INCREF(executor);\n        code->co_executors->executors[index] = executor;\n        Py_DECREF(old);\n    }\n    else {\n        Py_INCREF(executor);\n        executor->vm_data.opcode = instr->op.code;\n        executor->vm_data.oparg = instr->op.arg;\n        code->co_executors->executors[index] = executor;\n        assert(index < 256);\n        instr->op.code = ENTER_EXECUTOR;\n        instr->op.arg = index;\n    }\n    return;\n}\n\nstatic int\nget_executor_index(PyCodeObject *code, _Py_CODEUNIT *instr)\n{\n    if (instr->op.code == ENTER_EXECUTOR) {\n        return instr->op.arg;\n    }\n    else {\n        return get_next_free_in_executor_array(code);\n    }\n}\n\nint\nPyUnstable_Replace_Executor(PyCodeObject *code, _Py_CODEUNIT *instr, _PyExecutorObject *new)\n{\n    if (instr->op.code != ENTER_EXECUTOR) {\n        PyErr_Format(PyExc_ValueError, \"No executor to replace\");\n        return -1;\n    }\n    int index = get_executor_index(code, instr);\n    assert(index >= 0);\n    insert_executor(code, instr, index, new);\n    return 0;\n}\n\nstatic int\nerror_optimize(\n    _PyOptimizerObject* self,\n    PyCodeObject *code,\n    _Py_CODEUNIT *instr,\n    _PyExecutorObject **exec)\n{\n    PyErr_Format(PyExc_SystemError, \"Should never call error_optimize\");\n    return -1;\n}\n\nstatic PyTypeObject DefaultOptimizer_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    .tp_name = \"noop_optimizer\",\n    .tp_basicsize = sizeof(_PyOptimizerObject),\n    .tp_itemsize = 0,\n    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,\n};\n\n_PyOptimizerObject _PyOptimizer_Default = {\n    PyObject_HEAD_INIT(&DefaultOptimizer_Type)\n    .optimize = error_optimize,\n    .resume_threshold = UINT16_MAX,\n    .backedge_threshold = UINT16_MAX,\n};\n\n_PyOptimizerObject *\nPyUnstable_GetOptimizer(void)\n{\n    PyInterpreterState *interp = PyInterpreterState_Get();\n    if (interp->optimizer == &_PyOptimizer_Default) {\n        return NULL;\n    }\n    Py_INCREF(interp->optimizer);\n    return interp->optimizer;\n}\n\nvoid\nPyUnstable_SetOptimizer(_PyOptimizerObject *optimizer)\n{\n    PyInterpreterState *interp = PyInterpreterState_Get();\n    if (optimizer == NULL) {\n        optimizer = &_PyOptimizer_Default;\n    }\n    _PyOptimizerObject *old = interp->optimizer;\n    Py_INCREF(optimizer);\n    interp->optimizer = optimizer;\n    interp->optimizer_backedge_threshold = optimizer->backedge_threshold;\n    interp->optimizer_resume_threshold = optimizer->resume_threshold;\n    Py_DECREF(old);\n}\n\n_PyInterpreterFrame *\n_PyOptimizer_BackEdge(_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest, PyObject **stack_pointer)\n{\n    PyInterpreterState *interp = PyInterpreterState_Get();\n    int index = get_executor_index(frame->f_code, src);\n    if (index < 0) {\n        _PyFrame_SetStackPointer(frame, stack_pointer);\n        return frame;\n    }\n    _PyOptimizerObject *opt = interp->optimizer;\n    _PyExecutorObject *executor;\n    int err = opt->optimize(opt, frame->f_code, dest, &executor);\n    if (err <= 0) {\n        if (err < 0) {\n            return NULL;\n        }\n        _PyFrame_SetStackPointer(frame, stack_pointer);\n        return frame;\n    }\n    insert_executor(frame->f_code, src, index, executor);\n    return executor->execute(executor, frame, stack_pointer);\n}\n\n/** Test support **/\n\n\ntypedef struct {\n    _PyOptimizerObject base;\n    int64_t count;\n} _PyCounterOptimizerObject;\n\ntypedef struct {\n    _PyExecutorObject executor;\n    _PyCounterOptimizerObject *optimizer;\n    _Py_CODEUNIT *next_instr;\n} _PyCounterExecutorObject;\n\nstatic void\ncounter_dealloc(_PyCounterExecutorObject *self) {\n    Py_DECREF(self->optimizer);\n    PyObject_Free(self);\n}\n\nstatic PyTypeObject CounterExecutor_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    .tp_name = \"counting_executor\",\n    .tp_basicsize = sizeof(_PyCounterExecutorObject),\n    .tp_itemsize = 0,\n    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,\n    .tp_dealloc = (destructor)counter_dealloc,\n};\n\nstatic _PyInterpreterFrame *\ncounter_execute(_PyExecutorObject *self, _PyInterpreterFrame *frame, PyObject **stack_pointer)\n{\n    ((_PyCounterExecutorObject *)self)->optimizer->count++;\n    _PyFrame_SetStackPointer(frame, stack_pointer);\n    frame->prev_instr = ((_PyCounterExecutorObject *)self)->next_instr - 1;\n    Py_DECREF(self);\n    return frame;\n}\n\nstatic int\ncounter_optimize(\n    _PyOptimizerObject* self,\n    PyCodeObject *code,\n    _Py_CODEUNIT *instr,\n    _PyExecutorObject **exec_ptr)\n{\n    _PyCounterExecutorObject *executor = (_PyCounterExecutorObject *)_PyObject_New(&CounterExecutor_Type);\n    if (executor == NULL) {\n        return -1;\n    }\n    executor->executor.execute = counter_execute;\n    Py_INCREF(self);\n    executor->optimizer = (_PyCounterOptimizerObject *)self;\n    executor->next_instr = instr;\n    *exec_ptr = (_PyExecutorObject *)executor;\n    return 1;\n}\n\nstatic PyObject *\ncounter_get_counter(PyObject *self, PyObject *args)\n{\n    return PyLong_FromLongLong(((_PyCounterOptimizerObject *)self)->count);\n}\n\nstatic PyMethodDef counter_methods[] = {\n    { \"get_count\", counter_get_counter, METH_NOARGS, NULL },\n    { NULL, NULL },\n};\n\nstatic PyTypeObject CounterOptimizer_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    .tp_name = \"Counter optimizer\",\n    .tp_basicsize = sizeof(_PyCounterOptimizerObject),\n    .tp_itemsize = 0,\n    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,\n    .tp_methods = counter_methods,\n};\n\nPyObject *\nPyUnstable_Optimizer_NewCounter(void)\n{\n    _PyCounterOptimizerObject *opt = (_PyCounterOptimizerObject *)_PyObject_New(&CounterOptimizer_Type);\n    if (opt == NULL) {\n        return NULL;\n    }\n    opt->base.optimize = counter_optimize;\n    opt->base.resume_threshold = UINT16_MAX;\n    opt->base.backedge_threshold = 0;\n    opt->count = 0;\n    return (PyObject *)opt;\n}\n"
  },
  {
    "path": "PathConfig.c",
    "content": "/* Path configuration like module_search_path (sys.path) */\n\n#include \"Python.h\"\n#include \"marshal.h\"              // PyMarshal_ReadObjectFromString\n#include \"osdefs.h\"               // DELIM\n#include \"pycore_initconfig.h\"\n#include \"pycore_fileutils.h\"\n#include \"pycore_pathconfig.h\"\n#include \"pycore_pymem.h\"         // _PyMem_SetDefaultAllocator()\n#include <wchar.h>\n#ifdef MS_WINDOWS\n#  include <windows.h>            // GetFullPathNameW(), MAX_PATH\n#  include <pathcch.h>\n#  include <shlwapi.h>\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n/* External interface */\n\n/* Stored values set by C API functions */\ntypedef struct _PyPathConfig {\n    /* Full path to the Python program */\n    wchar_t *program_full_path;\n    wchar_t *prefix;\n    wchar_t *exec_prefix;\n    wchar_t *stdlib_dir;\n    /* Set by Py_SetPath */\n    wchar_t *module_search_path;\n    /* Set by _PyPathConfig_UpdateGlobal */\n    wchar_t *calculated_module_search_path;\n    /* Python program name */\n    wchar_t *program_name;\n    /* Set by Py_SetPythonHome() or PYTHONHOME environment variable */\n    wchar_t *home;\n    int _is_python_build;\n} _PyPathConfig;\n\n#  define _PyPathConfig_INIT \\\n      {.module_search_path = NULL, ._is_python_build = 0}\n\n\n_PyPathConfig _Py_path_config = _PyPathConfig_INIT;\n\n\nconst wchar_t *\n_PyPathConfig_GetGlobalModuleSearchPath(void)\n{\n    return _Py_path_config.module_search_path;\n}\n\n\nvoid\n_PyPathConfig_ClearGlobal(void)\n{\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n#define CLEAR(ATTR) \\\n    do { \\\n        PyMem_RawFree(_Py_path_config.ATTR); \\\n        _Py_path_config.ATTR = NULL; \\\n    } while (0)\n\n    CLEAR(program_full_path);\n    CLEAR(prefix);\n    CLEAR(exec_prefix);\n    CLEAR(stdlib_dir);\n    CLEAR(module_search_path);\n    CLEAR(calculated_module_search_path);\n    CLEAR(program_name);\n    CLEAR(home);\n    _Py_path_config._is_python_build = 0;\n\n#undef CLEAR\n\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n}\n\nPyStatus\n_PyPathConfig_ReadGlobal(PyConfig *config)\n{\n    PyStatus status = _PyStatus_OK();\n\n#define COPY(ATTR) \\\n    do { \\\n        if (_Py_path_config.ATTR && !config->ATTR) { \\\n            status = PyConfig_SetString(config, &config->ATTR, _Py_path_config.ATTR); \\\n            if (_PyStatus_EXCEPTION(status)) goto done; \\\n        } \\\n    } while (0)\n\n#define COPY2(ATTR, SRCATTR) \\\n    do { \\\n        if (_Py_path_config.SRCATTR && !config->ATTR) { \\\n            status = PyConfig_SetString(config, &config->ATTR, _Py_path_config.SRCATTR); \\\n            if (_PyStatus_EXCEPTION(status)) goto done; \\\n        } \\\n    } while (0)\n\n#define COPY_INT(ATTR) \\\n    do { \\\n        assert(_Py_path_config.ATTR >= 0); \\\n        if ((_Py_path_config.ATTR >= 0) && (config->ATTR <= 0)) { \\\n            config->ATTR = _Py_path_config.ATTR; \\\n        } \\\n    } while (0)\n\n    COPY(prefix);\n    COPY(exec_prefix);\n    COPY(stdlib_dir);\n    COPY(program_name);\n    COPY(home);\n    COPY2(executable, program_full_path);\n    COPY_INT(_is_python_build);\n    // module_search_path must be initialised - not read\n#undef COPY\n#undef COPY2\n#undef COPY_INT\n\ndone:\n    return status;\n}\n\nPyStatus\n_PyPathConfig_UpdateGlobal(const PyConfig *config)\n{\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n#define COPY(ATTR) \\\n    do { \\\n        if (config->ATTR) { \\\n            PyMem_RawFree(_Py_path_config.ATTR); \\\n            _Py_path_config.ATTR = _PyMem_RawWcsdup(config->ATTR); \\\n            if (!_Py_path_config.ATTR) goto error; \\\n        } \\\n    } while (0)\n\n#define COPY2(ATTR, SRCATTR) \\\n    do { \\\n        if (config->SRCATTR) { \\\n            PyMem_RawFree(_Py_path_config.ATTR); \\\n            _Py_path_config.ATTR = _PyMem_RawWcsdup(config->SRCATTR); \\\n            if (!_Py_path_config.ATTR) goto error; \\\n        } \\\n    } while (0)\n\n#define COPY_INT(ATTR) \\\n    do { \\\n        if (config->ATTR > 0) { \\\n            _Py_path_config.ATTR = config->ATTR; \\\n        } \\\n    } while (0)\n\n    COPY(prefix);\n    COPY(exec_prefix);\n    COPY(stdlib_dir);\n    COPY(program_name);\n    COPY(home);\n    COPY2(program_full_path, executable);\n    COPY_INT(_is_python_build);\n#undef COPY\n#undef COPY2\n#undef COPY_INT\n\n    PyMem_RawFree(_Py_path_config.module_search_path);\n    _Py_path_config.module_search_path = NULL;\n    PyMem_RawFree(_Py_path_config.calculated_module_search_path);\n    _Py_path_config.calculated_module_search_path = NULL;\n\n    do {\n        size_t cch = 1;\n        for (Py_ssize_t i = 0; i < config->module_search_paths.length; ++i) {\n            cch += 1 + wcslen(config->module_search_paths.items[i]);\n        }\n\n        wchar_t *path = (wchar_t*)PyMem_RawMalloc(sizeof(wchar_t) * cch);\n        if (!path) {\n            goto error;\n        }\n        wchar_t *p = path;\n        for (Py_ssize_t i = 0; i < config->module_search_paths.length; ++i) {\n            wcscpy(p, config->module_search_paths.items[i]);\n            p = wcschr(p, L'\\0');\n            *p++ = DELIM;\n            *p = L'\\0';\n        }\n\n        do {\n            *p = L'\\0';\n        } while (p != path && *--p == DELIM);\n        _Py_path_config.calculated_module_search_path = path;\n    } while (0);\n\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n    return _PyStatus_OK();\n\nerror:\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n    return _PyStatus_NO_MEMORY();\n}\n\n\nstatic void _Py_NO_RETURN\npath_out_of_memory(const char *func)\n{\n    _Py_FatalErrorFunc(func, \"out of memory\");\n}\n\n// Removed in Python 3.13 API, but kept for the stable ABI\nPyAPI_FUNC(void)\nPy_SetPath(const wchar_t *path)\n{\n    if (path == NULL) {\n        _PyPathConfig_ClearGlobal();\n        return;\n    }\n\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    PyMem_RawFree(_Py_path_config.prefix);\n    PyMem_RawFree(_Py_path_config.exec_prefix);\n    PyMem_RawFree(_Py_path_config.stdlib_dir);\n    PyMem_RawFree(_Py_path_config.module_search_path);\n    PyMem_RawFree(_Py_path_config.calculated_module_search_path);\n\n    _Py_path_config.prefix = _PyMem_RawWcsdup(L\"\");\n    _Py_path_config.exec_prefix = _PyMem_RawWcsdup(L\"\");\n    // XXX Copy this from the new module_search_path?\n    if (_Py_path_config.home != NULL) {\n        _Py_path_config.stdlib_dir = _PyMem_RawWcsdup(_Py_path_config.home);\n    }\n    else {\n        _Py_path_config.stdlib_dir = _PyMem_RawWcsdup(L\"\");\n    }\n    _Py_path_config.module_search_path = _PyMem_RawWcsdup(path);\n    _Py_path_config.calculated_module_search_path = NULL;\n\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    if (_Py_path_config.prefix == NULL\n        || _Py_path_config.exec_prefix == NULL\n        || _Py_path_config.stdlib_dir == NULL\n        || _Py_path_config.module_search_path == NULL)\n    {\n        path_out_of_memory(__func__);\n    }\n}\n\n\n// Removed in Python 3.13 API, but kept for the stable ABI\nPyAPI_FUNC(void)\nPy_SetPythonHome(const wchar_t *home)\n{\n    int has_value = home && home[0];\n\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    PyMem_RawFree(_Py_path_config.home);\n    _Py_path_config.home = NULL;\n\n    if (has_value) {\n        _Py_path_config.home = _PyMem_RawWcsdup(home);\n    }\n\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    if (has_value && _Py_path_config.home == NULL) {\n        path_out_of_memory(__func__);\n    }\n}\n\n\n// Removed in Python 3.13 API, but kept for the stable ABI\nPyAPI_FUNC(void)\nPy_SetProgramName(const wchar_t *program_name)\n{\n    int has_value = program_name && program_name[0];\n\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    PyMem_RawFree(_Py_path_config.program_name);\n    _Py_path_config.program_name = NULL;\n\n    if (has_value) {\n        _Py_path_config.program_name = _PyMem_RawWcsdup(program_name);\n    }\n\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    if (has_value && _Py_path_config.program_name == NULL) {\n        path_out_of_memory(__func__);\n    }\n}\n\n\nwchar_t *\nPy_GetPath(void)\n{\n    /* If the user has provided a path, return that */\n    if (_Py_path_config.module_search_path) {\n        return _Py_path_config.module_search_path;\n    }\n    /* If we have already done calculations, return the calculated path */\n    return _Py_path_config.calculated_module_search_path;\n}\n\n\nwchar_t *\n_Py_GetStdlibDir(void)\n{\n    wchar_t *stdlib_dir = _Py_path_config.stdlib_dir;\n    if (stdlib_dir != NULL && stdlib_dir[0] != L'\\0') {\n        return stdlib_dir;\n    }\n    return NULL;\n}\n\n\nwchar_t *\nPy_GetPrefix(void)\n{\n    return _Py_path_config.prefix;\n}\n\n\nwchar_t *\nPy_GetExecPrefix(void)\n{\n    return _Py_path_config.exec_prefix;\n}\n\n\nwchar_t *\nPy_GetProgramFullPath(void)\n{\n    return _Py_path_config.program_full_path;\n}\n\n\nwchar_t*\nPy_GetPythonHome(void)\n{\n    return _Py_path_config.home;\n}\n\n\nwchar_t *\nPy_GetProgramName(void)\n{\n    return _Py_path_config.program_name;\n}\n\n\n\n/* Compute module search path from argv[0] or the current working\n   directory (\"-m module\" case) which will be prepended to sys.argv:\n   sys.path[0].\n\n   Return 1 if the path is correctly resolved and written into *path0_p.\n\n   Return 0 if it fails to resolve the full path. For example, return 0 if the\n   current working directory has been removed (bpo-36236) or if argv is empty.\n\n   Raise an exception and return -1 on error.\n   */\nint\n_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)\n{\n    assert(_PyWideStringList_CheckConsistency(argv));\n\n    if (argv->length == 0) {\n        /* Leave sys.path unchanged if sys.argv is empty */\n        return 0;\n    }\n\n    wchar_t *argv0 = argv->items[0];\n    int have_module_arg = (wcscmp(argv0, L\"-m\") == 0);\n    int have_script_arg = (!have_module_arg && (wcscmp(argv0, L\"-c\") != 0));\n\n    wchar_t *path0 = argv0;\n    Py_ssize_t n = 0;\n\n#ifdef HAVE_REALPATH\n    wchar_t fullpath[MAXPATHLEN];\n#elif defined(MS_WINDOWS)\n    wchar_t fullpath[MAX_PATH];\n#endif\n\n    if (have_module_arg) {\n#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)\n        if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {\n            return 0;\n        }\n        path0 = fullpath;\n#else\n        path0 = L\".\";\n#endif\n        n = wcslen(path0);\n    }\n\n#ifdef HAVE_READLINK\n    wchar_t link[MAXPATHLEN + 1];\n    int nr = 0;\n    wchar_t path0copy[2 * MAXPATHLEN + 1];\n\n    if (have_script_arg) {\n        nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));\n    }\n    if (nr > 0) {\n        /* It's a symlink */\n        link[nr] = '\\0';\n        if (link[0] == SEP) {\n            path0 = link; /* Link to absolute path */\n        }\n        else if (wcschr(link, SEP) == NULL) {\n            /* Link without path */\n        }\n        else {\n            /* Must join(dirname(path0), link) */\n            wchar_t *q = wcsrchr(path0, SEP);\n            if (q == NULL) {\n                /* path0 without path */\n                path0 = link;\n            }\n            else {\n                /* Must make a copy, path0copy has room for 2 * MAXPATHLEN */\n                wcsncpy(path0copy, path0, MAXPATHLEN);\n                q = wcsrchr(path0copy, SEP);\n                wcsncpy(q+1, link, MAXPATHLEN);\n                q[MAXPATHLEN + 1] = L'\\0';\n                path0 = path0copy;\n            }\n        }\n    }\n#endif /* HAVE_READLINK */\n\n    wchar_t *p = NULL;\n\n#if SEP == '\\\\'\n    /* Special case for Microsoft filename syntax */\n    if (have_script_arg) {\n        wchar_t *q;\n#if defined(MS_WINDOWS)\n        /* Replace the first element in argv with the full path. */\n        wchar_t *ptemp;\n        if (GetFullPathNameW(path0,\n                           Py_ARRAY_LENGTH(fullpath),\n                           fullpath,\n                           &ptemp)) {\n            path0 = fullpath;\n        }\n#endif\n        p = wcsrchr(path0, SEP);\n        /* Test for alternate separator */\n        q = wcsrchr(p ? p : path0, '/');\n        if (q != NULL)\n            p = q;\n        if (p != NULL) {\n            n = p + 1 - path0;\n            if (n > 1 && p[-1] != ':')\n                n--; /* Drop trailing separator */\n        }\n    }\n#else\n    /* All other filename syntaxes */\n    if (have_script_arg) {\n#if defined(HAVE_REALPATH)\n        if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {\n            path0 = fullpath;\n        }\n#endif\n        p = wcsrchr(path0, SEP);\n    }\n    if (p != NULL) {\n        n = p + 1 - path0;\n#if SEP == '/' /* Special case for Unix filename syntax */\n        if (n > 1) {\n            /* Drop trailing separator */\n            n--;\n        }\n#endif /* Unix */\n    }\n#endif /* All others */\n\n    PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);\n    if (path0_obj == NULL) {\n        return -1;\n    }\n\n    *path0_p = path0_obj;\n    return 1;\n}\n\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "Perf_Trampoline.c",
    "content": "/*\n\nPerf trampoline instrumentation\n===============================\n\nThis file contains instrumentation to allow to associate\ncalls to the CPython eval loop back to the names of the Python\nfunctions and filename being executed.\n\nMany native performance profilers like the Linux perf tools are\nonly available to 'see' the C stack when sampling from the profiled\nprocess. This means that if we have the following python code:\n\n    import time\n    def foo(n):\n        # Some CPU intensive code\n\n    def bar(n):\n        foo(n)\n\n    def baz(n):\n        bar(n)\n\n    baz(10000000)\n\nA performance profiler that is only able to see native frames will\nproduce the following backtrace when sampling from foo():\n\n    _PyEval_EvalFrameDefault -----> Evaluation frame of foo()\n    _PyEval_Vector\n    _PyFunction_Vectorcall\n    PyObject_Vectorcall\n    call_function\n\n    _PyEval_EvalFrameDefault ------> Evaluation frame of bar()\n    _PyEval_EvalFrame\n    _PyEval_Vector\n    _PyFunction_Vectorcall\n    PyObject_Vectorcall\n    call_function\n\n    _PyEval_EvalFrameDefault -------> Evaluation frame of baz()\n    _PyEval_EvalFrame\n    _PyEval_Vector\n    _PyFunction_Vectorcall\n    PyObject_Vectorcall\n    call_function\n\n    ...\n\n    Py_RunMain\n\nBecause the profiler is only able to see the native frames and the native\nfunction that runs the evaluation loop is the same (_PyEval_EvalFrameDefault)\nthen the profiler and any reporter generated by it will not be able to\nassociate the names of the Python functions and the filenames associated with\nthose calls, rendering the results useless in the Python world.\n\nTo fix this problem, we introduce the concept of a trampoline frame. A\ntrampoline frame is a piece of code that is unique per Python code object that\nis executed before entering the CPython eval loop. This piece of code just\ncalls the original Python evaluation function (_PyEval_EvalFrameDefault) and\nforwards all the arguments received. In this way, when a profiler samples\nframes from the previous example it will see;\n\n    _PyEval_EvalFrameDefault -----> Evaluation frame of foo()\n    [Jit compiled code 3]\n    _PyEval_Vector\n    _PyFunction_Vectorcall\n    PyObject_Vectorcall\n    call_function\n\n    _PyEval_EvalFrameDefault ------> Evaluation frame of bar()\n    [Jit compiled code 2]\n    _PyEval_EvalFrame\n    _PyEval_Vector\n    _PyFunction_Vectorcall\n    PyObject_Vectorcall\n    call_function\n\n    _PyEval_EvalFrameDefault -------> Evaluation frame of baz()\n    [Jit compiled code 1]\n    _PyEval_EvalFrame\n    _PyEval_Vector\n    _PyFunction_Vectorcall\n    PyObject_Vectorcall\n    call_function\n\n    ...\n\n    Py_RunMain\n\nWhen we generate every unique copy of the trampoline (what here we called \"[Jit\ncompiled code N]\") we write the relationship between the compiled code and the\nPython function that is associated with it. Every profiler requires this\ninformation in a different format. For example, the Linux \"perf\" profiler\nrequires a file in \"/tmp/perf-PID.map\" (name and location not configurable)\nwith the following format:\n\n    <compiled code address> <compiled code size> <name of the compiled code>\n\nIf this file is available when \"perf\" generates reports, it will automatically\nassociate every trampoline with the Python function that it is associated with\nallowing it to generate reports that include Python information. These reports\nthen can also be filtered in a way that *only* Python information appears.\n\nNotice that for this to work, there must be a unique copied of the trampoline\nper Python code object even if the code in the trampoline is the same. To\nachieve this we have a assembly template in Objects/asm_trampiline.S that is\ncompiled into the Python executable/shared library. This template generates a\nsymbol that maps the start of the assembly code and another that marks the end\nof the assembly code for the trampoline.  Then, every time we need a unique\ntrampoline for a Python code object, we copy the assembly code into a mmaped\narea that has executable permissions and we return the start of that area as\nour trampoline function.\n\nAsking for a mmap-ed memory area for trampoline is very wasteful so we\nallocate big arenas of memory in a single mmap call, we populate the entire\narena with copies of the trampoline (this allows us to now have to invalidate\nthe icache for the instructions in the page) and then we return the next\navailable chunk every time someone asks for a new trampoline. We keep a linked\nlist of arenas in case the current memory arena is exhausted and another one is\nneeded.\n\nFor the best results, Python should be compiled with\nCFLAGS=\"-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer\" as this allows\nprofilers to unwind using only the frame pointer and not on DWARF debug\ninformation (note that as trampilines are dynamically generated there won't be\nany DWARF information available for them).\n*/\n\n#include \"Python.h\"\n#include \"pycore_ceval.h\"\n#include \"pycore_frame.h\"\n#include \"pycore_interp.h\"\n\n\n#ifdef PY_HAVE_PERF_TRAMPOLINE\n\n#include <fcntl.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)\n#define PY_HAVE_INVALIDATE_ICACHE\n\n#if defined(__clang__) || defined(__GNUC__)\nextern void __clear_cache(void *, void*);\n#endif\n\nstatic void invalidate_icache(char* begin, char*end) {\n#if defined(__clang__) || defined(__GNUC__)\n    return __clear_cache(begin, end);\n#else\n    return;\n#endif\n}\n#endif\n\n/* The function pointer is passed as last argument. The other three arguments\n * are passed in the same order as the function requires. This results in\n * shorter, more efficient ASM code for trampoline.\n */\ntypedef PyObject *(*py_evaluator)(PyThreadState *, _PyInterpreterFrame *,\n                                  int throwflag);\ntypedef PyObject *(*py_trampoline)(PyThreadState *, _PyInterpreterFrame *, int,\n                                   py_evaluator);\n\nextern void *_Py_trampoline_func_start;  // Start of the template of the\n                                         // assembly trampoline\nextern void *\n    _Py_trampoline_func_end;  // End of the template of the assembly trampoline\n\nstruct code_arena_st {\n    char *start_addr;    // Start of the memory arena\n    char *current_addr;  // Address of the current trampoline within the arena\n    size_t size;         // Size of the memory arena\n    size_t size_left;    // Remaining size of the memory arena\n    size_t code_size;    // Size of the code of every trampoline in the arena\n    struct code_arena_st\n        *prev;  // Pointer to the arena  or NULL if this is the first arena.\n};\n\ntypedef struct code_arena_st code_arena_t;\ntypedef struct trampoline_api_st trampoline_api_t;\n\n#define perf_status _PyRuntime.ceval.perf.status\n#define extra_code_index _PyRuntime.ceval.perf.extra_code_index\n#define perf_code_arena _PyRuntime.ceval.perf.code_arena\n#define trampoline_api _PyRuntime.ceval.perf.trampoline_api\n#define perf_map_file _PyRuntime.ceval.perf.map_file\n\n\nstatic void\nperf_map_write_entry(void *state, const void *code_addr,\n                         unsigned int code_size, PyCodeObject *co)\n{\n    const char *entry = \"\";\n    if (co->co_qualname != NULL) {\n        entry = PyUnicode_AsUTF8(co->co_qualname);\n    }\n    const char *filename = \"\";\n    if (co->co_filename != NULL) {\n        filename = PyUnicode_AsUTF8(co->co_filename);\n    }\n    size_t perf_map_entry_size = snprintf(NULL, 0, \"py::%s:%s\", entry, filename) + 1;\n    char* perf_map_entry = (char*) PyMem_RawMalloc(perf_map_entry_size);\n    if (perf_map_entry == NULL) {\n        return;\n    }\n    snprintf(perf_map_entry, perf_map_entry_size, \"py::%s:%s\", entry, filename);\n    PyUnstable_WritePerfMapEntry(code_addr, code_size, perf_map_entry);\n    PyMem_RawFree(perf_map_entry);\n}\n\n_PyPerf_Callbacks _Py_perfmap_callbacks = {\n    NULL,\n    &perf_map_write_entry,\n    NULL,\n};\n\nstatic int\nnew_code_arena(void)\n{\n    // non-trivial programs typically need 64 to 256 kiB.\n    size_t mem_size = 4096 * 16;\n    assert(mem_size % sysconf(_SC_PAGESIZE) == 0);\n    char *memory =\n        mmap(NULL,  // address\n             mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,\n             -1,  // fd (not used here)\n             0);  // offset (not used here)\n    if (!memory) {\n        PyErr_SetFromErrno(PyExc_OSError);\n        _PyErr_WriteUnraisableMsg(\n            \"Failed to create new mmap for perf trampoline\", NULL);\n        perf_status = PERF_STATUS_FAILED;\n        return -1;\n    }\n    void *start = &_Py_trampoline_func_start;\n    void *end = &_Py_trampoline_func_end;\n    size_t code_size = end - start;\n    // TODO: Check the effect of alignment of the code chunks. Initial investigation\n    // showed that this has no effect on performance in x86-64 or aarch64 and the current\n    // version has the advantage that the unwinder in GDB can unwind across JIT-ed code.\n    //\n    // We should check the values in the future and see if there is a\n    // measurable performance improvement by rounding trampolines up to 32-bit\n    // or 64-bit alignment.\n\n    size_t n_copies = mem_size / code_size;\n    for (size_t i = 0; i < n_copies; i++) {\n        memcpy(memory + i * code_size, start, code_size * sizeof(char));\n    }\n    // Some systems may prevent us from creating executable code on the fly.\n    int res = mprotect(memory, mem_size, PROT_READ | PROT_EXEC);\n    if (res == -1) {\n        PyErr_SetFromErrno(PyExc_OSError);\n        munmap(memory, mem_size);\n        _PyErr_WriteUnraisableMsg(\n            \"Failed to set mmap for perf trampoline to PROT_READ | PROT_EXEC\",\n            NULL);\n        return -1;\n    }\n\n#ifdef PY_HAVE_INVALIDATE_ICACHE\n    // Before the JIT can run a block of code that has been emitted it must invalidate\n    // the instruction cache on some platforms like arm and aarch64.\n    invalidate_icache(memory, memory + mem_size);\n#endif\n\n    code_arena_t *new_arena = PyMem_RawCalloc(1, sizeof(code_arena_t));\n    if (new_arena == NULL) {\n        PyErr_NoMemory();\n        munmap(memory, mem_size);\n        _PyErr_WriteUnraisableMsg(\"Failed to allocate new code arena struct\",\n                                  NULL);\n        return -1;\n    }\n\n    new_arena->start_addr = memory;\n    new_arena->current_addr = memory;\n    new_arena->size = mem_size;\n    new_arena->size_left = mem_size;\n    new_arena->code_size = code_size;\n    new_arena->prev = perf_code_arena;\n    perf_code_arena = new_arena;\n    return 0;\n}\n\nstatic void\nfree_code_arenas(void)\n{\n    code_arena_t *cur = perf_code_arena;\n    code_arena_t *prev;\n    perf_code_arena = NULL;  // invalid static pointer\n    while (cur) {\n        munmap(cur->start_addr, cur->size);\n        prev = cur->prev;\n        PyMem_RawFree(cur);\n        cur = prev;\n    }\n}\n\nstatic inline py_trampoline\ncode_arena_new_code(code_arena_t *code_arena)\n{\n    py_trampoline trampoline = (py_trampoline)code_arena->current_addr;\n    code_arena->size_left -= code_arena->code_size;\n    code_arena->current_addr += code_arena->code_size;\n    return trampoline;\n}\n\nstatic inline py_trampoline\ncompile_trampoline(void)\n{\n    if ((perf_code_arena == NULL) ||\n        (perf_code_arena->size_left <= perf_code_arena->code_size)) {\n        if (new_code_arena() < 0) {\n            return NULL;\n        }\n    }\n    assert(perf_code_arena->size_left <= perf_code_arena->size);\n    return code_arena_new_code(perf_code_arena);\n}\n\nstatic PyObject *\npy_trampoline_evaluator(PyThreadState *ts, _PyInterpreterFrame *frame,\n                        int throw)\n{\n    if (perf_status == PERF_STATUS_FAILED ||\n        perf_status == PERF_STATUS_NO_INIT) {\n        goto default_eval;\n    }\n    PyCodeObject *co = frame->f_code;\n    py_trampoline f = NULL;\n    assert(extra_code_index != -1);\n    int ret = _PyCode_GetExtra((PyObject *)co, extra_code_index, (void **)&f);\n    if (ret != 0 || f == NULL) {\n        // This is the first time we see this code object so we need\n        // to compile a trampoline for it.\n        py_trampoline new_trampoline = compile_trampoline();\n        if (new_trampoline == NULL) {\n            goto default_eval;\n        }\n        trampoline_api.write_state(trampoline_api.state, new_trampoline,\n                                   perf_code_arena->code_size, co);\n        _PyCode_SetExtra((PyObject *)co, extra_code_index,\n                         (void *)new_trampoline);\n        f = new_trampoline;\n    }\n    assert(f != NULL);\n    return f(ts, frame, throw, _PyEval_EvalFrameDefault);\ndefault_eval:\n    // Something failed, fall back to the default evaluator.\n    return _PyEval_EvalFrameDefault(ts, frame, throw);\n}\n#endif  // PY_HAVE_PERF_TRAMPOLINE\n\nint\n_PyIsPerfTrampolineActive(void)\n{\n#ifdef PY_HAVE_PERF_TRAMPOLINE\n    PyThreadState *tstate = _PyThreadState_GET();\n    return tstate->interp->eval_frame == py_trampoline_evaluator;\n#endif\n    return 0;\n}\n\nvoid\n_PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *callbacks)\n{\n    if (callbacks == NULL) {\n        return;\n    }\n#ifdef PY_HAVE_PERF_TRAMPOLINE\n    callbacks->init_state = trampoline_api.init_state;\n    callbacks->write_state = trampoline_api.write_state;\n    callbacks->free_state = trampoline_api.free_state;\n#endif\n    return;\n}\n\nint\n_PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *callbacks)\n{\n    if (callbacks == NULL) {\n        return -1;\n    }\n#ifdef PY_HAVE_PERF_TRAMPOLINE\n    if (trampoline_api.state) {\n        _PyPerfTrampoline_Fini();\n    }\n    trampoline_api.init_state = callbacks->init_state;\n    trampoline_api.write_state = callbacks->write_state;\n    trampoline_api.free_state = callbacks->free_state;\n    trampoline_api.state = NULL;\n    perf_status = PERF_STATUS_OK;\n#endif\n    return 0;\n}\n\nint\n_PyPerfTrampoline_Init(int activate)\n{\n#ifdef PY_HAVE_PERF_TRAMPOLINE\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (tstate->interp->eval_frame &&\n        tstate->interp->eval_frame != py_trampoline_evaluator) {\n        PyErr_SetString(PyExc_RuntimeError,\n                        \"Trampoline cannot be initialized as a custom eval \"\n                        \"frame is already present\");\n        return -1;\n    }\n    if (!activate) {\n        tstate->interp->eval_frame = NULL;\n    }\n    else {\n        tstate->interp->eval_frame = py_trampoline_evaluator;\n        if (new_code_arena() < 0) {\n            return -1;\n        }\n        extra_code_index = _PyEval_RequestCodeExtraIndex(NULL);\n        if (extra_code_index == -1) {\n            return -1;\n        }\n        perf_status = PERF_STATUS_OK;\n    }\n#endif\n    return 0;\n}\n\nint\n_PyPerfTrampoline_Fini(void)\n{\n#ifdef PY_HAVE_PERF_TRAMPOLINE\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (tstate->interp->eval_frame == py_trampoline_evaluator) {\n        tstate->interp->eval_frame = NULL;\n    }\n    free_code_arenas();\n    extra_code_index = -1;\n#endif\n    return 0;\n}\n\nPyStatus\n_PyPerfTrampoline_AfterFork_Child(void)\n{\n#ifdef PY_HAVE_PERF_TRAMPOLINE\n    // Restart trampoline in file in child.\n    int was_active = _PyIsPerfTrampolineActive();\n    _PyPerfTrampoline_Fini();\n    PyUnstable_PerfMapState_Fini();\n    if (was_active) {\n        _PyPerfTrampoline_Init(1);\n    }\n#endif\n    return PyStatus_Ok();\n}\n"
  },
  {
    "path": "PreConfig.c",
    "content": "#include \"Python.h\"\n#include \"pycore_fileutils.h\"     // DECODE_LOCALE_ERR\n#include \"pycore_getopt.h\"        // _PyOS_GetOpt()\n#include \"pycore_initconfig.h\"    // _PyArgv\n#include \"pycore_pymem.h\"         // _PyMem_GetAllocatorName()\n#include \"pycore_runtime.h\"       // _PyRuntime_Initialize()\n\n#include <locale.h>               // setlocale()\n#include <stdlib.h>               // getenv()\n\n\n/* Forward declarations */\nstatic void\npreconfig_copy(PyPreConfig *config, const PyPreConfig *config2);\n\n\n/* --- File system encoding/errors -------------------------------- */\n\nconst char *Py_FileSystemDefaultEncoding = NULL;\nint Py_HasFileSystemDefaultEncoding = 0;\nconst char *Py_FileSystemDefaultEncodeErrors = NULL;\nint _Py_HasFileSystemDefaultEncodeErrors = 0;\n\nvoid\n_Py_ClearFileSystemEncoding(void)\n{\n_Py_COMP_DIAG_PUSH\n_Py_COMP_DIAG_IGNORE_DEPR_DECLS\n    if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {\n        PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);\n        Py_FileSystemDefaultEncoding = NULL;\n    }\n    if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) {\n        PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors);\n        Py_FileSystemDefaultEncodeErrors = NULL;\n    }\n_Py_COMP_DIAG_POP\n}\n\n\n/* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors\n   global configuration variables to PyConfig.filesystem_encoding and\n   PyConfig.filesystem_errors (encoded to UTF-8).\n\n   Function called by _PyUnicode_InitEncodings(). */\nint\n_Py_SetFileSystemEncoding(const char *encoding, const char *errors)\n{\n    char *encoding2 = _PyMem_RawStrdup(encoding);\n    if (encoding2 == NULL) {\n        return -1;\n    }\n\n    char *errors2 = _PyMem_RawStrdup(errors);\n    if (errors2 == NULL) {\n        PyMem_RawFree(encoding2);\n        return -1;\n    }\n\n    _Py_ClearFileSystemEncoding();\n\n_Py_COMP_DIAG_PUSH\n_Py_COMP_DIAG_IGNORE_DEPR_DECLS\n    Py_FileSystemDefaultEncoding = encoding2;\n    Py_HasFileSystemDefaultEncoding = 0;\n\n    Py_FileSystemDefaultEncodeErrors = errors2;\n    _Py_HasFileSystemDefaultEncodeErrors = 0;\n_Py_COMP_DIAG_POP\n    return 0;\n}\n\n\n/* --- _PyArgv ---------------------------------------------------- */\n\n/* Decode bytes_argv using Py_DecodeLocale() */\nPyStatus\n_PyArgv_AsWstrList(const _PyArgv *args, PyWideStringList *list)\n{\n    PyWideStringList wargv = _PyWideStringList_INIT;\n    if (args->use_bytes_argv) {\n        size_t size = sizeof(wchar_t*) * args->argc;\n        wargv.items = (wchar_t **)PyMem_RawMalloc(size);\n        if (wargv.items == NULL) {\n            return _PyStatus_NO_MEMORY();\n        }\n\n        for (Py_ssize_t i = 0; i < args->argc; i++) {\n            size_t len;\n            wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);\n            if (arg == NULL) {\n                _PyWideStringList_Clear(&wargv);\n                return DECODE_LOCALE_ERR(\"command line arguments\", len);\n            }\n            wargv.items[i] = arg;\n            wargv.length++;\n        }\n\n        _PyWideStringList_Clear(list);\n        *list = wargv;\n    }\n    else {\n        wargv.length = args->argc;\n        wargv.items = (wchar_t **)args->wchar_argv;\n        if (_PyWideStringList_Copy(list, &wargv) < 0) {\n            return _PyStatus_NO_MEMORY();\n        }\n    }\n    return _PyStatus_OK();\n}\n\n\n/* --- _PyPreCmdline ------------------------------------------------- */\n\nvoid\n_PyPreCmdline_Clear(_PyPreCmdline *cmdline)\n{\n    _PyWideStringList_Clear(&cmdline->argv);\n    _PyWideStringList_Clear(&cmdline->xoptions);\n}\n\n\nPyStatus\n_PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)\n{\n    return _PyArgv_AsWstrList(args, &cmdline->argv);\n}\n\n\nstatic void\nprecmdline_get_preconfig(_PyPreCmdline *cmdline, const PyPreConfig *config)\n{\n#define COPY_ATTR(ATTR) \\\n    if (config->ATTR != -1) { \\\n        cmdline->ATTR = config->ATTR; \\\n    }\n\n    COPY_ATTR(isolated);\n    COPY_ATTR(use_environment);\n    COPY_ATTR(dev_mode);\n\n#undef COPY_ATTR\n}\n\n\nstatic void\nprecmdline_set_preconfig(const _PyPreCmdline *cmdline, PyPreConfig *config)\n{\n#define COPY_ATTR(ATTR) \\\n    config->ATTR = cmdline->ATTR\n\n    COPY_ATTR(isolated);\n    COPY_ATTR(use_environment);\n    COPY_ATTR(dev_mode);\n\n#undef COPY_ATTR\n}\n\n\nPyStatus\n_PyPreCmdline_SetConfig(const _PyPreCmdline *cmdline, PyConfig *config)\n{\n#define COPY_ATTR(ATTR) \\\n    config->ATTR = cmdline->ATTR\n\n    PyStatus status = _PyWideStringList_Extend(&config->xoptions, &cmdline->xoptions);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    COPY_ATTR(isolated);\n    COPY_ATTR(use_environment);\n    COPY_ATTR(dev_mode);\n    COPY_ATTR(warn_default_encoding);\n    return _PyStatus_OK();\n\n#undef COPY_ATTR\n}\n\n\n/* Parse the command line arguments */\nstatic PyStatus\nprecmdline_parse_cmdline(_PyPreCmdline *cmdline)\n{\n    const PyWideStringList *argv = &cmdline->argv;\n\n    _PyOS_ResetGetOpt();\n    /* Don't log parsing errors into stderr here: PyConfig_Read()\n       is responsible for that */\n    _PyOS_opterr = 0;\n    do {\n        int longindex = -1;\n        int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);\n\n        if (c == EOF || c == 'c' || c == 'm') {\n            break;\n        }\n\n        switch (c) {\n        case 'E':\n            cmdline->use_environment = 0;\n            break;\n\n        case 'I':\n            cmdline->isolated = 1;\n            break;\n\n        case 'X':\n        {\n            PyStatus status = PyWideStringList_Append(&cmdline->xoptions,\n                                                      _PyOS_optarg);\n            if (_PyStatus_EXCEPTION(status)) {\n                return status;\n            }\n            break;\n        }\n\n        default:\n            /* ignore other argument:\n               handled by PyConfig_Read() */\n            break;\n        }\n    } while (1);\n\n    return _PyStatus_OK();\n}\n\n\nPyStatus\n_PyPreCmdline_Read(_PyPreCmdline *cmdline, const PyPreConfig *preconfig)\n{\n    precmdline_get_preconfig(cmdline, preconfig);\n\n    if (preconfig->parse_argv) {\n        PyStatus status = precmdline_parse_cmdline(cmdline);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    /* isolated, use_environment */\n    if (cmdline->isolated < 0) {\n        cmdline->isolated = 0;\n    }\n    if (cmdline->isolated > 0) {\n        cmdline->use_environment = 0;\n    }\n    if (cmdline->use_environment < 0) {\n        cmdline->use_environment = 0;\n    }\n\n    /* dev_mode */\n    if ((cmdline->dev_mode < 0)\n        && (_Py_get_xoption(&cmdline->xoptions, L\"dev\")\n            || _Py_GetEnv(cmdline->use_environment, \"PYTHONDEVMODE\")))\n    {\n        cmdline->dev_mode = 1;\n    }\n    if (cmdline->dev_mode < 0) {\n        cmdline->dev_mode = 0;\n    }\n\n    // warn_default_encoding\n    if (_Py_get_xoption(&cmdline->xoptions, L\"warn_default_encoding\")\n            || _Py_GetEnv(cmdline->use_environment, \"PYTHONWARNDEFAULTENCODING\"))\n    {\n        cmdline->warn_default_encoding = 1;\n    }\n\n    assert(cmdline->use_environment >= 0);\n    assert(cmdline->isolated >= 0);\n    assert(cmdline->dev_mode >= 0);\n    assert(cmdline->warn_default_encoding >= 0);\n\n    return _PyStatus_OK();\n}\n\n\n/* --- PyPreConfig ----------------------------------------------- */\n\n\nvoid\n_PyPreConfig_InitCompatConfig(PyPreConfig *config)\n{\n    memset(config, 0, sizeof(*config));\n\n    config->_config_init = (int)_PyConfig_INIT_COMPAT;\n    config->parse_argv = 0;\n    config->isolated = -1;\n    config->use_environment = -1;\n    config->configure_locale = 1;\n\n    /* bpo-36443: C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)\n       are disabled by default using the Compat configuration.\n\n       Py_UTF8Mode=1 enables the UTF-8 mode. PYTHONUTF8 environment variable\n       is ignored (even if use_environment=1). */\n    config->utf8_mode = 0;\n    config->coerce_c_locale = 0;\n    config->coerce_c_locale_warn = 0;\n\n    config->dev_mode = -1;\n    config->allocator = PYMEM_ALLOCATOR_NOT_SET;\n#ifdef MS_WINDOWS\n    config->legacy_windows_fs_encoding = -1;\n#endif\n}\n\n\nvoid\nPyPreConfig_InitPythonConfig(PyPreConfig *config)\n{\n    _PyPreConfig_InitCompatConfig(config);\n\n    config->_config_init = (int)_PyConfig_INIT_PYTHON;\n    config->isolated = 0;\n    config->parse_argv = 1;\n    config->use_environment = 1;\n    /* Set to -1 to enable C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)\n       depending on the LC_CTYPE locale, PYTHONUTF8 and PYTHONCOERCECLOCALE\n       environment variables. */\n    config->coerce_c_locale = -1;\n    config->coerce_c_locale_warn = -1;\n    config->utf8_mode = -1;\n#ifdef MS_WINDOWS\n    config->legacy_windows_fs_encoding = 0;\n#endif\n}\n\n\nvoid\nPyPreConfig_InitIsolatedConfig(PyPreConfig *config)\n{\n    _PyPreConfig_InitCompatConfig(config);\n\n    config->_config_init = (int)_PyConfig_INIT_ISOLATED;\n    config->configure_locale = 0;\n    config->isolated = 1;\n    config->use_environment = 0;\n    config->utf8_mode = 0;\n    config->dev_mode = 0;\n#ifdef MS_WINDOWS\n    config->legacy_windows_fs_encoding = 0;\n#endif\n}\n\n\nPyStatus\n_PyPreConfig_InitFromPreConfig(PyPreConfig *config,\n                               const PyPreConfig *config2)\n{\n    PyPreConfig_InitPythonConfig(config);\n    preconfig_copy(config, config2);\n    return _PyStatus_OK();\n}\n\n\nvoid\n_PyPreConfig_InitFromConfig(PyPreConfig *preconfig, const PyConfig *config)\n{\n    _PyConfigInitEnum config_init = (_PyConfigInitEnum)config->_config_init;\n    switch (config_init) {\n    case _PyConfig_INIT_PYTHON:\n        PyPreConfig_InitPythonConfig(preconfig);\n        break;\n    case _PyConfig_INIT_ISOLATED:\n        PyPreConfig_InitIsolatedConfig(preconfig);\n        break;\n    case _PyConfig_INIT_COMPAT:\n    default:\n        _PyPreConfig_InitCompatConfig(preconfig);\n    }\n\n    _PyPreConfig_GetConfig(preconfig, config);\n}\n\n\nstatic void\npreconfig_copy(PyPreConfig *config, const PyPreConfig *config2)\n{\n#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR\n\n    COPY_ATTR(_config_init);\n    COPY_ATTR(parse_argv);\n    COPY_ATTR(isolated);\n    COPY_ATTR(use_environment);\n    COPY_ATTR(configure_locale);\n    COPY_ATTR(dev_mode);\n    COPY_ATTR(coerce_c_locale);\n    COPY_ATTR(coerce_c_locale_warn);\n    COPY_ATTR(utf8_mode);\n    COPY_ATTR(allocator);\n#ifdef MS_WINDOWS\n    COPY_ATTR(legacy_windows_fs_encoding);\n#endif\n\n#undef COPY_ATTR\n}\n\n\nPyObject*\n_PyPreConfig_AsDict(const PyPreConfig *config)\n{\n    PyObject *dict;\n\n    dict = PyDict_New();\n    if (dict == NULL) {\n        return NULL;\n    }\n\n#define SET_ITEM_INT(ATTR) \\\n        do { \\\n            PyObject *obj = PyLong_FromLong(config->ATTR); \\\n            if (obj == NULL) { \\\n                goto fail; \\\n            } \\\n            int res = PyDict_SetItemString(dict, #ATTR, obj); \\\n            Py_DECREF(obj); \\\n            if (res < 0) { \\\n                goto fail; \\\n            } \\\n        } while (0)\n\n    SET_ITEM_INT(_config_init);\n    SET_ITEM_INT(parse_argv);\n    SET_ITEM_INT(isolated);\n    SET_ITEM_INT(use_environment);\n    SET_ITEM_INT(configure_locale);\n    SET_ITEM_INT(coerce_c_locale);\n    SET_ITEM_INT(coerce_c_locale_warn);\n    SET_ITEM_INT(utf8_mode);\n#ifdef MS_WINDOWS\n    SET_ITEM_INT(legacy_windows_fs_encoding);\n#endif\n    SET_ITEM_INT(dev_mode);\n    SET_ITEM_INT(allocator);\n    return dict;\n\nfail:\n    Py_DECREF(dict);\n    return NULL;\n\n#undef SET_ITEM_INT\n}\n\n\nvoid\n_PyPreConfig_GetConfig(PyPreConfig *preconfig, const PyConfig *config)\n{\n#define COPY_ATTR(ATTR) \\\n    if (config->ATTR != -1) { \\\n        preconfig->ATTR = config->ATTR; \\\n    }\n\n    COPY_ATTR(parse_argv);\n    COPY_ATTR(isolated);\n    COPY_ATTR(use_environment);\n    COPY_ATTR(dev_mode);\n\n#undef COPY_ATTR\n}\n\n\nstatic void\npreconfig_get_global_vars(PyPreConfig *config)\n{\n    if (config->_config_init != _PyConfig_INIT_COMPAT) {\n        /* Python and Isolated configuration ignore global variables */\n        return;\n    }\n\n#define COPY_FLAG(ATTR, VALUE) \\\n    if (config->ATTR < 0) { \\\n        config->ATTR = VALUE; \\\n    }\n#define COPY_NOT_FLAG(ATTR, VALUE) \\\n    if (config->ATTR < 0) { \\\n        config->ATTR = !(VALUE); \\\n    }\n\n_Py_COMP_DIAG_PUSH\n_Py_COMP_DIAG_IGNORE_DEPR_DECLS\n    COPY_FLAG(isolated, Py_IsolatedFlag);\n    COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);\n    if (Py_UTF8Mode > 0) {\n        config->utf8_mode = Py_UTF8Mode;\n    }\n#ifdef MS_WINDOWS\n    COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);\n#endif\n_Py_COMP_DIAG_POP\n\n#undef COPY_FLAG\n#undef COPY_NOT_FLAG\n}\n\n\nstatic void\npreconfig_set_global_vars(const PyPreConfig *config)\n{\n#define COPY_FLAG(ATTR, VAR) \\\n    if (config->ATTR >= 0) { \\\n        VAR = config->ATTR; \\\n    }\n#define COPY_NOT_FLAG(ATTR, VAR) \\\n    if (config->ATTR >= 0) { \\\n        VAR = !config->ATTR; \\\n    }\n\n_Py_COMP_DIAG_PUSH\n_Py_COMP_DIAG_IGNORE_DEPR_DECLS\n    COPY_FLAG(isolated, Py_IsolatedFlag);\n    COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);\n#ifdef MS_WINDOWS\n    COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);\n#endif\n    COPY_FLAG(utf8_mode, Py_UTF8Mode);\n_Py_COMP_DIAG_POP\n\n#undef COPY_FLAG\n#undef COPY_NOT_FLAG\n}\n\n\nconst char*\n_Py_GetEnv(int use_environment, const char *name)\n{\n    assert(use_environment >= 0);\n\n    if (!use_environment) {\n        return NULL;\n    }\n\n    const char *var = getenv(name);\n    if (var && var[0] != '\\0') {\n        return var;\n    }\n    else {\n        return NULL;\n    }\n}\n\n\nint\n_Py_str_to_int(const char *str, int *result)\n{\n    const char *endptr = str;\n    errno = 0;\n    long value = strtol(str, (char **)&endptr, 10);\n    if (*endptr != '\\0' || errno == ERANGE) {\n        return -1;\n    }\n    if (value < INT_MIN || value > INT_MAX) {\n        return -1;\n    }\n\n    *result = (int)value;\n    return 0;\n}\n\n\nvoid\n_Py_get_env_flag(int use_environment, int *flag, const char *name)\n{\n    const char *var = _Py_GetEnv(use_environment, name);\n    if (!var) {\n        return;\n    }\n    int value;\n    if (_Py_str_to_int(var, &value) < 0 || value < 0) {\n        /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */\n        value = 1;\n    }\n    if (*flag < value) {\n        *flag = value;\n    }\n}\n\n\nconst wchar_t*\n_Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name)\n{\n    for (Py_ssize_t i=0; i < xoptions->length; i++) {\n        const wchar_t *option = xoptions->items[i];\n        size_t len;\n        wchar_t *sep = wcschr(option, L'=');\n        if (sep != NULL) {\n            len = (sep - option);\n        }\n        else {\n            len = wcslen(option);\n        }\n        if (wcsncmp(option, name, len) == 0 && name[len] == L'\\0') {\n            return option;\n        }\n    }\n    return NULL;\n}\n\n\nstatic PyStatus\npreconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline)\n{\n#ifdef MS_WINDOWS\n    if (config->legacy_windows_fs_encoding) {\n        config->utf8_mode = 0;\n    }\n#endif\n\n    if (config->utf8_mode >= 0) {\n        return _PyStatus_OK();\n    }\n\n    const wchar_t *xopt;\n    xopt = _Py_get_xoption(&cmdline->xoptions, L\"utf8\");\n    if (xopt) {\n        wchar_t *sep = wcschr(xopt, L'=');\n        if (sep) {\n            xopt = sep + 1;\n            if (wcscmp(xopt, L\"1\") == 0) {\n                config->utf8_mode = 1;\n            }\n            else if (wcscmp(xopt, L\"0\") == 0) {\n                config->utf8_mode = 0;\n            }\n            else {\n                return _PyStatus_ERR(\"invalid -X utf8 option value\");\n            }\n        }\n        else {\n            config->utf8_mode = 1;\n        }\n        return _PyStatus_OK();\n    }\n\n    const char *opt = _Py_GetEnv(config->use_environment, \"PYTHONUTF8\");\n    if (opt) {\n        if (strcmp(opt, \"1\") == 0) {\n            config->utf8_mode = 1;\n        }\n        else if (strcmp(opt, \"0\") == 0) {\n            config->utf8_mode = 0;\n        }\n        else {\n            return _PyStatus_ERR(\"invalid PYTHONUTF8 environment \"\n                                \"variable value\");\n        }\n        return _PyStatus_OK();\n    }\n\n\n#ifndef MS_WINDOWS\n    if (config->utf8_mode < 0) {\n        /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */\n        const char *ctype_loc = setlocale(LC_CTYPE, NULL);\n        if (ctype_loc != NULL\n           && (strcmp(ctype_loc, \"C\") == 0\n               || strcmp(ctype_loc, \"POSIX\") == 0))\n        {\n            config->utf8_mode = 1;\n        }\n    }\n#endif\n\n    if (config->utf8_mode < 0) {\n        config->utf8_mode = 0;\n    }\n    return _PyStatus_OK();\n}\n\n\nstatic void\npreconfig_init_coerce_c_locale(PyPreConfig *config)\n{\n    if (!config->configure_locale) {\n        config->coerce_c_locale = 0;\n        config->coerce_c_locale_warn = 0;\n        return;\n    }\n\n    const char *env = _Py_GetEnv(config->use_environment, \"PYTHONCOERCECLOCALE\");\n    if (env) {\n        if (strcmp(env, \"0\") == 0) {\n            if (config->coerce_c_locale < 0) {\n                config->coerce_c_locale = 0;\n            }\n        }\n        else if (strcmp(env, \"warn\") == 0) {\n            if (config->coerce_c_locale_warn < 0) {\n                config->coerce_c_locale_warn = 1;\n            }\n        }\n        else {\n            if (config->coerce_c_locale < 0) {\n                config->coerce_c_locale = 1;\n            }\n        }\n    }\n\n    /* Test if coerce_c_locale equals to -1 or equals to 1:\n       PYTHONCOERCECLOCALE=1 doesn't imply that the C locale is always coerced.\n       It is only coerced if if the LC_CTYPE locale is \"C\". */\n    if (config->coerce_c_locale < 0 || config->coerce_c_locale == 1) {\n        /* The C locale enables the C locale coercion (PEP 538) */\n        if (_Py_LegacyLocaleDetected(0)) {\n            config->coerce_c_locale = 2;\n        }\n        else {\n            config->coerce_c_locale = 0;\n        }\n    }\n\n    if (config->coerce_c_locale_warn < 0) {\n        config->coerce_c_locale_warn = 0;\n    }\n}\n\n\nstatic PyStatus\npreconfig_init_allocator(PyPreConfig *config)\n{\n    if (config->allocator == PYMEM_ALLOCATOR_NOT_SET) {\n        /* bpo-34247. The PYTHONMALLOC environment variable has the priority\n           over PYTHONDEV env var and \"-X dev\" command line option.\n           For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory\n           allocators to \"malloc\" (and not to \"debug\"). */\n        const char *envvar = _Py_GetEnv(config->use_environment, \"PYTHONMALLOC\");\n        if (envvar) {\n            PyMemAllocatorName name;\n            if (_PyMem_GetAllocatorName(envvar, &name) < 0) {\n                return _PyStatus_ERR(\"PYTHONMALLOC: unknown allocator\");\n            }\n            config->allocator = (int)name;\n        }\n    }\n\n    if (config->dev_mode && config->allocator == PYMEM_ALLOCATOR_NOT_SET) {\n        config->allocator = PYMEM_ALLOCATOR_DEBUG;\n    }\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\npreconfig_read(PyPreConfig *config, _PyPreCmdline *cmdline)\n{\n    PyStatus status;\n\n    status = _PyPreCmdline_Read(cmdline, config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    precmdline_set_preconfig(cmdline, config);\n\n    /* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */\n#ifdef MS_WINDOWS\n    _Py_get_env_flag(config->use_environment,\n                     &config->legacy_windows_fs_encoding,\n                     \"PYTHONLEGACYWINDOWSFSENCODING\");\n#endif\n\n    preconfig_init_coerce_c_locale(config);\n\n    status = preconfig_init_utf8_mode(config, cmdline);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    /* allocator */\n    status = preconfig_init_allocator(config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    assert(config->coerce_c_locale >= 0);\n    assert(config->coerce_c_locale_warn >= 0);\n#ifdef MS_WINDOWS\n    assert(config->legacy_windows_fs_encoding >= 0);\n#endif\n    assert(config->utf8_mode >= 0);\n    assert(config->isolated >= 0);\n    assert(config->use_environment >= 0);\n    assert(config->dev_mode >= 0);\n\n    return _PyStatus_OK();\n}\n\n\n/* Read the configuration from:\n\n   - command line arguments\n   - environment variables\n   - Py_xxx global configuration variables\n   - the LC_CTYPE locale */\nPyStatus\n_PyPreConfig_Read(PyPreConfig *config, const _PyArgv *args)\n{\n    PyStatus status;\n\n    status = _PyRuntime_Initialize();\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    preconfig_get_global_vars(config);\n\n    /* Copy LC_CTYPE locale, since it's modified later */\n    const char *loc = setlocale(LC_CTYPE, NULL);\n    if (loc == NULL) {\n        return _PyStatus_ERR(\"failed to LC_CTYPE locale\");\n    }\n    char *init_ctype_locale = _PyMem_RawStrdup(loc);\n    if (init_ctype_locale == NULL) {\n        return _PyStatus_NO_MEMORY();\n    }\n\n    /* Save the config to be able to restore it if encodings change */\n    PyPreConfig save_config;\n\n    status = _PyPreConfig_InitFromPreConfig(&save_config, config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    /* Set LC_CTYPE to the user preferred locale */\n    if (config->configure_locale) {\n        _Py_SetLocaleFromEnv(LC_CTYPE);\n    }\n\n    PyPreConfig save_runtime_config;\n    preconfig_copy(&save_runtime_config, &_PyRuntime.preconfig);\n\n    _PyPreCmdline cmdline = _PyPreCmdline_INIT;\n    int locale_coerced = 0;\n    int loops = 0;\n\n    while (1) {\n        int utf8_mode = config->utf8_mode;\n\n        /* Watchdog to prevent an infinite loop */\n        loops++;\n        if (loops == 3) {\n            status = _PyStatus_ERR(\"Encoding changed twice while \"\n                                   \"reading the configuration\");\n            goto done;\n        }\n\n        /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend\n           on the utf8_mode and legacy_windows_fs_encoding members\n           of _PyRuntime.preconfig. */\n        preconfig_copy(&_PyRuntime.preconfig, config);\n\n        if (args) {\n            // Set command line arguments at each iteration. If they are bytes\n            // strings, they are decoded from the new encoding.\n            status = _PyPreCmdline_SetArgv(&cmdline, args);\n            if (_PyStatus_EXCEPTION(status)) {\n                goto done;\n            }\n        }\n\n        status = preconfig_read(config, &cmdline);\n        if (_PyStatus_EXCEPTION(status)) {\n            goto done;\n        }\n\n        /* The legacy C locale assumes ASCII as the default text encoding, which\n         * causes problems not only for the CPython runtime, but also other\n         * components like GNU readline.\n         *\n         * Accordingly, when the CLI detects it, it attempts to coerce it to a\n         * more capable UTF-8 based alternative.\n         *\n         * See the documentation of the PYTHONCOERCECLOCALE setting for more\n         * details.\n         */\n        int encoding_changed = 0;\n        if (config->coerce_c_locale && !locale_coerced) {\n            locale_coerced = 1;\n            _Py_CoerceLegacyLocale(0);\n            encoding_changed = 1;\n        }\n\n        if (utf8_mode == -1) {\n            if (config->utf8_mode == 1) {\n                /* UTF-8 Mode enabled */\n                encoding_changed = 1;\n            }\n        }\n        else {\n            if (config->utf8_mode != utf8_mode) {\n                encoding_changed = 1;\n            }\n        }\n\n        if (!encoding_changed) {\n            break;\n        }\n\n        /* Reset the configuration before reading again the configuration,\n           just keep UTF-8 Mode and coerce C locale value. */\n        int new_utf8_mode = config->utf8_mode;\n        int new_coerce_c_locale = config->coerce_c_locale;\n        preconfig_copy(config, &save_config);\n        config->utf8_mode = new_utf8_mode;\n        config->coerce_c_locale = new_coerce_c_locale;\n\n        /* The encoding changed: read again the configuration\n           with the new encoding */\n    }\n    status = _PyStatus_OK();\n\ndone:\n    // Revert side effects\n    setlocale(LC_CTYPE, init_ctype_locale);\n    PyMem_RawFree(init_ctype_locale);\n    preconfig_copy(&_PyRuntime.preconfig, &save_runtime_config);\n    _PyPreCmdline_Clear(&cmdline);\n    return status;\n}\n\n\n/* Write the pre-configuration:\n\n   - set the memory allocators\n   - set Py_xxx global configuration variables\n   - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode\n     (PEP 540)\n\n   The applied configuration is written into _PyRuntime.preconfig.\n   If the C locale cannot be coerced, set coerce_c_locale to 0.\n\n   Do nothing if called after Py_Initialize(): ignore the new\n   pre-configuration. */\nPyStatus\n_PyPreConfig_Write(const PyPreConfig *src_config)\n{\n    PyPreConfig config;\n\n    PyStatus status = _PyPreConfig_InitFromPreConfig(&config, src_config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    if (_PyRuntime.core_initialized) {\n        /* bpo-34008: Calling this functions after Py_Initialize() ignores\n           the new configuration. */\n        return _PyStatus_OK();\n    }\n\n    PyMemAllocatorName name = (PyMemAllocatorName)config.allocator;\n    if (name != PYMEM_ALLOCATOR_NOT_SET) {\n        if (_PyMem_SetupAllocators(name) < 0) {\n            return _PyStatus_ERR(\"Unknown PYTHONMALLOC allocator\");\n        }\n    }\n\n    preconfig_set_global_vars(&config);\n\n    if (config.configure_locale) {\n        if (config.coerce_c_locale) {\n            if (!_Py_CoerceLegacyLocale(config.coerce_c_locale_warn)) {\n                /* C locale not coerced */\n                config.coerce_c_locale = 0;\n            }\n        }\n\n        /* Set LC_CTYPE to the user preferred locale */\n        _Py_SetLocaleFromEnv(LC_CTYPE);\n    }\n\n    /* Write the new pre-configuration into _PyRuntime */\n    preconfig_copy(&_PyRuntime.preconfig, &config);\n\n    return _PyStatus_OK();\n}\n"
  },
  {
    "path": "PyArena.c",
    "content": "#include \"Python.h\"\n#include \"pycore_pyarena.h\"       // PyArena\n\n/* A simple arena block structure.\n\n   Measurements with standard library modules suggest the average\n   allocation is about 20 bytes and that most compiles use a single\n   block.\n\n   TODO(jhylton): Think about a realloc API, maybe just for the last\n   allocation?\n*/\n\n#define DEFAULT_BLOCK_SIZE 8192\n#define ALIGNMENT               8\n\ntypedef struct _block {\n    /* Total number of bytes owned by this block available to pass out.\n     * Read-only after initialization.  The first such byte starts at\n     * ab_mem.\n     */\n    size_t ab_size;\n\n    /* Total number of bytes already passed out.  The next byte available\n     * to pass out starts at ab_mem + ab_offset.\n     */\n    size_t ab_offset;\n\n    /* An arena maintains a singly-linked, NULL-terminated list of\n     * all blocks owned by the arena.  These are linked via the\n     * ab_next member.\n     */\n    struct _block *ab_next;\n\n    /* Pointer to the first allocatable byte owned by this block.  Read-\n     * only after initialization.\n     */\n    void *ab_mem;\n} block;\n\n/* The arena manages two kinds of memory, blocks of raw memory\n   and a list of PyObject* pointers.  PyObjects are decrefed\n   when the arena is freed.\n*/\n\nstruct _arena {\n    /* Pointer to the first block allocated for the arena, never NULL.\n       It is used only to find the first block when the arena is\n       being freed.\n     */\n    block *a_head;\n\n    /* Pointer to the block currently used for allocation.  Its\n       ab_next field should be NULL.  If it is not-null after a\n       call to block_alloc(), it means a new block has been allocated\n       and a_cur should be reset to point it.\n     */\n    block *a_cur;\n\n    /* A Python list object containing references to all the PyObject\n       pointers associated with this arena.  They will be DECREFed\n       when the arena is freed.\n    */\n    PyObject *a_objects;\n\n#if defined(Py_DEBUG)\n    /* Debug output */\n    size_t total_allocs;\n    size_t total_size;\n    size_t total_blocks;\n    size_t total_block_size;\n    size_t total_big_blocks;\n#endif\n};\n\nstatic block *\nblock_new(size_t size)\n{\n    /* Allocate header and block as one unit.\n       ab_mem points just past header. */\n    block *b = (block *)PyMem_Malloc(sizeof(block) + size);\n    if (!b)\n        return NULL;\n    b->ab_size = size;\n    b->ab_mem = (void *)(b + 1);\n    b->ab_next = NULL;\n    b->ab_offset = (char *)_Py_ALIGN_UP(b->ab_mem, ALIGNMENT) -\n            (char *)(b->ab_mem);\n    return b;\n}\n\nstatic void\nblock_free(block *b) {\n    while (b) {\n        block *next = b->ab_next;\n        PyMem_Free(b);\n        b = next;\n    }\n}\n\nstatic void *\nblock_alloc(block *b, size_t size)\n{\n    void *p;\n    assert(b);\n    size = _Py_SIZE_ROUND_UP(size, ALIGNMENT);\n    if (b->ab_offset + size > b->ab_size) {\n        /* If we need to allocate more memory than will fit in\n           the default block, allocate a one-off block that is\n           exactly the right size. */\n        /* TODO(jhylton): Think about space waste at end of block */\n        block *newbl = block_new(\n                        size < DEFAULT_BLOCK_SIZE ?\n                        DEFAULT_BLOCK_SIZE : size);\n        if (!newbl)\n            return NULL;\n        assert(!b->ab_next);\n        b->ab_next = newbl;\n        b = newbl;\n    }\n\n    assert(b->ab_offset + size <= b->ab_size);\n    p = (void *)(((char *)b->ab_mem) + b->ab_offset);\n    b->ab_offset += size;\n    return p;\n}\n\nPyArena *\n_PyArena_New(void)\n{\n    PyArena* arena = (PyArena *)PyMem_Malloc(sizeof(PyArena));\n    if (!arena)\n        return (PyArena*)PyErr_NoMemory();\n\n    arena->a_head = block_new(DEFAULT_BLOCK_SIZE);\n    arena->a_cur = arena->a_head;\n    if (!arena->a_head) {\n        PyMem_Free((void *)arena);\n        return (PyArena*)PyErr_NoMemory();\n    }\n    arena->a_objects = PyList_New(0);\n    if (!arena->a_objects) {\n        block_free(arena->a_head);\n        PyMem_Free((void *)arena);\n        return (PyArena*)PyErr_NoMemory();\n    }\n#if defined(Py_DEBUG)\n    arena->total_allocs = 0;\n    arena->total_size = 0;\n    arena->total_blocks = 1;\n    arena->total_block_size = DEFAULT_BLOCK_SIZE;\n    arena->total_big_blocks = 0;\n#endif\n    return arena;\n}\n\nvoid\n_PyArena_Free(PyArena *arena)\n{\n    assert(arena);\n#if defined(Py_DEBUG)\n    /*\n    fprintf(stderr,\n        \"alloc=%zu size=%zu blocks=%zu block_size=%zu big=%zu objects=%zu\\n\",\n        arena->total_allocs, arena->total_size, arena->total_blocks,\n        arena->total_block_size, arena->total_big_blocks,\n        PyList_Size(arena->a_objects));\n    */\n#endif\n    block_free(arena->a_head);\n    /* This property normally holds, except when the code being compiled\n       is sys.getobjects(0), in which case there will be two references.\n    assert(arena->a_objects->ob_refcnt == 1);\n    */\n\n    Py_DECREF(arena->a_objects);\n    PyMem_Free(arena);\n}\n\nvoid *\n_PyArena_Malloc(PyArena *arena, size_t size)\n{\n    void *p = block_alloc(arena->a_cur, size);\n    if (!p)\n        return PyErr_NoMemory();\n#if defined(Py_DEBUG)\n    arena->total_allocs++;\n    arena->total_size += size;\n#endif\n    /* Reset cur if we allocated a new block. */\n    if (arena->a_cur->ab_next) {\n        arena->a_cur = arena->a_cur->ab_next;\n#if defined(Py_DEBUG)\n        arena->total_blocks++;\n        arena->total_block_size += arena->a_cur->ab_size;\n        if (arena->a_cur->ab_size > DEFAULT_BLOCK_SIZE)\n            ++arena->total_big_blocks;\n#endif\n    }\n    return p;\n}\n\nint\n_PyArena_AddPyObject(PyArena *arena, PyObject *obj)\n{\n    int r = PyList_Append(arena->a_objects, obj);\n    if (r >= 0) {\n        Py_DECREF(obj);\n    }\n    return r;\n}\n"
  },
  {
    "path": "PyCtype.c",
    "content": "#include \"Python.h\"\n\n/* Our own locale-independent ctype.h-like macros */\n\nconst unsigned int _Py_ctype_table[256] = {\n    0, /* 0x0 '\\x00' */\n    0, /* 0x1 '\\x01' */\n    0, /* 0x2 '\\x02' */\n    0, /* 0x3 '\\x03' */\n    0, /* 0x4 '\\x04' */\n    0, /* 0x5 '\\x05' */\n    0, /* 0x6 '\\x06' */\n    0, /* 0x7 '\\x07' */\n    0, /* 0x8 '\\x08' */\n    PY_CTF_SPACE, /* 0x9 '\\t' */\n    PY_CTF_SPACE, /* 0xa '\\n' */\n    PY_CTF_SPACE, /* 0xb '\\v' */\n    PY_CTF_SPACE, /* 0xc '\\f' */\n    PY_CTF_SPACE, /* 0xd '\\r' */\n    0, /* 0xe '\\x0e' */\n    0, /* 0xf '\\x0f' */\n    0, /* 0x10 '\\x10' */\n    0, /* 0x11 '\\x11' */\n    0, /* 0x12 '\\x12' */\n    0, /* 0x13 '\\x13' */\n    0, /* 0x14 '\\x14' */\n    0, /* 0x15 '\\x15' */\n    0, /* 0x16 '\\x16' */\n    0, /* 0x17 '\\x17' */\n    0, /* 0x18 '\\x18' */\n    0, /* 0x19 '\\x19' */\n    0, /* 0x1a '\\x1a' */\n    0, /* 0x1b '\\x1b' */\n    0, /* 0x1c '\\x1c' */\n    0, /* 0x1d '\\x1d' */\n    0, /* 0x1e '\\x1e' */\n    0, /* 0x1f '\\x1f' */\n    PY_CTF_SPACE, /* 0x20 ' ' */\n    0, /* 0x21 '!' */\n    0, /* 0x22 '\"' */\n    0, /* 0x23 '#' */\n    0, /* 0x24 '$' */\n    0, /* 0x25 '%' */\n    0, /* 0x26 '&' */\n    0, /* 0x27 \"'\" */\n    0, /* 0x28 '(' */\n    0, /* 0x29 ')' */\n    0, /* 0x2a '*' */\n    0, /* 0x2b '+' */\n    0, /* 0x2c ',' */\n    0, /* 0x2d '-' */\n    0, /* 0x2e '.' */\n    0, /* 0x2f '/' */\n    PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x30 '0' */\n    PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x31 '1' */\n    PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x32 '2' */\n    PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x33 '3' */\n    PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x34 '4' */\n    PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x35 '5' */\n    PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x36 '6' */\n    PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x37 '7' */\n    PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x38 '8' */\n    PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x39 '9' */\n    0, /* 0x3a ':' */\n    0, /* 0x3b ';' */\n    0, /* 0x3c '<' */\n    0, /* 0x3d '=' */\n    0, /* 0x3e '>' */\n    0, /* 0x3f '?' */\n    0, /* 0x40 '@' */\n    PY_CTF_UPPER|PY_CTF_XDIGIT, /* 0x41 'A' */\n    PY_CTF_UPPER|PY_CTF_XDIGIT, /* 0x42 'B' */\n    PY_CTF_UPPER|PY_CTF_XDIGIT, /* 0x43 'C' */\n    PY_CTF_UPPER|PY_CTF_XDIGIT, /* 0x44 'D' */\n    PY_CTF_UPPER|PY_CTF_XDIGIT, /* 0x45 'E' */\n    PY_CTF_UPPER|PY_CTF_XDIGIT, /* 0x46 'F' */\n    PY_CTF_UPPER, /* 0x47 'G' */\n    PY_CTF_UPPER, /* 0x48 'H' */\n    PY_CTF_UPPER, /* 0x49 'I' */\n    PY_CTF_UPPER, /* 0x4a 'J' */\n    PY_CTF_UPPER, /* 0x4b 'K' */\n    PY_CTF_UPPER, /* 0x4c 'L' */\n    PY_CTF_UPPER, /* 0x4d 'M' */\n    PY_CTF_UPPER, /* 0x4e 'N' */\n    PY_CTF_UPPER, /* 0x4f 'O' */\n    PY_CTF_UPPER, /* 0x50 'P' */\n    PY_CTF_UPPER, /* 0x51 'Q' */\n    PY_CTF_UPPER, /* 0x52 'R' */\n    PY_CTF_UPPER, /* 0x53 'S' */\n    PY_CTF_UPPER, /* 0x54 'T' */\n    PY_CTF_UPPER, /* 0x55 'U' */\n    PY_CTF_UPPER, /* 0x56 'V' */\n    PY_CTF_UPPER, /* 0x57 'W' */\n    PY_CTF_UPPER, /* 0x58 'X' */\n    PY_CTF_UPPER, /* 0x59 'Y' */\n    PY_CTF_UPPER, /* 0x5a 'Z' */\n    0, /* 0x5b '[' */\n    0, /* 0x5c '\\\\' */\n    0, /* 0x5d ']' */\n    0, /* 0x5e '^' */\n    0, /* 0x5f '_' */\n    0, /* 0x60 '`' */\n    PY_CTF_LOWER|PY_CTF_XDIGIT, /* 0x61 'a' */\n    PY_CTF_LOWER|PY_CTF_XDIGIT, /* 0x62 'b' */\n    PY_CTF_LOWER|PY_CTF_XDIGIT, /* 0x63 'c' */\n    PY_CTF_LOWER|PY_CTF_XDIGIT, /* 0x64 'd' */\n    PY_CTF_LOWER|PY_CTF_XDIGIT, /* 0x65 'e' */\n    PY_CTF_LOWER|PY_CTF_XDIGIT, /* 0x66 'f' */\n    PY_CTF_LOWER, /* 0x67 'g' */\n    PY_CTF_LOWER, /* 0x68 'h' */\n    PY_CTF_LOWER, /* 0x69 'i' */\n    PY_CTF_LOWER, /* 0x6a 'j' */\n    PY_CTF_LOWER, /* 0x6b 'k' */\n    PY_CTF_LOWER, /* 0x6c 'l' */\n    PY_CTF_LOWER, /* 0x6d 'm' */\n    PY_CTF_LOWER, /* 0x6e 'n' */\n    PY_CTF_LOWER, /* 0x6f 'o' */\n    PY_CTF_LOWER, /* 0x70 'p' */\n    PY_CTF_LOWER, /* 0x71 'q' */\n    PY_CTF_LOWER, /* 0x72 'r' */\n    PY_CTF_LOWER, /* 0x73 's' */\n    PY_CTF_LOWER, /* 0x74 't' */\n    PY_CTF_LOWER, /* 0x75 'u' */\n    PY_CTF_LOWER, /* 0x76 'v' */\n    PY_CTF_LOWER, /* 0x77 'w' */\n    PY_CTF_LOWER, /* 0x78 'x' */\n    PY_CTF_LOWER, /* 0x79 'y' */\n    PY_CTF_LOWER, /* 0x7a 'z' */\n    0, /* 0x7b '{' */\n    0, /* 0x7c '|' */\n    0, /* 0x7d '}' */\n    0, /* 0x7e '~' */\n    0, /* 0x7f '\\x7f' */\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n};\n\n\nconst unsigned char _Py_ctype_tolower[256] = {\n    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,\n    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,\n    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,\n    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,\n    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,\n    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,\n    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,\n    0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,\n    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,\n    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,\n    0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,\n    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,\n    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,\n    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,\n    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,\n    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,\n    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,\n    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,\n    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,\n    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,\n    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,\n    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,\n    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,\n    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,\n    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,\n    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,\n    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,\n    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,\n    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,\n    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,\n    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,\n};\n\nconst unsigned char _Py_ctype_toupper[256] = {\n    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,\n    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,\n    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,\n    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,\n    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,\n    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,\n    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,\n    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,\n    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,\n    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,\n    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,\n    0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,\n    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,\n    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,\n    0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,\n    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,\n    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,\n    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,\n    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,\n    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,\n    0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,\n    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,\n    0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,\n    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,\n    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,\n    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,\n    0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,\n    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,\n    0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,\n    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,\n    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,\n};\n\n"
  },
  {
    "path": "PyFpc.c",
    "content": "/* These variables used to be used when Python was built with --with-fpectl,\n * but support for that was dropped in 3.7. We continue to define them,\n * though, because they may be referenced by extensions using the stable ABI.\n */\n\n#ifdef HAVE_SETJMP_H\n#include <setjmp.h>\n\njmp_buf PyFPE_jbuf;\n#endif\n\nint PyFPE_counter;\n\ndouble\nPyFPE_dummy(void *dummy)\n{\n    return 1.0;\n}\n"
  },
  {
    "path": "PyHash.c",
    "content": "/* Set of hash utility functions to help maintaining the invariant that\n    if a==b then hash(a)==hash(b)\n\n   All the utility functions (_Py_Hash*()) return \"-1\" to signify an error.\n*/\n#include \"Python.h\"\n\n#ifdef __APPLE__\n#  include <libkern/OSByteOrder.h>\n#elif defined(HAVE_LE64TOH) && defined(HAVE_ENDIAN_H)\n#  include <endian.h>\n#elif defined(HAVE_LE64TOH) && defined(HAVE_SYS_ENDIAN_H)\n#  include <sys/endian.h>\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n_Py_HashSecret_t _Py_HashSecret = {{0}};\n\n#if Py_HASH_ALGORITHM == Py_HASH_EXTERNAL\nextern PyHash_FuncDef PyHash_Func;\n#else\nstatic PyHash_FuncDef PyHash_Func;\n#endif\n\n/* Count _Py_HashBytes() calls */\n#ifdef Py_HASH_STATS\n#define Py_HASH_STATS_MAX 32\nstatic Py_ssize_t hashstats[Py_HASH_STATS_MAX + 1] = {0};\n#endif\n\n/* For numeric types, the hash of a number x is based on the reduction\n   of x modulo the prime P = 2**_PyHASH_BITS - 1.  It's designed so that\n   hash(x) == hash(y) whenever x and y are numerically equal, even if\n   x and y have different types.\n\n   A quick summary of the hashing strategy:\n\n   (1) First define the 'reduction of x modulo P' for any rational\n   number x; this is a standard extension of the usual notion of\n   reduction modulo P for integers.  If x == p/q (written in lowest\n   terms), the reduction is interpreted as the reduction of p times\n   the inverse of the reduction of q, all modulo P; if q is exactly\n   divisible by P then define the reduction to be infinity.  So we've\n   got a well-defined map\n\n      reduce : { rational numbers } -> { 0, 1, 2, ..., P-1, infinity }.\n\n   (2) Now for a rational number x, define hash(x) by:\n\n      reduce(x)   if x >= 0\n      -reduce(-x) if x < 0\n\n   If the result of the reduction is infinity (this is impossible for\n   integers, floats and Decimals) then use the predefined hash value\n   _PyHASH_INF for x >= 0, or -_PyHASH_INF for x < 0, instead.\n   _PyHASH_INF and -_PyHASH_INF are also used for the\n   hashes of float and Decimal infinities.\n\n   NaNs hash with a pointer hash.  Having distinct hash values prevents\n   catastrophic pileups from distinct NaN instances which used to always\n   have the same hash value but would compare unequal.\n\n   A selling point for the above strategy is that it makes it possible\n   to compute hashes of decimal and binary floating-point numbers\n   efficiently, even if the exponent of the binary or decimal number\n   is large.  The key point is that\n\n      reduce(x * y) == reduce(x) * reduce(y) (modulo _PyHASH_MODULUS)\n\n   provided that {reduce(x), reduce(y)} != {0, infinity}.  The reduction of a\n   binary or decimal float is never infinity, since the denominator is a power\n   of 2 (for binary) or a divisor of a power of 10 (for decimal).  So we have,\n   for nonnegative x,\n\n      reduce(x * 2**e) == reduce(x) * reduce(2**e) % _PyHASH_MODULUS\n\n      reduce(x * 10**e) == reduce(x) * reduce(10**e) % _PyHASH_MODULUS\n\n   and reduce(10**e) can be computed efficiently by the usual modular\n   exponentiation algorithm.  For reduce(2**e) it's even better: since\n   P is of the form 2**n-1, reduce(2**e) is 2**(e mod n), and multiplication\n   by 2**(e mod n) modulo 2**n-1 just amounts to a rotation of bits.\n\n   */\n\nPy_hash_t _Py_HashPointer(const void *);\n\nPy_hash_t\n_Py_HashDouble(PyObject *inst, double v)\n{\n    int e, sign;\n    double m;\n    Py_uhash_t x, y;\n\n    if (!Py_IS_FINITE(v)) {\n        if (Py_IS_INFINITY(v))\n            return v > 0 ? _PyHASH_INF : -_PyHASH_INF;\n        else\n            return _Py_HashPointer(inst);\n    }\n\n    m = frexp(v, &e);\n\n    sign = 1;\n    if (m < 0) {\n        sign = -1;\n        m = -m;\n    }\n\n    /* process 28 bits at a time;  this should work well both for binary\n       and hexadecimal floating point. */\n    x = 0;\n    while (m) {\n        x = ((x << 28) & _PyHASH_MODULUS) | x >> (_PyHASH_BITS - 28);\n        m *= 268435456.0;  /* 2**28 */\n        e -= 28;\n        y = (Py_uhash_t)m;  /* pull out integer part */\n        m -= y;\n        x += y;\n        if (x >= _PyHASH_MODULUS)\n            x -= _PyHASH_MODULUS;\n    }\n\n    /* adjust for the exponent;  first reduce it modulo _PyHASH_BITS */\n    e = e >= 0 ? e % _PyHASH_BITS : _PyHASH_BITS-1-((-1-e) % _PyHASH_BITS);\n    x = ((x << e) & _PyHASH_MODULUS) | x >> (_PyHASH_BITS - e);\n\n    x = x * sign;\n    if (x == (Py_uhash_t)-1)\n        x = (Py_uhash_t)-2;\n    return (Py_hash_t)x;\n}\n\nPy_hash_t\n_Py_HashPointerRaw(const void *p)\n{\n    size_t y = (size_t)p;\n    /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid\n       excessive hash collisions for dicts and sets */\n    y = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4));\n    return (Py_hash_t)y;\n}\n\nPy_hash_t\n_Py_HashPointer(const void *p)\n{\n    Py_hash_t x = _Py_HashPointerRaw(p);\n    if (x == -1) {\n        x = -2;\n    }\n    return x;\n}\n\nPy_hash_t\n_Py_HashBytes(const void *src, Py_ssize_t len)\n{\n    Py_hash_t x;\n    /*\n      We make the hash of the empty string be 0, rather than using\n      (prefix ^ suffix), since this slightly obfuscates the hash secret\n    */\n    if (len == 0) {\n        return 0;\n    }\n\n#ifdef Py_HASH_STATS\n    hashstats[(len <= Py_HASH_STATS_MAX) ? len : 0]++;\n#endif\n\n#if Py_HASH_CUTOFF > 0\n    if (len < Py_HASH_CUTOFF) {\n        /* Optimize hashing of very small strings with inline DJBX33A. */\n        Py_uhash_t hash;\n        const unsigned char *p = src;\n        hash = 5381; /* DJBX33A starts with 5381 */\n\n        switch(len) {\n            /* ((hash << 5) + hash) + *p == hash * 33 + *p */\n            case 7: hash = ((hash << 5) + hash) + *p++; /* fallthrough */\n            case 6: hash = ((hash << 5) + hash) + *p++; /* fallthrough */\n            case 5: hash = ((hash << 5) + hash) + *p++; /* fallthrough */\n            case 4: hash = ((hash << 5) + hash) + *p++; /* fallthrough */\n            case 3: hash = ((hash << 5) + hash) + *p++; /* fallthrough */\n            case 2: hash = ((hash << 5) + hash) + *p++; /* fallthrough */\n            case 1: hash = ((hash << 5) + hash) + *p++; break;\n            default:\n                Py_UNREACHABLE();\n        }\n        hash ^= len;\n        hash ^= (Py_uhash_t) _Py_HashSecret.djbx33a.suffix;\n        x = (Py_hash_t)hash;\n    }\n    else\n#endif /* Py_HASH_CUTOFF */\n        x = PyHash_Func.hash(src, len);\n\n    if (x == -1)\n        return -2;\n    return x;\n}\n\nvoid\n_PyHash_Fini(void)\n{\n#ifdef Py_HASH_STATS\n    fprintf(stderr, \"len   calls    total\\n\");\n    Py_ssize_t total = 0;\n    for (int i = 1; i <= Py_HASH_STATS_MAX; i++) {\n        total += hashstats[i];\n        fprintf(stderr, \"%2i %8zd %8zd\\n\", i, hashstats[i], total);\n    }\n    total += hashstats[0];\n    fprintf(stderr, \">  %8zd %8zd\\n\", hashstats[0], total);\n#endif\n}\n\nPyHash_FuncDef *\nPyHash_GetFuncDef(void)\n{\n    return &PyHash_Func;\n}\n\n/* Optimized memcpy() for Windows */\n#ifdef _MSC_VER\n#  if SIZEOF_PY_UHASH_T == 4\n#    define PY_UHASH_CPY(dst, src) do {                                    \\\n       dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst[3] = src[3]; \\\n       } while(0)\n#  elif SIZEOF_PY_UHASH_T == 8\n#    define PY_UHASH_CPY(dst, src) do {                                    \\\n       dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; dst[3] = src[3]; \\\n       dst[4] = src[4]; dst[5] = src[5]; dst[6] = src[6]; dst[7] = src[7]; \\\n       } while(0)\n#  else\n#    error SIZEOF_PY_UHASH_T must be 4 or 8\n#  endif /* SIZEOF_PY_UHASH_T */\n#else /* not Windows */\n#  define PY_UHASH_CPY(dst, src) memcpy(dst, src, SIZEOF_PY_UHASH_T)\n#endif /* _MSC_VER */\n\n\n#if Py_HASH_ALGORITHM == Py_HASH_FNV\n/* **************************************************************************\n * Modified Fowler-Noll-Vo (FNV) hash function\n */\nstatic Py_hash_t\nfnv(const void *src, Py_ssize_t len)\n{\n    const unsigned char *p = src;\n    Py_uhash_t x;\n    Py_ssize_t remainder, blocks;\n    union {\n        Py_uhash_t value;\n        unsigned char bytes[SIZEOF_PY_UHASH_T];\n    } block;\n\n#ifdef Py_DEBUG\n    assert(_Py_HashSecret_Initialized);\n#endif\n    remainder = len % SIZEOF_PY_UHASH_T;\n    if (remainder == 0) {\n        /* Process at least one block byte by byte to reduce hash collisions\n         * for strings with common prefixes. */\n        remainder = SIZEOF_PY_UHASH_T;\n    }\n    blocks = (len - remainder) / SIZEOF_PY_UHASH_T;\n\n    x = (Py_uhash_t) _Py_HashSecret.fnv.prefix;\n    x ^= (Py_uhash_t) *p << 7;\n    while (blocks--) {\n        PY_UHASH_CPY(block.bytes, p);\n        x = (_PyHASH_MULTIPLIER * x) ^ block.value;\n        p += SIZEOF_PY_UHASH_T;\n    }\n    /* add remainder */\n    for (; remainder > 0; remainder--)\n        x = (_PyHASH_MULTIPLIER * x) ^ (Py_uhash_t) *p++;\n    x ^= (Py_uhash_t) len;\n    x ^= (Py_uhash_t) _Py_HashSecret.fnv.suffix;\n    if (x == (Py_uhash_t) -1) {\n        x = (Py_uhash_t) -2;\n    }\n    return x;\n}\n\nstatic PyHash_FuncDef PyHash_Func = {fnv, \"fnv\", 8 * SIZEOF_PY_HASH_T,\n                                     16 * SIZEOF_PY_HASH_T};\n\n#endif /* Py_HASH_ALGORITHM == Py_HASH_FNV */\n\n\n/* **************************************************************************\n <MIT License>\n Copyright (c) 2013  Marek Majkowski <marek@popcount.org>\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n </MIT License>\n\n Original location:\n    https://github.com/majek/csiphash/\n\n Solution inspired by code from:\n    Samuel Neves (supercop/crypto_auth/siphash24/little)\n    djb (supercop/crypto_auth/siphash24/little2)\n    Jean-Philippe Aumasson (https://131002.net/siphash/siphash24.c)\n\n Modified for Python by Christian Heimes:\n    - C89 / MSVC compatibility\n    - _rotl64() on Windows\n    - letoh64() fallback\n*/\n\n/* byte swap little endian to host endian\n * Endian conversion not only ensures that the hash function returns the same\n * value on all platforms. It is also required to for a good dispersion of\n * the hash values' least significant bits.\n */\n#if PY_LITTLE_ENDIAN\n#  define _le64toh(x) ((uint64_t)(x))\n#elif defined(__APPLE__)\n#  define _le64toh(x) OSSwapLittleToHostInt64(x)\n#elif defined(HAVE_LETOH64)\n#  define _le64toh(x) le64toh(x)\n#else\n#  define _le64toh(x) (((uint64_t)(x) << 56) | \\\n                      (((uint64_t)(x) << 40) & 0xff000000000000ULL) | \\\n                      (((uint64_t)(x) << 24) & 0xff0000000000ULL) | \\\n                      (((uint64_t)(x) << 8)  & 0xff00000000ULL) | \\\n                      (((uint64_t)(x) >> 8)  & 0xff000000ULL) | \\\n                      (((uint64_t)(x) >> 24) & 0xff0000ULL) | \\\n                      (((uint64_t)(x) >> 40) & 0xff00ULL) | \\\n                      ((uint64_t)(x)  >> 56))\n#endif\n\n\n#ifdef _MSC_VER\n#  define ROTATE(x, b)  _rotl64(x, b)\n#else\n#  define ROTATE(x, b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )\n#endif\n\n#define HALF_ROUND(a,b,c,d,s,t)     \\\n    a += b; c += d;                 \\\n    b = ROTATE(b, s) ^ a;           \\\n    d = ROTATE(d, t) ^ c;           \\\n    a = ROTATE(a, 32);\n\n#define SINGLE_ROUND(v0,v1,v2,v3)   \\\n    HALF_ROUND(v0,v1,v2,v3,13,16);  \\\n    HALF_ROUND(v2,v1,v0,v3,17,21);\n\n#define DOUBLE_ROUND(v0,v1,v2,v3)   \\\n    SINGLE_ROUND(v0,v1,v2,v3);      \\\n    SINGLE_ROUND(v0,v1,v2,v3);\n\n\nstatic uint64_t\nsiphash13(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) {\n    uint64_t b = (uint64_t)src_sz << 56;\n    const uint8_t *in = (const uint8_t*)src;\n\n    uint64_t v0 = k0 ^ 0x736f6d6570736575ULL;\n    uint64_t v1 = k1 ^ 0x646f72616e646f6dULL;\n    uint64_t v2 = k0 ^ 0x6c7967656e657261ULL;\n    uint64_t v3 = k1 ^ 0x7465646279746573ULL;\n\n    uint64_t t;\n    uint8_t *pt;\n\n    while (src_sz >= 8) {\n        uint64_t mi;\n        memcpy(&mi, in, sizeof(mi));\n        mi = _le64toh(mi);\n        in += sizeof(mi);\n        src_sz -= sizeof(mi);\n        v3 ^= mi;\n        SINGLE_ROUND(v0,v1,v2,v3);\n        v0 ^= mi;\n    }\n\n    t = 0;\n    pt = (uint8_t *)&t;\n    switch (src_sz) {\n        case 7: pt[6] = in[6]; /* fall through */\n        case 6: pt[5] = in[5]; /* fall through */\n        case 5: pt[4] = in[4]; /* fall through */\n        case 4: memcpy(pt, in, sizeof(uint32_t)); break;\n        case 3: pt[2] = in[2]; /* fall through */\n        case 2: pt[1] = in[1]; /* fall through */\n        case 1: pt[0] = in[0]; /* fall through */\n    }\n    b |= _le64toh(t);\n\n    v3 ^= b;\n    SINGLE_ROUND(v0,v1,v2,v3);\n    v0 ^= b;\n    v2 ^= 0xff;\n    SINGLE_ROUND(v0,v1,v2,v3);\n    SINGLE_ROUND(v0,v1,v2,v3);\n    SINGLE_ROUND(v0,v1,v2,v3);\n\n    /* modified */\n    t = (v0 ^ v1) ^ (v2 ^ v3);\n    return t;\n}\n\n#if Py_HASH_ALGORITHM == Py_HASH_SIPHASH24\nstatic uint64_t\nsiphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) {\n    uint64_t b = (uint64_t)src_sz << 56;\n    const uint8_t *in = (const uint8_t*)src;\n\n    uint64_t v0 = k0 ^ 0x736f6d6570736575ULL;\n    uint64_t v1 = k1 ^ 0x646f72616e646f6dULL;\n    uint64_t v2 = k0 ^ 0x6c7967656e657261ULL;\n    uint64_t v3 = k1 ^ 0x7465646279746573ULL;\n\n    uint64_t t;\n    uint8_t *pt;\n\n    while (src_sz >= 8) {\n        uint64_t mi;\n        memcpy(&mi, in, sizeof(mi));\n        mi = _le64toh(mi);\n        in += sizeof(mi);\n        src_sz -= sizeof(mi);\n        v3 ^= mi;\n        DOUBLE_ROUND(v0,v1,v2,v3);\n        v0 ^= mi;\n    }\n\n    t = 0;\n    pt = (uint8_t *)&t;\n    switch (src_sz) {\n        case 7: pt[6] = in[6]; /* fall through */\n        case 6: pt[5] = in[5]; /* fall through */\n        case 5: pt[4] = in[4]; /* fall through */\n        case 4: memcpy(pt, in, sizeof(uint32_t)); break;\n        case 3: pt[2] = in[2]; /* fall through */\n        case 2: pt[1] = in[1]; /* fall through */\n        case 1: pt[0] = in[0]; /* fall through */\n    }\n    b |= _le64toh(t);\n\n    v3 ^= b;\n    DOUBLE_ROUND(v0,v1,v2,v3);\n    v0 ^= b;\n    v2 ^= 0xff;\n    DOUBLE_ROUND(v0,v1,v2,v3);\n    DOUBLE_ROUND(v0,v1,v2,v3);\n\n    /* modified */\n    t = (v0 ^ v1) ^ (v2 ^ v3);\n    return t;\n}\n#endif\n\nuint64_t\n_Py_KeyedHash(uint64_t key, const void *src, Py_ssize_t src_sz)\n{\n    return siphash13(key, 0, src, src_sz);\n}\n\n\n#if Py_HASH_ALGORITHM == Py_HASH_SIPHASH13\nstatic Py_hash_t\npysiphash(const void *src, Py_ssize_t src_sz) {\n    return (Py_hash_t)siphash13(\n        _le64toh(_Py_HashSecret.siphash.k0), _le64toh(_Py_HashSecret.siphash.k1),\n        src, src_sz);\n}\n\nstatic PyHash_FuncDef PyHash_Func = {pysiphash, \"siphash13\", 64, 128};\n#endif\n\n#if Py_HASH_ALGORITHM == Py_HASH_SIPHASH24\nstatic Py_hash_t\npysiphash(const void *src, Py_ssize_t src_sz) {\n    return (Py_hash_t)siphash24(\n        _le64toh(_Py_HashSecret.siphash.k0), _le64toh(_Py_HashSecret.siphash.k1),\n        src, src_sz);\n}\n\nstatic PyHash_FuncDef PyHash_Func = {pysiphash, \"siphash24\", 64, 128};\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "PyLifeCycle.c",
    "content": "/* Python interpreter top-level routines, including init/exit */\n\n#include \"Python.h\"\n\n#include \"pycore_ceval.h\"         // _PyEval_FiniGIL()\n#include \"pycore_context.h\"       // _PyContext_Init()\n#include \"pycore_exceptions.h\"    // _PyExc_InitTypes()\n#include \"pycore_dict.h\"          // _PyDict_Fini()\n#include \"pycore_fileutils.h\"     // _Py_ResetForceASCII()\n#include \"pycore_floatobject.h\"   // _PyFloat_InitTypes()\n#include \"pycore_genobject.h\"     // _PyAsyncGen_Fini()\n#include \"pycore_global_objects_fini_generated.h\"  // \"_PyStaticObjects_CheckRefcnt()\n#include \"pycore_import.h\"        // _PyImport_BootstrapImp()\n#include \"pycore_initconfig.h\"    // _PyStatus_OK()\n#include \"pycore_list.h\"          // _PyList_Fini()\n#include \"pycore_long.h\"          // _PyLong_InitTypes()\n#include \"pycore_object.h\"        // _PyDebug_PrintTotalRefs()\n#include \"pycore_pathconfig.h\"    // _PyConfig_WritePathConfig()\n#include \"pycore_pyerrors.h\"      // _PyErr_Occurred()\n#include \"pycore_pylifecycle.h\"   // _PyErr_Print()\n#include \"pycore_pymem.h\"         // _PyObject_DebugMallocStats()\n#include \"pycore_pystate.h\"       // _PyThreadState_GET()\n#include \"pycore_runtime.h\"       // _Py_ID()\n#include \"pycore_runtime_init.h\"  // _PyRuntimeState_INIT\n#include \"pycore_sliceobject.h\"   // _PySlice_Fini()\n#include \"pycore_sysmodule.h\"     // _PySys_ClearAuditHooks()\n#include \"pycore_traceback.h\"     // _Py_DumpTracebackThreads()\n#include \"pycore_typeobject.h\"    // _PyTypes_InitTypes()\n#include \"pycore_typevarobject.h\" // _Py_clear_generic_types()\n#include \"pycore_unicodeobject.h\" // _PyUnicode_InitTypes()\n#include \"opcode.h\"\n\n#include <locale.h>               // setlocale()\n#include <stdlib.h>               // getenv()\n\n#if defined(__APPLE__)\n#include <mach-o/loader.h>\n#endif\n\n#ifdef HAVE_SIGNAL_H\n#  include <signal.h>             // SIG_IGN\n#endif\n\n#ifdef HAVE_LANGINFO_H\n#  include <langinfo.h>           // nl_langinfo(CODESET)\n#endif\n\n#ifdef HAVE_FCNTL_H\n#  include <fcntl.h>              // F_GETFD\n#endif\n\n#ifdef MS_WINDOWS\n#  undef BYTE\n#endif\n\n#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n/* Forward declarations */\nstatic PyStatus add_main_module(PyInterpreterState *interp);\nstatic PyStatus init_import_site(void);\nstatic PyStatus init_set_builtins_open(void);\nstatic PyStatus init_sys_streams(PyThreadState *tstate);\nstatic void wait_for_thread_shutdown(PyThreadState *tstate);\nstatic void call_ll_exitfuncs(_PyRuntimeState *runtime);\n\n/* The following places the `_PyRuntime` structure in a location that can be\n * found without any external information. This is meant to ease access to the\n * interpreter state for various runtime debugging tools, but is *not* an\n * officially supported feature */\n\n/* Suppress deprecation warning for PyBytesObject.ob_shash */\n_Py_COMP_DIAG_PUSH\n_Py_COMP_DIAG_IGNORE_DEPR_DECLS\n\n#if defined(MS_WINDOWS)\n\n#pragma section(\"PyRuntime\", read, write)\n__declspec(allocate(\"PyRuntime\"))\n\n#elif defined(__APPLE__)\n\n__attribute__((\n    section(SEG_DATA \",PyRuntime\")\n))\n\n#endif\n\n_PyRuntimeState _PyRuntime\n#if defined(__linux__) && (defined(__GNUC__) || defined(__clang__))\n__attribute__ ((section (\".PyRuntime\")))\n#endif\n= _PyRuntimeState_INIT(_PyRuntime);\n_Py_COMP_DIAG_POP\n\nstatic int runtime_initialized = 0;\n\nPyStatus\n_PyRuntime_Initialize(void)\n{\n    /* XXX We only initialize once in the process, which aligns with\n       the static initialization of the former globals now found in\n       _PyRuntime.  However, _PyRuntime *should* be initialized with\n       every Py_Initialize() call, but doing so breaks the runtime.\n       This is because the runtime state is not properly finalized\n       currently. */\n    if (runtime_initialized) {\n        return _PyStatus_OK();\n    }\n    runtime_initialized = 1;\n\n    return _PyRuntimeState_Init(&_PyRuntime);\n}\n\nvoid\n_PyRuntime_Finalize(void)\n{\n    _PyRuntimeState_Fini(&_PyRuntime);\n    runtime_initialized = 0;\n}\n\nint\n_Py_IsFinalizing(void)\n{\n    return _PyRuntimeState_GetFinalizing(&_PyRuntime) != NULL;\n}\n\n/* Hack to force loading of object files */\nint (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) = \\\n    PyOS_mystrnicmp; /* Python/pystrcmp.o */\n\n\n/* APIs to access the initialization flags\n *\n * Can be called prior to Py_Initialize.\n */\n\nint\n_Py_IsCoreInitialized(void)\n{\n    return _PyRuntime.core_initialized;\n}\n\nint\nPy_IsInitialized(void)\n{\n    return _PyRuntime.initialized;\n}\n\n\n/* Helper functions to better handle the legacy C locale\n *\n * The legacy C locale assumes ASCII as the default text encoding, which\n * causes problems not only for the CPython runtime, but also other\n * components like GNU readline.\n *\n * Accordingly, when the CLI detects it, it attempts to coerce it to a\n * more capable UTF-8 based alternative as follows:\n *\n *     if (_Py_LegacyLocaleDetected()) {\n *         _Py_CoerceLegacyLocale();\n *     }\n *\n * See the documentation of the PYTHONCOERCECLOCALE setting for more details.\n *\n * Locale coercion also impacts the default error handler for the standard\n * streams: while the usual default is \"strict\", the default for the legacy\n * C locale and for any of the coercion target locales is \"surrogateescape\".\n */\n\nint\n_Py_LegacyLocaleDetected(int warn)\n{\n#ifndef MS_WINDOWS\n    if (!warn) {\n        const char *locale_override = getenv(\"LC_ALL\");\n        if (locale_override != NULL && *locale_override != '\\0') {\n            /* Don't coerce C locale if the LC_ALL environment variable\n               is set */\n            return 0;\n        }\n    }\n\n    /* On non-Windows systems, the C locale is considered a legacy locale */\n    /* XXX (ncoghlan): some platforms (notably Mac OS X) don't appear to treat\n     *                 the POSIX locale as a simple alias for the C locale, so\n     *                 we may also want to check for that explicitly.\n     */\n    const char *ctype_loc = setlocale(LC_CTYPE, NULL);\n    return ctype_loc != NULL && strcmp(ctype_loc, \"C\") == 0;\n#else\n    /* Windows uses code pages instead of locales, so no locale is legacy */\n    return 0;\n#endif\n}\n\n#ifndef MS_WINDOWS\nstatic const char *_C_LOCALE_WARNING =\n    \"Python runtime initialized with LC_CTYPE=C (a locale with default ASCII \"\n    \"encoding), which may cause Unicode compatibility problems. Using C.UTF-8, \"\n    \"C.utf8, or UTF-8 (if available) as alternative Unicode-compatible \"\n    \"locales is recommended.\\n\";\n\nstatic void\nemit_stderr_warning_for_legacy_locale(_PyRuntimeState *runtime)\n{\n    const PyPreConfig *preconfig = &runtime->preconfig;\n    if (preconfig->coerce_c_locale_warn && _Py_LegacyLocaleDetected(1)) {\n        PySys_FormatStderr(\"%s\", _C_LOCALE_WARNING);\n    }\n}\n#endif   /* !defined(MS_WINDOWS) */\n\ntypedef struct _CandidateLocale {\n    const char *locale_name; /* The locale to try as a coercion target */\n} _LocaleCoercionTarget;\n\nstatic _LocaleCoercionTarget _TARGET_LOCALES[] = {\n    {\"C.UTF-8\"},\n    {\"C.utf8\"},\n    {\"UTF-8\"},\n    {NULL}\n};\n\n\nint\n_Py_IsLocaleCoercionTarget(const char *ctype_loc)\n{\n    const _LocaleCoercionTarget *target = NULL;\n    for (target = _TARGET_LOCALES; target->locale_name; target++) {\n        if (strcmp(ctype_loc, target->locale_name) == 0) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\n\n#ifdef PY_COERCE_C_LOCALE\nstatic const char C_LOCALE_COERCION_WARNING[] =\n    \"Python detected LC_CTYPE=C: LC_CTYPE coerced to %.20s (set another locale \"\n    \"or PYTHONCOERCECLOCALE=0 to disable this locale coercion behavior).\\n\";\n\nstatic int\n_coerce_default_locale_settings(int warn, const _LocaleCoercionTarget *target)\n{\n    const char *newloc = target->locale_name;\n\n    /* Reset locale back to currently configured defaults */\n    _Py_SetLocaleFromEnv(LC_ALL);\n\n    /* Set the relevant locale environment variable */\n    if (setenv(\"LC_CTYPE\", newloc, 1)) {\n        fprintf(stderr,\n                \"Error setting LC_CTYPE, skipping C locale coercion\\n\");\n        return 0;\n    }\n    if (warn) {\n        fprintf(stderr, C_LOCALE_COERCION_WARNING, newloc);\n    }\n\n    /* Reconfigure with the overridden environment variables */\n    _Py_SetLocaleFromEnv(LC_ALL);\n    return 1;\n}\n#endif\n\nint\n_Py_CoerceLegacyLocale(int warn)\n{\n    int coerced = 0;\n#ifdef PY_COERCE_C_LOCALE\n    char *oldloc = NULL;\n\n    oldloc = _PyMem_RawStrdup(setlocale(LC_CTYPE, NULL));\n    if (oldloc == NULL) {\n        return coerced;\n    }\n\n    const char *locale_override = getenv(\"LC_ALL\");\n    if (locale_override == NULL || *locale_override == '\\0') {\n        /* LC_ALL is also not set (or is set to an empty string) */\n        const _LocaleCoercionTarget *target = NULL;\n        for (target = _TARGET_LOCALES; target->locale_name; target++) {\n            const char *new_locale = setlocale(LC_CTYPE,\n                                               target->locale_name);\n            if (new_locale != NULL) {\n#if !defined(_Py_FORCE_UTF8_LOCALE) && defined(HAVE_LANGINFO_H) && defined(CODESET)\n                /* Also ensure that nl_langinfo works in this locale */\n                char *codeset = nl_langinfo(CODESET);\n                if (!codeset || *codeset == '\\0') {\n                    /* CODESET is not set or empty, so skip coercion */\n                    new_locale = NULL;\n                    _Py_SetLocaleFromEnv(LC_CTYPE);\n                    continue;\n                }\n#endif\n                /* Successfully configured locale, so make it the default */\n                coerced = _coerce_default_locale_settings(warn, target);\n                goto done;\n            }\n        }\n    }\n    /* No C locale warning here, as Py_Initialize will emit one later */\n\n    setlocale(LC_CTYPE, oldloc);\n\ndone:\n    PyMem_RawFree(oldloc);\n#endif\n    return coerced;\n}\n\n/* _Py_SetLocaleFromEnv() is a wrapper around setlocale(category, \"\") to\n * isolate the idiosyncrasies of different libc implementations. It reads the\n * appropriate environment variable and uses its value to select the locale for\n * 'category'. */\nchar *\n_Py_SetLocaleFromEnv(int category)\n{\n    char *res;\n#ifdef __ANDROID__\n    const char *locale;\n    const char **pvar;\n#ifdef PY_COERCE_C_LOCALE\n    const char *coerce_c_locale;\n#endif\n    const char *utf8_locale = \"C.UTF-8\";\n    const char *env_var_set[] = {\n        \"LC_ALL\",\n        \"LC_CTYPE\",\n        \"LANG\",\n        NULL,\n    };\n\n    /* Android setlocale(category, \"\") doesn't check the environment variables\n     * and incorrectly sets the \"C\" locale at API 24 and older APIs. We only\n     * check the environment variables listed in env_var_set. */\n    for (pvar=env_var_set; *pvar; pvar++) {\n        locale = getenv(*pvar);\n        if (locale != NULL && *locale != '\\0') {\n            if (strcmp(locale, utf8_locale) == 0 ||\n                    strcmp(locale, \"en_US.UTF-8\") == 0) {\n                return setlocale(category, utf8_locale);\n            }\n            return setlocale(category, \"C\");\n        }\n    }\n\n    /* Android uses UTF-8, so explicitly set the locale to C.UTF-8 if none of\n     * LC_ALL, LC_CTYPE, or LANG is set to a non-empty string.\n     * Quote from POSIX section \"8.2 Internationalization Variables\":\n     * \"4. If the LANG environment variable is not set or is set to the empty\n     * string, the implementation-defined default locale shall be used.\" */\n\n#ifdef PY_COERCE_C_LOCALE\n    coerce_c_locale = getenv(\"PYTHONCOERCECLOCALE\");\n    if (coerce_c_locale == NULL || strcmp(coerce_c_locale, \"0\") != 0) {\n        /* Some other ported code may check the environment variables (e.g. in\n         * extension modules), so we make sure that they match the locale\n         * configuration */\n        if (setenv(\"LC_CTYPE\", utf8_locale, 1)) {\n            fprintf(stderr, \"Warning: failed setting the LC_CTYPE \"\n                            \"environment variable to %s\\n\", utf8_locale);\n        }\n    }\n#endif\n    res = setlocale(category, utf8_locale);\n#else /* !defined(__ANDROID__) */\n    res = setlocale(category, \"\");\n#endif\n    _Py_ResetForceASCII();\n    return res;\n}\n\n\nstatic int\ninterpreter_update_config(PyThreadState *tstate, int only_update_path_config)\n{\n    const PyConfig *config = &tstate->interp->config;\n\n    if (!only_update_path_config) {\n        PyStatus status = _PyConfig_Write(config, tstate->interp->runtime);\n        if (_PyStatus_EXCEPTION(status)) {\n            _PyErr_SetFromPyStatus(status);\n            return -1;\n        }\n    }\n\n    if (_Py_IsMainInterpreter(tstate->interp)) {\n        PyStatus status = _PyPathConfig_UpdateGlobal(config);\n        if (_PyStatus_EXCEPTION(status)) {\n            _PyErr_SetFromPyStatus(status);\n            return -1;\n        }\n    }\n\n    tstate->interp->long_state.max_str_digits = config->int_max_str_digits;\n\n    // Update the sys module for the new configuration\n    if (_PySys_UpdateConfig(tstate) < 0) {\n        return -1;\n    }\n    return 0;\n}\n\n\nint\n_PyInterpreterState_SetConfig(const PyConfig *src_config)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    int res = -1;\n\n    PyConfig config;\n    PyConfig_InitPythonConfig(&config);\n    PyStatus status = _PyConfig_Copy(&config, src_config);\n    if (_PyStatus_EXCEPTION(status)) {\n        _PyErr_SetFromPyStatus(status);\n        goto done;\n    }\n\n    status = _PyConfig_Read(&config, 1);\n    if (_PyStatus_EXCEPTION(status)) {\n        _PyErr_SetFromPyStatus(status);\n        goto done;\n    }\n\n    status = _PyConfig_Copy(&tstate->interp->config, &config);\n    if (_PyStatus_EXCEPTION(status)) {\n        _PyErr_SetFromPyStatus(status);\n        goto done;\n    }\n\n    res = interpreter_update_config(tstate, 0);\n\ndone:\n    PyConfig_Clear(&config);\n    return res;\n}\n\n\n/* Global initializations.  Can be undone by Py_Finalize().  Don't\n   call this twice without an intervening Py_Finalize() call.\n\n   Every call to Py_InitializeFromConfig, Py_Initialize or Py_InitializeEx\n   must have a corresponding call to Py_Finalize.\n\n   Locking: you must hold the interpreter lock while calling these APIs.\n   (If the lock has not yet been initialized, that's equivalent to\n   having the lock, but you cannot use multiple threads.)\n\n*/\n\nstatic PyStatus\npyinit_core_reconfigure(_PyRuntimeState *runtime,\n                        PyThreadState **tstate_p,\n                        const PyConfig *config)\n{\n    PyStatus status;\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (!tstate) {\n        return _PyStatus_ERR(\"failed to read thread state\");\n    }\n    *tstate_p = tstate;\n\n    PyInterpreterState *interp = tstate->interp;\n    if (interp == NULL) {\n        return _PyStatus_ERR(\"can't make main interpreter\");\n    }\n\n    status = _PyConfig_Write(config, runtime);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyConfig_Copy(&interp->config, config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    config = _PyInterpreterState_GetConfig(interp);\n\n    if (config->_install_importlib) {\n        status = _PyPathConfig_UpdateGlobal(config);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\npycore_init_runtime(_PyRuntimeState *runtime,\n                    const PyConfig *config)\n{\n    if (runtime->initialized) {\n        return _PyStatus_ERR(\"main interpreter already initialized\");\n    }\n\n    PyStatus status = _PyConfig_Write(config, runtime);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    /* Py_Finalize leaves _Py_Finalizing set in order to help daemon\n     * threads behave a little more gracefully at interpreter shutdown.\n     * We clobber it here so the new interpreter can start with a clean\n     * slate.\n     *\n     * However, this may still lead to misbehaviour if there are daemon\n     * threads still hanging around from a previous Py_Initialize/Finalize\n     * pair :(\n     */\n    _PyRuntimeState_SetFinalizing(runtime, NULL);\n\n    _Py_InitVersion();\n\n    status = _Py_HashRandomization_Init(config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyTime_Init();\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyImport_Init();\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyInterpreterState_Enable(runtime);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\ninit_interp_settings(PyInterpreterState *interp,\n                     const PyInterpreterConfig *config)\n{\n    assert(interp->feature_flags == 0);\n\n    if (config->use_main_obmalloc) {\n        interp->feature_flags |= Py_RTFLAGS_USE_MAIN_OBMALLOC;\n    }\n    else if (!config->check_multi_interp_extensions) {\n        /* The reason: PyModuleDef.m_base.m_copy leaks objects between\n           interpreters. */\n        return _PyStatus_ERR(\"per-interpreter obmalloc does not support \"\n                             \"single-phase init extension modules\");\n    }\n\n    if (config->allow_fork) {\n        interp->feature_flags |= Py_RTFLAGS_FORK;\n    }\n    if (config->allow_exec) {\n        interp->feature_flags |= Py_RTFLAGS_EXEC;\n    }\n    // Note that fork+exec is always allowed.\n\n    if (config->allow_threads) {\n        interp->feature_flags |= Py_RTFLAGS_THREADS;\n    }\n    if (config->allow_daemon_threads) {\n        interp->feature_flags |= Py_RTFLAGS_DAEMON_THREADS;\n    }\n\n    if (config->check_multi_interp_extensions) {\n        interp->feature_flags |= Py_RTFLAGS_MULTI_INTERP_EXTENSIONS;\n    }\n\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\ninit_interp_create_gil(PyThreadState *tstate, int own_gil)\n{\n    PyStatus status;\n\n    /* finalize_interp_delete() comment explains why _PyEval_FiniGIL() is\n       only called here. */\n    // XXX This is broken with a per-interpreter GIL.\n    _PyEval_FiniGIL(tstate->interp);\n\n    /* Auto-thread-state API */\n    status = _PyGILState_SetTstate(tstate);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    /* Create the GIL and take it */\n    status = _PyEval_InitGIL(tstate, own_gil);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\npycore_create_interpreter(_PyRuntimeState *runtime,\n                          const PyConfig *src_config,\n                          PyThreadState **tstate_p)\n{\n    PyStatus status;\n    PyInterpreterState *interp = PyInterpreterState_New();\n    if (interp == NULL) {\n        return _PyStatus_ERR(\"can't make main interpreter\");\n    }\n    assert(_Py_IsMainInterpreter(interp));\n\n    status = _PyConfig_Copy(&interp->config, src_config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    /* Auto-thread-state API */\n    status = _PyGILState_Init(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT;\n    // The main interpreter always has its own GIL.\n    config.own_gil = 1;\n    status = init_interp_settings(interp, &config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    PyThreadState *tstate = _PyThreadState_New(interp);\n    if (tstate == NULL) {\n        return _PyStatus_ERR(\"can't make first thread\");\n    }\n    _PyThreadState_Bind(tstate);\n    // XXX For now we do this before the GIL is created.\n    (void) _PyThreadState_SwapNoGIL(tstate);\n\n    status = init_interp_create_gil(tstate, config.own_gil);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    *tstate_p = tstate;\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\npycore_init_global_objects(PyInterpreterState *interp)\n{\n    PyStatus status;\n\n    _PyFloat_InitState(interp);\n\n    status = _PyUnicode_InitGlobalObjects(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    _PyUnicode_InitState(interp);\n\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\npycore_init_types(PyInterpreterState *interp)\n{\n    PyStatus status;\n\n    status = _PyTypes_InitTypes(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyLong_InitTypes(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyUnicode_InitTypes(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyFloat_InitTypes(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    if (_PyExc_InitTypes(interp) < 0) {\n        return _PyStatus_ERR(\"failed to initialize an exception type\");\n    }\n\n    status = _PyExc_InitGlobalObjects(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyExc_InitState(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyErr_InitTypes(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyContext_Init(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    return _PyStatus_OK();\n}\n\nstatic const uint8_t INTERPRETER_TRAMPOLINE_INSTRUCTIONS[] = {\n    /* Put a NOP at the start, so that the IP points into\n    * the code, rather than before it */\n    NOP, 0,\n    INTERPRETER_EXIT, 0,\n    /* RESUME at end makes sure that the frame appears incomplete */\n    RESUME, 0\n};\n\nstatic const _PyShimCodeDef INTERPRETER_TRAMPOLINE_CODEDEF = {\n    INTERPRETER_TRAMPOLINE_INSTRUCTIONS,\n    sizeof(INTERPRETER_TRAMPOLINE_INSTRUCTIONS),\n    1,\n    \"<interpreter trampoline>\"\n};\n\nstatic PyStatus\npycore_init_builtins(PyThreadState *tstate)\n{\n    PyInterpreterState *interp = tstate->interp;\n\n    PyObject *bimod = _PyBuiltin_Init(interp);\n    if (bimod == NULL) {\n        goto error;\n    }\n\n    PyObject *modules = _PyImport_GetModules(interp);\n    if (_PyImport_FixupBuiltin(bimod, \"builtins\", modules) < 0) {\n        goto error;\n    }\n\n    PyObject *builtins_dict = PyModule_GetDict(bimod);\n    if (builtins_dict == NULL) {\n        goto error;\n    }\n    interp->builtins = Py_NewRef(builtins_dict);\n\n    PyObject *isinstance = PyDict_GetItem(builtins_dict, &_Py_ID(isinstance));\n    assert(isinstance);\n    interp->callable_cache.isinstance = isinstance;\n    PyObject *len = PyDict_GetItem(builtins_dict, &_Py_ID(len));\n    assert(len);\n    interp->callable_cache.len = len;\n    PyObject *list_append = _PyType_Lookup(&PyList_Type, &_Py_ID(append));\n    assert(list_append);\n    interp->callable_cache.list_append = list_append;\n    PyObject *object__getattribute__ = _PyType_Lookup(&PyBaseObject_Type, &_Py_ID(__getattribute__));\n    assert(object__getattribute__);\n    interp->callable_cache.object__getattribute__ = object__getattribute__;\n    interp->interpreter_trampoline = _Py_MakeShimCode(&INTERPRETER_TRAMPOLINE_CODEDEF);\n    if (interp->interpreter_trampoline == NULL) {\n        return _PyStatus_ERR(\"failed to create interpreter trampoline.\");\n    }\n    if (_PyBuiltins_AddExceptions(bimod) < 0) {\n        return _PyStatus_ERR(\"failed to add exceptions to builtins\");\n    }\n\n    interp->builtins_copy = PyDict_Copy(interp->builtins);\n    if (interp->builtins_copy == NULL) {\n        goto error;\n    }\n    Py_DECREF(bimod);\n\n    if (_PyImport_InitDefaultImportFunc(interp) < 0) {\n        goto error;\n    }\n\n    assert(!_PyErr_Occurred(tstate));\n    return _PyStatus_OK();\n\nerror:\n    Py_XDECREF(bimod);\n    return _PyStatus_ERR(\"can't initialize builtins module\");\n}\n\n\nstatic PyStatus\npycore_interp_init(PyThreadState *tstate)\n{\n    PyInterpreterState *interp = tstate->interp;\n    PyStatus status;\n    PyObject *sysmod = NULL;\n\n    // Create singletons before the first PyType_Ready() call, since\n    // PyType_Ready() uses singletons like the Unicode empty string (tp_doc)\n    // and the empty tuple singletons (tp_bases).\n    status = pycore_init_global_objects(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    // The GC must be initialized before the first GC collection.\n    status = _PyGC_Init(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    // Intern strings in deep-frozen modules first so that others\n    // can use it instead of creating a heap allocated string.\n    if (_Py_Deepfreeze_Init() < 0) {\n        return _PyStatus_ERR(\"failed to initialize deep-frozen modules\");\n    }\n\n    status = pycore_init_types(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\n    if (_PyWarnings_InitState(interp) < 0) {\n        return _PyStatus_ERR(\"can't initialize warnings\");\n    }\n\n    status = _PyAtExit_Init(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PySys_Create(tstate, &sysmod);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\n    status = pycore_init_builtins(tstate);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\n    const PyConfig *config = _PyInterpreterState_GetConfig(interp);\n\n    status = _PyImport_InitCore(tstate, sysmod, config->_install_importlib);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\ndone:\n    /* sys.modules['sys'] contains a strong reference to the module */\n    Py_XDECREF(sysmod);\n    return status;\n}\n\n\nstatic PyStatus\npyinit_config(_PyRuntimeState *runtime,\n              PyThreadState **tstate_p,\n              const PyConfig *config)\n{\n    PyStatus status = pycore_init_runtime(runtime, config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    PyThreadState *tstate;\n    status = pycore_create_interpreter(runtime, config, &tstate);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    *tstate_p = tstate;\n\n    status = pycore_interp_init(tstate);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    /* Only when we get here is the runtime core fully initialized */\n    runtime->core_initialized = 1;\n    return _PyStatus_OK();\n}\n\n\nPyStatus\n_Py_PreInitializeFromPyArgv(const PyPreConfig *src_config, const _PyArgv *args)\n{\n    PyStatus status;\n\n    if (src_config == NULL) {\n        return _PyStatus_ERR(\"preinitialization config is NULL\");\n    }\n\n    status = _PyRuntime_Initialize();\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    _PyRuntimeState *runtime = &_PyRuntime;\n\n    if (runtime->preinitialized) {\n        /* If it's already configured: ignored the new configuration */\n        return _PyStatus_OK();\n    }\n\n    /* Note: preinitialized remains 1 on error, it is only set to 0\n       at exit on success. */\n    runtime->preinitializing = 1;\n\n    PyPreConfig config;\n\n    status = _PyPreConfig_InitFromPreConfig(&config, src_config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyPreConfig_Read(&config, args);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PyPreConfig_Write(&config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    runtime->preinitializing = 0;\n    runtime->preinitialized = 1;\n    return _PyStatus_OK();\n}\n\n\nPyStatus\nPy_PreInitializeFromBytesArgs(const PyPreConfig *src_config, Py_ssize_t argc, char **argv)\n{\n    _PyArgv args = {.use_bytes_argv = 1, .argc = argc, .bytes_argv = argv};\n    return _Py_PreInitializeFromPyArgv(src_config, &args);\n}\n\n\nPyStatus\nPy_PreInitializeFromArgs(const PyPreConfig *src_config, Py_ssize_t argc, wchar_t **argv)\n{\n    _PyArgv args = {.use_bytes_argv = 0, .argc = argc, .wchar_argv = argv};\n    return _Py_PreInitializeFromPyArgv(src_config, &args);\n}\n\n\nPyStatus\nPy_PreInitialize(const PyPreConfig *src_config)\n{\n    return _Py_PreInitializeFromPyArgv(src_config, NULL);\n}\n\n\nPyStatus\n_Py_PreInitializeFromConfig(const PyConfig *config,\n                            const _PyArgv *args)\n{\n    assert(config != NULL);\n\n    PyStatus status = _PyRuntime_Initialize();\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    _PyRuntimeState *runtime = &_PyRuntime;\n\n    if (runtime->preinitialized) {\n        /* Already initialized: do nothing */\n        return _PyStatus_OK();\n    }\n\n    PyPreConfig preconfig;\n\n    _PyPreConfig_InitFromConfig(&preconfig, config);\n\n    if (!config->parse_argv) {\n        return Py_PreInitialize(&preconfig);\n    }\n    else if (args == NULL) {\n        _PyArgv config_args = {\n            .use_bytes_argv = 0,\n            .argc = config->argv.length,\n            .wchar_argv = config->argv.items};\n        return _Py_PreInitializeFromPyArgv(&preconfig, &config_args);\n    }\n    else {\n        return _Py_PreInitializeFromPyArgv(&preconfig, args);\n    }\n}\n\n\n/* Begin interpreter initialization\n *\n * On return, the first thread and interpreter state have been created,\n * but the compiler, signal handling, multithreading and\n * multiple interpreter support, and codec infrastructure are not yet\n * available.\n *\n * The import system will support builtin and frozen modules only.\n * The only supported io is writing to sys.stderr\n *\n * If any operation invoked by this function fails, a fatal error is\n * issued and the function does not return.\n *\n * Any code invoked from this function should *not* assume it has access\n * to the Python C API (unless the API is explicitly listed as being\n * safe to call without calling Py_Initialize first)\n */\nstatic PyStatus\npyinit_core(_PyRuntimeState *runtime,\n            const PyConfig *src_config,\n            PyThreadState **tstate_p)\n{\n    PyStatus status;\n\n    status = _Py_PreInitializeFromConfig(src_config, NULL);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    PyConfig config;\n    PyConfig_InitPythonConfig(&config);\n\n    status = _PyConfig_Copy(&config, src_config);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\n    // Read the configuration, but don't compute the path configuration\n    // (it is computed in the main init).\n    status = _PyConfig_Read(&config, 0);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\n    if (!runtime->core_initialized) {\n        status = pyinit_config(runtime, tstate_p, &config);\n    }\n    else {\n        status = pyinit_core_reconfigure(runtime, tstate_p, &config);\n    }\n    if (_PyStatus_EXCEPTION(status)) {\n        goto done;\n    }\n\ndone:\n    PyConfig_Clear(&config);\n    return status;\n}\n\n\n/* Py_Initialize() has already been called: update the main interpreter\n   configuration. Example of bpo-34008: Py_Main() called after\n   Py_Initialize(). */\nstatic PyStatus\npyinit_main_reconfigure(PyThreadState *tstate)\n{\n    if (interpreter_update_config(tstate, 0) < 0) {\n        return _PyStatus_ERR(\"fail to reconfigure Python\");\n    }\n    return _PyStatus_OK();\n}\n\n\nstatic PyStatus\ninit_interp_main(PyThreadState *tstate)\n{\n    assert(!_PyErr_Occurred(tstate));\n\n    PyStatus status;\n    int is_main_interp = _Py_IsMainInterpreter(tstate->interp);\n    PyInterpreterState *interp = tstate->interp;\n    const PyConfig *config = _PyInterpreterState_GetConfig(interp);\n\n    if (!config->_install_importlib) {\n        /* Special mode for freeze_importlib: run with no import system\n         *\n         * This means anything which needs support from extension modules\n         * or pure Python code in the standard library won't work.\n         */\n        if (is_main_interp) {\n            interp->runtime->initialized = 1;\n        }\n        return _PyStatus_OK();\n    }\n\n    // Initialize the import-related configuration.\n    status = _PyConfig_InitImportConfig(&interp->config);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    if (interpreter_update_config(tstate, 1) < 0) {\n        return _PyStatus_ERR(\"failed to update the Python config\");\n    }\n\n    status = _PyImport_InitExternal(tstate);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    if (is_main_interp) {\n        /* initialize the faulthandler module */\n        status = _PyFaulthandler_Init(config->faulthandler);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    status = _PyUnicode_InitEncodings(tstate);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    if (is_main_interp) {\n        if (_PySignal_Init(config->install_signal_handlers) < 0) {\n            return _PyStatus_ERR(\"can't initialize signals\");\n        }\n\n        if (config->tracemalloc) {\n           if (_PyTraceMalloc_Start(config->tracemalloc) < 0) {\n                return _PyStatus_ERR(\"can't start tracemalloc\");\n            }\n        }\n\n#ifdef PY_HAVE_PERF_TRAMPOLINE\n        if (config->perf_profiling) {\n            if (_PyPerfTrampoline_SetCallbacks(&_Py_perfmap_callbacks) < 0 ||\n                    _PyPerfTrampoline_Init(config->perf_profiling) < 0) {\n                return _PyStatus_ERR(\"can't initialize the perf trampoline\");\n            }\n        }\n#endif\n    }\n\n    status = init_sys_streams(tstate);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = init_set_builtins_open();\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = add_main_module(interp);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    if (is_main_interp) {\n        /* Initialize warnings. */\n        PyObject *warnoptions = PySys_GetObject(\"warnoptions\");\n        if (warnoptions != NULL && PyList_Size(warnoptions) > 0)\n        {\n            PyObject *warnings_module = PyImport_ImportModule(\"warnings\");\n            if (warnings_module == NULL) {\n                fprintf(stderr, \"'import warnings' failed; traceback:\\n\");\n                _PyErr_Print(tstate);\n            }\n            Py_XDECREF(warnings_module);\n        }\n\n        interp->runtime->initialized = 1;\n    }\n\n    if (config->site_import) {\n        status = init_import_site();\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    if (is_main_interp) {\n#ifndef MS_WINDOWS\n        emit_stderr_warning_for_legacy_locale(interp->runtime);\n#endif\n    }\n\n    assert(!_PyErr_Occurred(tstate));\n\n    return _PyStatus_OK();\n}\n\n\n/* Update interpreter state based on supplied configuration settings\n *\n * After calling this function, most of the restrictions on the interpreter\n * are lifted. The only remaining incomplete settings are those related\n * to the main module (sys.argv[0], __main__ metadata)\n *\n * Calling this when the interpreter is not initializing, is already\n * initialized or without a valid current thread state is a fatal error.\n * Other errors should be reported as normal Python exceptions with a\n * non-zero return code.\n */\nstatic PyStatus\npyinit_main(PyThreadState *tstate)\n{\n    PyInterpreterState *interp = tstate->interp;\n    if (!interp->runtime->core_initialized) {\n        return _PyStatus_ERR(\"runtime core not initialized\");\n    }\n\n    if (interp->runtime->initialized) {\n        return pyinit_main_reconfigure(tstate);\n    }\n\n    PyStatus status = init_interp_main(tstate);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    return _PyStatus_OK();\n}\n\n\nPyStatus\nPy_InitializeFromConfig(const PyConfig *config)\n{\n    if (config == NULL) {\n        return _PyStatus_ERR(\"initialization config is NULL\");\n    }\n\n    PyStatus status;\n\n    status = _PyRuntime_Initialize();\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    _PyRuntimeState *runtime = &_PyRuntime;\n\n    PyThreadState *tstate = NULL;\n    status = pyinit_core(runtime, config, &tstate);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    config = _PyInterpreterState_GetConfig(tstate->interp);\n\n    if (config->_init_main) {\n        status = pyinit_main(tstate);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    return _PyStatus_OK();\n}\n\n\nvoid\nPy_InitializeEx(int install_sigs)\n{\n    PyStatus status;\n\n    status = _PyRuntime_Initialize();\n    if (_PyStatus_EXCEPTION(status)) {\n        Py_ExitStatusException(status);\n    }\n    _PyRuntimeState *runtime = &_PyRuntime;\n\n    if (runtime->initialized) {\n        /* bpo-33932: Calling Py_Initialize() twice does nothing. */\n        return;\n    }\n\n    PyConfig config;\n    _PyConfig_InitCompatConfig(&config);\n\n    config.install_signal_handlers = install_sigs;\n\n    status = Py_InitializeFromConfig(&config);\n    PyConfig_Clear(&config);\n    if (_PyStatus_EXCEPTION(status)) {\n        Py_ExitStatusException(status);\n    }\n}\n\nvoid\nPy_Initialize(void)\n{\n    Py_InitializeEx(1);\n}\n\n\nPyStatus\n_Py_InitializeMain(void)\n{\n    PyStatus status = _PyRuntime_Initialize();\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    PyThreadState *tstate = _PyThreadState_GET();\n    return pyinit_main(tstate);\n}\n\n\nstatic void\nfinalize_modules_delete_special(PyThreadState *tstate, int verbose)\n{\n    // List of names to clear in sys\n    static const char * const sys_deletes[] = {\n        \"path\", \"argv\", \"ps1\", \"ps2\", \"last_exc\",\n        \"last_type\", \"last_value\", \"last_traceback\",\n        \"__interactivehook__\",\n        // path_hooks and path_importer_cache are cleared\n        // by _PyImport_FiniExternal().\n        // XXX Clear meta_path in _PyImport_FiniCore().\n        \"meta_path\",\n        NULL\n    };\n\n    static const char * const sys_files[] = {\n        \"stdin\", \"__stdin__\",\n        \"stdout\", \"__stdout__\",\n        \"stderr\", \"__stderr__\",\n        NULL\n    };\n\n    PyInterpreterState *interp = tstate->interp;\n    if (verbose) {\n        PySys_WriteStderr(\"# clear builtins._\\n\");\n    }\n    if (PyDict_SetItemString(interp->builtins, \"_\", Py_None) < 0) {\n        PyErr_WriteUnraisable(NULL);\n    }\n\n    const char * const *p;\n    for (p = sys_deletes; *p != NULL; p++) {\n        if (_PySys_ClearAttrString(interp, *p, verbose) < 0) {\n            PyErr_WriteUnraisable(NULL);\n        }\n    }\n    for (p = sys_files; *p != NULL; p+=2) {\n        const char *name = p[0];\n        const char *orig_name = p[1];\n        if (verbose) {\n            PySys_WriteStderr(\"# restore sys.%s\\n\", name);\n        }\n        PyObject *value = _PyDict_GetItemStringWithError(interp->sysdict,\n                                                         orig_name);\n        if (value == NULL) {\n            if (_PyErr_Occurred(tstate)) {\n                PyErr_WriteUnraisable(NULL);\n            }\n            value = Py_None;\n        }\n        if (PyDict_SetItemString(interp->sysdict, name, value) < 0) {\n            PyErr_WriteUnraisable(NULL);\n        }\n    }\n}\n\n\nstatic PyObject*\nfinalize_remove_modules(PyObject *modules, int verbose)\n{\n    PyObject *weaklist = PyList_New(0);\n    if (weaklist == NULL) {\n        PyErr_WriteUnraisable(NULL);\n    }\n\n#define STORE_MODULE_WEAKREF(name, mod) \\\n        if (weaklist != NULL) { \\\n            PyObject *wr = PyWeakref_NewRef(mod, NULL); \\\n            if (wr) { \\\n                PyObject *tup = PyTuple_Pack(2, name, wr); \\\n                if (!tup || PyList_Append(weaklist, tup) < 0) { \\\n                    PyErr_WriteUnraisable(NULL); \\\n                } \\\n                Py_XDECREF(tup); \\\n                Py_DECREF(wr); \\\n            } \\\n            else { \\\n                PyErr_WriteUnraisable(NULL); \\\n            } \\\n        }\n\n#define CLEAR_MODULE(name, mod) \\\n        if (PyModule_Check(mod)) { \\\n            if (verbose && PyUnicode_Check(name)) { \\\n                PySys_FormatStderr(\"# cleanup[2] removing %U\\n\", name); \\\n            } \\\n            STORE_MODULE_WEAKREF(name, mod); \\\n            if (PyObject_SetItem(modules, name, Py_None) < 0) { \\\n                PyErr_WriteUnraisable(NULL); \\\n            } \\\n        }\n\n    if (PyDict_CheckExact(modules)) {\n        Py_ssize_t pos = 0;\n        PyObject *key, *value;\n        while (PyDict_Next(modules, &pos, &key, &value)) {\n            CLEAR_MODULE(key, value);\n        }\n    }\n    else {\n        PyObject *iterator = PyObject_GetIter(modules);\n        if (iterator == NULL) {\n            PyErr_WriteUnraisable(NULL);\n        }\n        else {\n            PyObject *key;\n            while ((key = PyIter_Next(iterator))) {\n                PyObject *value = PyObject_GetItem(modules, key);\n                if (value == NULL) {\n                    PyErr_WriteUnraisable(NULL);\n                    continue;\n                }\n                CLEAR_MODULE(key, value);\n                Py_DECREF(value);\n                Py_DECREF(key);\n            }\n            if (PyErr_Occurred()) {\n                PyErr_WriteUnraisable(NULL);\n            }\n            Py_DECREF(iterator);\n        }\n    }\n#undef CLEAR_MODULE\n#undef STORE_MODULE_WEAKREF\n\n    return weaklist;\n}\n\n\nstatic void\nfinalize_clear_modules_dict(PyObject *modules)\n{\n    if (PyDict_CheckExact(modules)) {\n        PyDict_Clear(modules);\n    }\n    else {\n        if (PyObject_CallMethodNoArgs(modules, &_Py_ID(clear)) == NULL) {\n            PyErr_WriteUnraisable(NULL);\n        }\n    }\n}\n\n\nstatic void\nfinalize_restore_builtins(PyThreadState *tstate)\n{\n    PyInterpreterState *interp = tstate->interp;\n    PyObject *dict = PyDict_Copy(interp->builtins);\n    if (dict == NULL) {\n        PyErr_WriteUnraisable(NULL);\n    }\n    PyDict_Clear(interp->builtins);\n    if (PyDict_Update(interp->builtins, interp->builtins_copy)) {\n        PyErr_WriteUnraisable(NULL);\n    }\n    Py_XDECREF(dict);\n}\n\n\nstatic void\nfinalize_modules_clear_weaklist(PyInterpreterState *interp,\n                                PyObject *weaklist, int verbose)\n{\n    // First clear modules imported later\n    for (Py_ssize_t i = PyList_GET_SIZE(weaklist) - 1; i >= 0; i--) {\n        PyObject *tup = PyList_GET_ITEM(weaklist, i);\n        PyObject *name = PyTuple_GET_ITEM(tup, 0);\n        PyObject *mod = PyWeakref_GET_OBJECT(PyTuple_GET_ITEM(tup, 1));\n        if (mod == Py_None) {\n            continue;\n        }\n        assert(PyModule_Check(mod));\n        PyObject *dict = PyModule_GetDict(mod);\n        if (dict == interp->builtins || dict == interp->sysdict) {\n            continue;\n        }\n        Py_INCREF(mod);\n        if (verbose && PyUnicode_Check(name)) {\n            PySys_FormatStderr(\"# cleanup[3] wiping %U\\n\", name);\n        }\n        _PyModule_Clear(mod);\n        Py_DECREF(mod);\n    }\n}\n\n\nstatic void\nfinalize_clear_sys_builtins_dict(PyInterpreterState *interp, int verbose)\n{\n    // Clear sys dict\n    if (verbose) {\n        PySys_FormatStderr(\"# cleanup[3] wiping sys\\n\");\n    }\n    _PyModule_ClearDict(interp->sysdict);\n\n    // Clear builtins dict\n    if (verbose) {\n        PySys_FormatStderr(\"# cleanup[3] wiping builtins\\n\");\n    }\n    _PyModule_ClearDict(interp->builtins);\n}\n\n\n/* Clear modules, as good as we can */\n// XXX Move most of this to import.c.\nstatic void\nfinalize_modules(PyThreadState *tstate)\n{\n    PyInterpreterState *interp = tstate->interp;\n    PyObject *modules = _PyImport_GetModules(interp);\n    if (modules == NULL) {\n        // Already done\n        return;\n    }\n    int verbose = _PyInterpreterState_GetConfig(interp)->verbose;\n\n    // Delete some special builtins._ and sys attributes first.  These are\n    // common places where user values hide and people complain when their\n    // destructors fail.  Since the modules containing them are\n    // deleted *last* of all, they would come too late in the normal\n    // destruction order.  Sigh.\n    //\n    // XXX Perhaps these precautions are obsolete. Who knows?\n    finalize_modules_delete_special(tstate, verbose);\n\n    // Remove all modules from sys.modules, hoping that garbage collection\n    // can reclaim most of them: set all sys.modules values to None.\n    //\n    // We prepare a list which will receive (name, weakref) tuples of\n    // modules when they are removed from sys.modules.  The name is used\n    // for diagnosis messages (in verbose mode), while the weakref helps\n    // detect those modules which have been held alive.\n    PyObject *weaklist = finalize_remove_modules(modules, verbose);\n\n    // Clear the modules dict\n    finalize_clear_modules_dict(modules);\n\n    // Restore the original builtins dict, to ensure that any\n    // user data gets cleared.\n    finalize_restore_builtins(tstate);\n\n    // Collect garbage\n    _PyGC_CollectNoFail(tstate);\n\n    // Dump GC stats before it's too late, since it uses the warnings\n    // machinery.\n    _PyGC_DumpShutdownStats(interp);\n\n    if (weaklist != NULL) {\n        // Now, if there are any modules left alive, clear their globals to\n        // minimize potential leaks.  All C extension modules actually end\n        // up here, since they are kept alive in the interpreter state.\n        //\n        // The special treatment of \"builtins\" here is because even\n        // when it's not referenced as a module, its dictionary is\n        // referenced by almost every module's __builtins__.  Since\n        // deleting a module clears its dictionary (even if there are\n        // references left to it), we need to delete the \"builtins\"\n        // module last.  Likewise, we don't delete sys until the very\n        // end because it is implicitly referenced (e.g. by print).\n        //\n        // Since dict is ordered in CPython 3.6+, modules are saved in\n        // importing order.  First clear modules imported later.\n        finalize_modules_clear_weaklist(interp, weaklist, verbose);\n        Py_DECREF(weaklist);\n    }\n\n    // Clear sys and builtins modules dict\n    finalize_clear_sys_builtins_dict(interp, verbose);\n\n    // Clear module dict copies stored in the interpreter state:\n    // clear PyInterpreterState.modules_by_index and\n    // clear PyModuleDef.m_base.m_copy (of extensions not using the multi-phase\n    // initialization API)\n    _PyImport_ClearModulesByIndex(interp);\n\n    // Clear and delete the modules directory.  Actual modules will\n    // still be there only if imported during the execution of some\n    // destructor.\n    _PyImport_ClearModules(interp);\n\n    // Collect garbage once more\n    _PyGC_CollectNoFail(tstate);\n}\n\n\n/* Flush stdout and stderr */\n\nstatic int\nfile_is_closed(PyObject *fobj)\n{\n    int r;\n    PyObject *tmp = PyObject_GetAttrString(fobj, \"closed\");\n    if (tmp == NULL) {\n        PyErr_Clear();\n        return 0;\n    }\n    r = PyObject_IsTrue(tmp);\n    Py_DECREF(tmp);\n    if (r < 0)\n        PyErr_Clear();\n    return r > 0;\n}\n\n\nstatic int\nflush_std_files(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *fout = _PySys_GetAttr(tstate, &_Py_ID(stdout));\n    PyObject *ferr = _PySys_GetAttr(tstate, &_Py_ID(stderr));\n    PyObject *tmp;\n    int status = 0;\n\n    if (fout != NULL && fout != Py_None && !file_is_closed(fout)) {\n        tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(flush));\n        if (tmp == NULL) {\n            PyErr_WriteUnraisable(fout);\n            status = -1;\n        }\n        else\n            Py_DECREF(tmp);\n    }\n\n    if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) {\n        tmp = PyObject_CallMethodNoArgs(ferr, &_Py_ID(flush));\n        if (tmp == NULL) {\n            PyErr_Clear();\n            status = -1;\n        }\n        else\n            Py_DECREF(tmp);\n    }\n\n    return status;\n}\n\n/* Undo the effect of Py_Initialize().\n\n   Beware: if multiple interpreter and/or thread states exist, these\n   are not wiped out; only the current thread and interpreter state\n   are deleted.  But since everything else is deleted, those other\n   interpreter and thread states should no longer be used.\n\n   (XXX We should do better, e.g. wipe out all interpreters and\n   threads.)\n\n   Locking: as above.\n\n*/\n\n\nstatic void\nfinalize_interp_types(PyInterpreterState *interp)\n{\n    _PyUnicode_FiniTypes(interp);\n    _PySys_FiniTypes(interp);\n    _PyExc_Fini(interp);\n    _PyAsyncGen_Fini(interp);\n    _PyContext_Fini(interp);\n    _PyFloat_FiniType(interp);\n    _PyLong_FiniTypes(interp);\n    _PyThread_FiniType(interp);\n    // XXX fini collections module static types (_PyStaticType_Dealloc())\n    // XXX fini IO module static types (_PyStaticType_Dealloc())\n    _PyErr_FiniTypes(interp);\n    _PyTypes_FiniTypes(interp);\n\n    _PyTypes_Fini(interp);\n\n    // Call _PyUnicode_ClearInterned() before _PyDict_Fini() since it uses\n    // a dict internally.\n    _PyUnicode_ClearInterned(interp);\n\n    _PyDict_Fini(interp);\n    _PyList_Fini(interp);\n    _PyTuple_Fini(interp);\n\n    _PySlice_Fini(interp);\n\n    _PyUnicode_Fini(interp);\n    _PyFloat_Fini(interp);\n#ifdef Py_DEBUG\n    _PyStaticObjects_CheckRefcnt(interp);\n#endif\n}\n\n\nstatic void\nfinalize_interp_clear(PyThreadState *tstate)\n{\n    int is_main_interp = _Py_IsMainInterpreter(tstate->interp);\n\n    _PyExc_ClearExceptionGroupType(tstate->interp);\n    _Py_clear_generic_types(tstate->interp);\n\n    /* Clear interpreter state and all thread states */\n    _PyInterpreterState_Clear(tstate);\n\n    /* Clear all loghooks */\n    /* Both _PySys_Audit function and users still need PyObject, such as tuple.\n       Call _PySys_ClearAuditHooks when PyObject available. */\n    if (is_main_interp) {\n        _PySys_ClearAuditHooks(tstate);\n    }\n\n    if (is_main_interp) {\n        _Py_HashRandomization_Fini();\n        _PyArg_Fini();\n        _Py_ClearFileSystemEncoding();\n        _Py_Deepfreeze_Fini();\n        _PyPerfTrampoline_Fini();\n    }\n\n    finalize_interp_types(tstate->interp);\n}\n\n\nstatic void\nfinalize_interp_delete(PyInterpreterState *interp)\n{\n    /* Cleanup auto-thread-state */\n    _PyGILState_Fini(interp);\n\n    /* We can't call _PyEval_FiniGIL() here because destroying the GIL lock can\n       fail when it is being awaited by another running daemon thread (see\n       bpo-9901). Instead pycore_create_interpreter() destroys the previously\n       created GIL, which ensures that Py_Initialize / Py_FinalizeEx can be\n       called multiple times. */\n\n    PyInterpreterState_Delete(interp);\n}\n\n\nint\nPy_FinalizeEx(void)\n{\n    int status = 0;\n\n    _PyRuntimeState *runtime = &_PyRuntime;\n    if (!runtime->initialized) {\n        return status;\n    }\n\n    /* Get current thread state and interpreter pointer */\n    PyThreadState *tstate = _PyThreadState_GET();\n    // XXX assert(_Py_IsMainInterpreter(tstate->interp));\n    // XXX assert(_Py_IsMainThread());\n\n    // Block some operations.\n    tstate->interp->finalizing = 1;\n\n    // Wrap up existing \"threading\"-module-created, non-daemon threads.\n    wait_for_thread_shutdown(tstate);\n\n    // Make any remaining pending calls.\n    _Py_FinishPendingCalls(tstate);\n\n    /* The interpreter is still entirely intact at this point, and the\n     * exit funcs may be relying on that.  In particular, if some thread\n     * or exit func is still waiting to do an import, the import machinery\n     * expects Py_IsInitialized() to return true.  So don't say the\n     * runtime is uninitialized until after the exit funcs have run.\n     * Note that Threading.py uses an exit func to do a join on all the\n     * threads created thru it, so this also protects pending imports in\n     * the threads created via Threading.\n     */\n\n    _PyAtExit_Call(tstate->interp);\n    PyUnstable_PerfMapState_Fini();\n\n    /* Copy the core config, PyInterpreterState_Delete() free\n       the core config memory */\n#ifdef Py_REF_DEBUG\n    int show_ref_count = tstate->interp->config.show_ref_count;\n#endif\n#ifdef Py_TRACE_REFS\n    int dump_refs = tstate->interp->config.dump_refs;\n    wchar_t *dump_refs_file = tstate->interp->config.dump_refs_file;\n#endif\n#ifdef WITH_PYMALLOC\n    int malloc_stats = tstate->interp->config.malloc_stats;\n#endif\n\n    /* Remaining daemon threads will automatically exit\n       when they attempt to take the GIL (ex: PyEval_RestoreThread()). */\n    _PyInterpreterState_SetFinalizing(tstate->interp, tstate);\n    _PyRuntimeState_SetFinalizing(runtime, tstate);\n    runtime->initialized = 0;\n    runtime->core_initialized = 0;\n\n    // XXX Call something like _PyImport_Disable() here?\n\n    /* Destroy the state of all threads of the interpreter, except of the\n       current thread. In practice, only daemon threads should still be alive,\n       except if wait_for_thread_shutdown() has been cancelled by CTRL+C.\n       Clear frames of other threads to call objects destructors. Destructors\n       will be called in the current Python thread. Since\n       _PyRuntimeState_SetFinalizing() has been called, no other Python thread\n       can take the GIL at this point: if they try, they will exit\n       immediately. */\n    _PyThreadState_DeleteExcept(tstate);\n\n    /* At this point no Python code should be running at all.\n       The only thread state left should be the main thread of the main\n       interpreter (AKA tstate), in which this code is running right now.\n       There may be other OS threads running but none of them will have\n       thread states associated with them, nor will be able to create\n       new thread states.\n\n       Thus tstate is the only possible thread state from here on out.\n       It may still be used during finalization to run Python code as\n       needed or provide runtime state (e.g. sys.modules) but that will\n       happen sparingly.  Furthermore, the order of finalization aims\n       to not need a thread (or interpreter) state as soon as possible.\n     */\n    // XXX Make sure we are preventing the creating of any new thread states\n    // (or interpreters).\n\n    /* Flush sys.stdout and sys.stderr */\n    if (flush_std_files() < 0) {\n        status = -1;\n    }\n\n    /* Disable signal handling */\n    _PySignal_Fini();\n\n    /* Collect garbage.  This may call finalizers; it's nice to call these\n     * before all modules are destroyed.\n     * XXX If a __del__ or weakref callback is triggered here, and tries to\n     * XXX import a module, bad things can happen, because Python no\n     * XXX longer believes it's initialized.\n     * XXX     Fatal Python error: Interpreter not initialized (version mismatch?)\n     * XXX is easy to provoke that way.  I've also seen, e.g.,\n     * XXX     Exception exceptions.ImportError: 'No module named sha'\n     * XXX         in <function callback at 0x008F5718> ignored\n     * XXX but I'm unclear on exactly how that one happens.  In any case,\n     * XXX I haven't seen a real-life report of either of these.\n     */\n    PyGC_Collect();\n\n    /* Destroy all modules */\n    _PyImport_FiniExternal(tstate->interp);\n    finalize_modules(tstate);\n\n    /* Print debug stats if any */\n    _PyEval_Fini();\n\n    /* Flush sys.stdout and sys.stderr (again, in case more was printed) */\n    if (flush_std_files() < 0) {\n        status = -1;\n    }\n\n    /* Collect final garbage.  This disposes of cycles created by\n     * class definitions, for example.\n     * XXX This is disabled because it caused too many problems.  If\n     * XXX a __del__ or weakref callback triggers here, Python code has\n     * XXX a hard time running, because even the sys module has been\n     * XXX cleared out (sys.stdout is gone, sys.excepthook is gone, etc).\n     * XXX One symptom is a sequence of information-free messages\n     * XXX coming from threads (if a __del__ or callback is invoked,\n     * XXX other threads can execute too, and any exception they encounter\n     * XXX triggers a comedy of errors as subsystem after subsystem\n     * XXX fails to find what it *expects* to find in sys to help report\n     * XXX the exception and consequent unexpected failures).  I've also\n     * XXX seen segfaults then, after adding print statements to the\n     * XXX Python code getting called.\n     */\n#if 0\n    _PyGC_CollectIfEnabled();\n#endif\n\n    /* Disable tracemalloc after all Python objects have been destroyed,\n       so it is possible to use tracemalloc in objects destructor. */\n    _PyTraceMalloc_Fini();\n\n    /* Finalize any remaining import state */\n    // XXX Move these up to where finalize_modules() is currently.\n    _PyImport_FiniCore(tstate->interp);\n    _PyImport_Fini();\n\n    /* unload faulthandler module */\n    _PyFaulthandler_Fini();\n\n    /* dump hash stats */\n    _PyHash_Fini();\n\n#ifdef Py_TRACE_REFS\n    /* Display all objects still alive -- this can invoke arbitrary\n     * __repr__ overrides, so requires a mostly-intact interpreter.\n     * Alas, a lot of stuff may still be alive now that will be cleaned\n     * up later.\n     */\n\n    FILE *dump_refs_fp = NULL;\n    if (dump_refs_file != NULL) {\n        dump_refs_fp = _Py_wfopen(dump_refs_file, L\"w\");\n        if (dump_refs_fp == NULL) {\n            fprintf(stderr, \"PYTHONDUMPREFSFILE: cannot create file: %ls\\n\", dump_refs_file);\n        }\n    }\n\n    if (dump_refs) {\n        _Py_PrintReferences(stderr);\n    }\n\n    if (dump_refs_fp != NULL) {\n        _Py_PrintReferences(dump_refs_fp);\n    }\n#endif /* Py_TRACE_REFS */\n\n    /* At this point there's almost no other Python code that will run,\n       nor interpreter state needed.  The only possibility is the\n       finalizers of the objects stored on tstate (and tstate->interp),\n       which are triggered via finalize_interp_clear().\n\n       For now we operate as though none of those finalizers actually\n       need an operational thread state or interpreter.  In reality,\n       those finalizers may rely on some part of tstate or\n       tstate->interp, and/or may raise exceptions\n       or otherwise fail.\n     */\n    // XXX Do this sooner during finalization.\n    // XXX Ensure finalizer errors are handled properly.\n\n    finalize_interp_clear(tstate);\n    finalize_interp_delete(tstate->interp);\n\n#ifdef Py_REF_DEBUG\n    if (show_ref_count) {\n        _PyDebug_PrintTotalRefs();\n    }\n    _Py_FinalizeRefTotal(runtime);\n#endif\n    _Py_FinalizeAllocatedBlocks(runtime);\n\n#ifdef Py_TRACE_REFS\n    /* Display addresses (& refcnts) of all objects still alive.\n     * An address can be used to find the repr of the object, printed\n     * above by _Py_PrintReferences.\n     */\n\n    if (dump_refs) {\n        _Py_PrintReferenceAddresses(stderr);\n    }\n\n    if (dump_refs_fp != NULL) {\n        _Py_PrintReferenceAddresses(dump_refs_fp);\n        fclose(dump_refs_fp);\n    }\n#endif /* Py_TRACE_REFS */\n#ifdef WITH_PYMALLOC\n    if (malloc_stats) {\n        _PyObject_DebugMallocStats(stderr);\n    }\n#endif\n\n    call_ll_exitfuncs(runtime);\n\n    _PyRuntime_Finalize();\n    return status;\n}\n\nvoid\nPy_Finalize(void)\n{\n    Py_FinalizeEx();\n}\n\n\n/* Create and initialize a new interpreter and thread, and return the\n   new thread.  This requires that Py_Initialize() has been called\n   first.\n\n   Unsuccessful initialization yields a NULL pointer.  Note that *no*\n   exception information is available even in this case -- the\n   exception information is held in the thread, and there is no\n   thread.\n\n   Locking: as above.\n\n*/\n\nstatic PyStatus\nnew_interpreter(PyThreadState **tstate_p, const PyInterpreterConfig *config)\n{\n    PyStatus status;\n\n    status = _PyRuntime_Initialize();\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n    _PyRuntimeState *runtime = &_PyRuntime;\n\n    if (!runtime->initialized) {\n        return _PyStatus_ERR(\"Py_Initialize must be called first\");\n    }\n\n    /* Issue #10915, #15751: The GIL API doesn't work with multiple\n       interpreters: disable PyGILState_Check(). */\n    runtime->gilstate.check_enabled = 0;\n\n    PyInterpreterState *interp = PyInterpreterState_New();\n    if (interp == NULL) {\n        *tstate_p = NULL;\n        return _PyStatus_OK();\n    }\n\n    PyThreadState *tstate = _PyThreadState_New(interp);\n    if (tstate == NULL) {\n        PyInterpreterState_Delete(interp);\n        *tstate_p = NULL;\n        return _PyStatus_OK();\n    }\n    _PyThreadState_Bind(tstate);\n\n    // XXX For now we do this before the GIL is created.\n    PyThreadState *save_tstate = _PyThreadState_SwapNoGIL(tstate);\n    int has_gil = 0;\n\n    /* From this point until the init_interp_create_gil() call,\n       we must not do anything that requires that the GIL be held\n       (or otherwise exist).  That applies whether or not the new\n       interpreter has its own GIL (e.g. the main interpreter). */\n\n    /* Copy the current interpreter config into the new interpreter */\n    const PyConfig *src_config;\n    if (save_tstate != NULL) {\n        // XXX Might new_interpreter() have been called without the GIL held?\n        _PyEval_ReleaseLock(save_tstate);\n        src_config = _PyInterpreterState_GetConfig(save_tstate->interp);\n    }\n    else\n    {\n        /* No current thread state, copy from the main interpreter */\n        PyInterpreterState *main_interp = _PyInterpreterState_Main();\n        src_config = _PyInterpreterState_GetConfig(main_interp);\n    }\n\n    /* This does not require that the GIL be held. */\n    status = _PyConfig_Copy(&interp->config, src_config);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto error;\n    }\n\n    /* This does not require that the GIL be held. */\n    status = init_interp_settings(interp, config);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto error;\n    }\n\n    status = init_interp_create_gil(tstate, config->own_gil);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto error;\n    }\n    has_gil = 1;\n\n    status = pycore_interp_init(tstate);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto error;\n    }\n\n    status = init_interp_main(tstate);\n    if (_PyStatus_EXCEPTION(status)) {\n        goto error;\n    }\n\n    *tstate_p = tstate;\n    return _PyStatus_OK();\n\nerror:\n    *tstate_p = NULL;\n\n    /* Oops, it didn't work.  Undo it all. */\n    PyErr_PrintEx(0);\n    if (has_gil) {\n        PyThreadState_Swap(save_tstate);\n    }\n    else {\n        _PyThreadState_SwapNoGIL(save_tstate);\n    }\n    PyThreadState_Clear(tstate);\n    PyThreadState_Delete(tstate);\n    PyInterpreterState_Delete(interp);\n\n    return status;\n}\n\nPyStatus\nPy_NewInterpreterFromConfig(PyThreadState **tstate_p,\n                            const PyInterpreterConfig *config)\n{\n    return new_interpreter(tstate_p, config);\n}\n\nPyThreadState *\nPy_NewInterpreter(void)\n{\n    PyThreadState *tstate = NULL;\n    const PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT;\n    PyStatus status = new_interpreter(&tstate, &config);\n    if (_PyStatus_EXCEPTION(status)) {\n        Py_ExitStatusException(status);\n    }\n    return tstate;\n}\n\n/* Delete an interpreter and its last thread.  This requires that the\n   given thread state is current, that the thread has no remaining\n   frames, and that it is its interpreter's only remaining thread.\n   It is a fatal error to violate these constraints.\n\n   (Py_FinalizeEx() doesn't have these constraints -- it zaps\n   everything, regardless.)\n\n   Locking: as above.\n\n*/\n\nvoid\nPy_EndInterpreter(PyThreadState *tstate)\n{\n    PyInterpreterState *interp = tstate->interp;\n\n    if (tstate != _PyThreadState_GET()) {\n        Py_FatalError(\"thread is not current\");\n    }\n    if (tstate->cframe->current_frame != NULL) {\n        Py_FatalError(\"thread still has a frame\");\n    }\n    interp->finalizing = 1;\n\n    // Wrap up existing \"threading\"-module-created, non-daemon threads.\n    wait_for_thread_shutdown(tstate);\n\n    _PyAtExit_Call(tstate->interp);\n\n    if (tstate != interp->threads.head || tstate->next != NULL) {\n        Py_FatalError(\"not the last thread\");\n    }\n\n    /* Remaining daemon threads will automatically exit\n       when they attempt to take the GIL (ex: PyEval_RestoreThread()). */\n    _PyInterpreterState_SetFinalizing(interp, tstate);\n\n    // XXX Call something like _PyImport_Disable() here?\n\n    _PyImport_FiniExternal(tstate->interp);\n    finalize_modules(tstate);\n    _PyImport_FiniCore(tstate->interp);\n\n    finalize_interp_clear(tstate);\n    finalize_interp_delete(tstate->interp);\n}\n\nint\n_Py_IsInterpreterFinalizing(PyInterpreterState *interp)\n{\n    /* We check the runtime first since, in a daemon thread,\n       interp might be dangling pointer. */\n    PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime);\n    if (finalizing == NULL) {\n        finalizing = _PyInterpreterState_GetFinalizing(interp);\n    }\n    return finalizing != NULL;\n}\n\n/* Add the __main__ module */\n\nstatic PyStatus\nadd_main_module(PyInterpreterState *interp)\n{\n    PyObject *m, *d, *loader, *ann_dict;\n    m = PyImport_AddModule(\"__main__\");\n    if (m == NULL)\n        return _PyStatus_ERR(\"can't create __main__ module\");\n\n    d = PyModule_GetDict(m);\n    ann_dict = PyDict_New();\n    if ((ann_dict == NULL) ||\n        (PyDict_SetItemString(d, \"__annotations__\", ann_dict) < 0)) {\n        return _PyStatus_ERR(\"Failed to initialize __main__.__annotations__\");\n    }\n    Py_DECREF(ann_dict);\n\n    if (_PyDict_GetItemStringWithError(d, \"__builtins__\") == NULL) {\n        if (PyErr_Occurred()) {\n            return _PyStatus_ERR(\"Failed to test __main__.__builtins__\");\n        }\n        PyObject *bimod = PyImport_ImportModule(\"builtins\");\n        if (bimod == NULL) {\n            return _PyStatus_ERR(\"Failed to retrieve builtins module\");\n        }\n        if (PyDict_SetItemString(d, \"__builtins__\", bimod) < 0) {\n            return _PyStatus_ERR(\"Failed to initialize __main__.__builtins__\");\n        }\n        Py_DECREF(bimod);\n    }\n\n    /* Main is a little special - BuiltinImporter is the most appropriate\n     * initial setting for its __loader__ attribute. A more suitable value\n     * will be set if __main__ gets further initialized later in the startup\n     * process.\n     */\n    loader = _PyDict_GetItemStringWithError(d, \"__loader__\");\n    if (loader == NULL || loader == Py_None) {\n        if (PyErr_Occurred()) {\n            return _PyStatus_ERR(\"Failed to test __main__.__loader__\");\n        }\n        PyObject *loader = _PyImport_GetImportlibLoader(interp,\n                                                        \"BuiltinImporter\");\n        if (loader == NULL) {\n            return _PyStatus_ERR(\"Failed to retrieve BuiltinImporter\");\n        }\n        if (PyDict_SetItemString(d, \"__loader__\", loader) < 0) {\n            return _PyStatus_ERR(\"Failed to initialize __main__.__loader__\");\n        }\n        Py_DECREF(loader);\n    }\n    return _PyStatus_OK();\n}\n\n/* Import the site module (not into __main__ though) */\n\nstatic PyStatus\ninit_import_site(void)\n{\n    PyObject *m;\n    m = PyImport_ImportModule(\"site\");\n    if (m == NULL) {\n        return _PyStatus_ERR(\"Failed to import the site module\");\n    }\n    Py_DECREF(m);\n    return _PyStatus_OK();\n}\n\n/* Check if a file descriptor is valid or not.\n   Return 0 if the file descriptor is invalid, return non-zero otherwise. */\nstatic int\nis_valid_fd(int fd)\n{\n/* dup() is faster than fstat(): fstat() can require input/output operations,\n   whereas dup() doesn't. There is a low risk of EMFILE/ENFILE at Python\n   startup. Problem: dup() doesn't check if the file descriptor is valid on\n   some platforms.\n\n   fcntl(fd, F_GETFD) is even faster, because it only checks the process table.\n   It is preferred over dup() when available, since it cannot fail with the\n   \"too many open files\" error (EMFILE).\n\n   bpo-30225: On macOS Tiger, when stdout is redirected to a pipe and the other\n   side of the pipe is closed, dup(1) succeed, whereas fstat(1, &st) fails with\n   EBADF. FreeBSD has similar issue (bpo-32849).\n\n   Only use dup() on Linux where dup() is enough to detect invalid FD\n   (bpo-32849).\n*/\n    if (fd < 0) {\n        return 0;\n    }\n#if defined(F_GETFD) && ( \\\n        defined(__linux__) || \\\n        defined(__APPLE__) || \\\n        defined(__wasm__))\n    return fcntl(fd, F_GETFD) >= 0;\n#elif defined(__linux__)\n    int fd2 = dup(fd);\n    if (fd2 >= 0) {\n        close(fd2);\n    }\n    return (fd2 >= 0);\n#elif defined(MS_WINDOWS)\n    HANDLE hfile;\n    _Py_BEGIN_SUPPRESS_IPH\n    hfile = (HANDLE)_get_osfhandle(fd);\n    _Py_END_SUPPRESS_IPH\n    return (hfile != INVALID_HANDLE_VALUE\n            && GetFileType(hfile) != FILE_TYPE_UNKNOWN);\n#else\n    struct stat st;\n    return (fstat(fd, &st) == 0);\n#endif\n}\n\n/* returns Py_None if the fd is not valid */\nstatic PyObject*\ncreate_stdio(const PyConfig *config, PyObject* io,\n    int fd, int write_mode, const char* name,\n    const wchar_t* encoding, const wchar_t* errors)\n{\n    PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res;\n    const char* mode;\n    const char* newline;\n    PyObject *line_buffering, *write_through;\n    int buffering, isatty;\n    const int buffered_stdio = config->buffered_stdio;\n\n    if (!is_valid_fd(fd))\n        Py_RETURN_NONE;\n\n    /* stdin is always opened in buffered mode, first because it shouldn't\n       make a difference in common use cases, second because TextIOWrapper\n       depends on the presence of a read1() method which only exists on\n       buffered streams.\n    */\n    if (!buffered_stdio && write_mode)\n        buffering = 0;\n    else\n        buffering = -1;\n    if (write_mode)\n        mode = \"wb\";\n    else\n        mode = \"rb\";\n    buf = _PyObject_CallMethod(io, &_Py_ID(open), \"isiOOOO\",\n                               fd, mode, buffering,\n                               Py_None, Py_None, /* encoding, errors */\n                               Py_None, Py_False); /* newline, closefd */\n    if (buf == NULL)\n        goto error;\n\n    if (buffering) {\n        raw = PyObject_GetAttr(buf, &_Py_ID(raw));\n        if (raw == NULL)\n            goto error;\n    }\n    else {\n        raw = Py_NewRef(buf);\n    }\n\n#ifdef HAVE_WINDOWS_CONSOLE_IO\n    /* Windows console IO is always UTF-8 encoded */\n    PyTypeObject *winconsoleio_type = (PyTypeObject *)_PyImport_GetModuleAttr(\n            &_Py_ID(_io), &_Py_ID(_WindowsConsoleIO));\n    if (winconsoleio_type == NULL) {\n        goto error;\n    }\n    int is_subclass = PyObject_TypeCheck(raw, winconsoleio_type);\n    Py_DECREF(winconsoleio_type);\n    if (is_subclass) {\n        encoding = L\"utf-8\";\n    }\n#endif\n\n    text = PyUnicode_FromString(name);\n    if (text == NULL || PyObject_SetAttr(raw, &_Py_ID(name), text) < 0)\n        goto error;\n    res = PyObject_CallMethodNoArgs(raw, &_Py_ID(isatty));\n    if (res == NULL)\n        goto error;\n    isatty = PyObject_IsTrue(res);\n    Py_DECREF(res);\n    if (isatty == -1)\n        goto error;\n    if (!buffered_stdio)\n        write_through = Py_True;\n    else\n        write_through = Py_False;\n    if (buffered_stdio && (isatty || fd == fileno(stderr)))\n        line_buffering = Py_True;\n    else\n        line_buffering = Py_False;\n\n    Py_CLEAR(raw);\n    Py_CLEAR(text);\n\n#ifdef MS_WINDOWS\n    /* sys.stdin: enable universal newline mode, translate \"\\r\\n\" and \"\\r\"\n       newlines to \"\\n\".\n       sys.stdout and sys.stderr: translate \"\\n\" to \"\\r\\n\". */\n    newline = NULL;\n#else\n    /* sys.stdin: split lines at \"\\n\".\n       sys.stdout and sys.stderr: don't translate newlines (use \"\\n\"). */\n    newline = \"\\n\";\n#endif\n\n    PyObject *encoding_str = PyUnicode_FromWideChar(encoding, -1);\n    if (encoding_str == NULL) {\n        Py_CLEAR(buf);\n        goto error;\n    }\n\n    PyObject *errors_str = PyUnicode_FromWideChar(errors, -1);\n    if (errors_str == NULL) {\n        Py_CLEAR(buf);\n        Py_CLEAR(encoding_str);\n        goto error;\n    }\n\n    stream = _PyObject_CallMethod(io, &_Py_ID(TextIOWrapper), \"OOOsOO\",\n                                  buf, encoding_str, errors_str,\n                                  newline, line_buffering, write_through);\n    Py_CLEAR(buf);\n    Py_CLEAR(encoding_str);\n    Py_CLEAR(errors_str);\n    if (stream == NULL)\n        goto error;\n\n    if (write_mode)\n        mode = \"w\";\n    else\n        mode = \"r\";\n    text = PyUnicode_FromString(mode);\n    if (!text || PyObject_SetAttr(stream, &_Py_ID(mode), text) < 0)\n        goto error;\n    Py_CLEAR(text);\n    return stream;\n\nerror:\n    Py_XDECREF(buf);\n    Py_XDECREF(stream);\n    Py_XDECREF(text);\n    Py_XDECREF(raw);\n\n    if (PyErr_ExceptionMatches(PyExc_OSError) && !is_valid_fd(fd)) {\n        /* Issue #24891: the file descriptor was closed after the first\n           is_valid_fd() check was called. Ignore the OSError and set the\n           stream to None. */\n        PyErr_Clear();\n        Py_RETURN_NONE;\n    }\n    return NULL;\n}\n\n/* Set builtins.open to io.open */\nstatic PyStatus\ninit_set_builtins_open(void)\n{\n    PyObject *wrapper;\n    PyObject *bimod = NULL;\n    PyStatus res = _PyStatus_OK();\n\n    if (!(bimod = PyImport_ImportModule(\"builtins\"))) {\n        goto error;\n    }\n\n    if (!(wrapper = _PyImport_GetModuleAttrString(\"io\", \"open\"))) {\n        goto error;\n    }\n\n    /* Set builtins.open */\n    if (PyObject_SetAttrString(bimod, \"open\", wrapper) == -1) {\n        Py_DECREF(wrapper);\n        goto error;\n    }\n    Py_DECREF(wrapper);\n    goto done;\n\nerror:\n    res = _PyStatus_ERR(\"can't initialize io.open\");\n\ndone:\n    Py_XDECREF(bimod);\n    return res;\n}\n\n\n/* Create sys.stdin, sys.stdout and sys.stderr */\nstatic PyStatus\ninit_sys_streams(PyThreadState *tstate)\n{\n    PyObject *iomod = NULL;\n    PyObject *std = NULL;\n    int fd;\n    PyObject * encoding_attr;\n    PyStatus res = _PyStatus_OK();\n    const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);\n\n    /* Check that stdin is not a directory\n       Using shell redirection, you can redirect stdin to a directory,\n       crashing the Python interpreter. Catch this common mistake here\n       and output a useful error message. Note that under MS Windows,\n       the shell already prevents that. */\n#ifndef MS_WINDOWS\n    struct _Py_stat_struct sb;\n    if (_Py_fstat_noraise(fileno(stdin), &sb) == 0 &&\n        S_ISDIR(sb.st_mode)) {\n        return _PyStatus_ERR(\"<stdin> is a directory, cannot continue\");\n    }\n#endif\n\n    if (!(iomod = PyImport_ImportModule(\"io\"))) {\n        goto error;\n    }\n\n    /* Set sys.stdin */\n    fd = fileno(stdin);\n    /* Under some conditions stdin, stdout and stderr may not be connected\n     * and fileno() may point to an invalid file descriptor. For example\n     * GUI apps don't have valid standard streams by default.\n     */\n    std = create_stdio(config, iomod, fd, 0, \"<stdin>\",\n                       config->stdio_encoding,\n                       config->stdio_errors);\n    if (std == NULL)\n        goto error;\n    PySys_SetObject(\"__stdin__\", std);\n    _PySys_SetAttr(&_Py_ID(stdin), std);\n    Py_DECREF(std);\n\n    /* Set sys.stdout */\n    fd = fileno(stdout);\n    std = create_stdio(config, iomod, fd, 1, \"<stdout>\",\n                       config->stdio_encoding,\n                       config->stdio_errors);\n    if (std == NULL)\n        goto error;\n    PySys_SetObject(\"__stdout__\", std);\n    _PySys_SetAttr(&_Py_ID(stdout), std);\n    Py_DECREF(std);\n\n#if 1 /* Disable this if you have trouble debugging bootstrap stuff */\n    /* Set sys.stderr, replaces the preliminary stderr */\n    fd = fileno(stderr);\n    std = create_stdio(config, iomod, fd, 1, \"<stderr>\",\n                       config->stdio_encoding,\n                       L\"backslashreplace\");\n    if (std == NULL)\n        goto error;\n\n    /* Same as hack above, pre-import stderr's codec to avoid recursion\n       when import.c tries to write to stderr in verbose mode. */\n    encoding_attr = PyObject_GetAttrString(std, \"encoding\");\n    if (encoding_attr != NULL) {\n        const char *std_encoding = PyUnicode_AsUTF8(encoding_attr);\n        if (std_encoding != NULL) {\n            PyObject *codec_info = _PyCodec_Lookup(std_encoding);\n            Py_XDECREF(codec_info);\n        }\n        Py_DECREF(encoding_attr);\n    }\n    _PyErr_Clear(tstate);  /* Not a fatal error if codec isn't available */\n\n    if (PySys_SetObject(\"__stderr__\", std) < 0) {\n        Py_DECREF(std);\n        goto error;\n    }\n    if (_PySys_SetAttr(&_Py_ID(stderr), std) < 0) {\n        Py_DECREF(std);\n        goto error;\n    }\n    Py_DECREF(std);\n#endif\n\n    goto done;\n\nerror:\n    res = _PyStatus_ERR(\"can't initialize sys standard streams\");\n\ndone:\n    Py_XDECREF(iomod);\n    return res;\n}\n\n\nstatic void\n_Py_FatalError_DumpTracebacks(int fd, PyInterpreterState *interp,\n                              PyThreadState *tstate)\n{\n    PUTS(fd, \"\\n\");\n\n    /* display the current Python stack */\n    _Py_DumpTracebackThreads(fd, interp, tstate);\n}\n\n/* Print the current exception (if an exception is set) with its traceback,\n   or display the current Python stack.\n\n   Don't call PyErr_PrintEx() and the except hook, because Py_FatalError() is\n   called on catastrophic cases.\n\n   Return 1 if the traceback was displayed, 0 otherwise. */\n\nstatic int\n_Py_FatalError_PrintExc(PyThreadState *tstate)\n{\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    if (exc == NULL) {\n        /* No current exception */\n        return 0;\n    }\n\n    PyObject *ferr = _PySys_GetAttr(tstate, &_Py_ID(stderr));\n    if (ferr == NULL || ferr == Py_None) {\n        /* sys.stderr is not set yet or set to None,\n           no need to try to display the exception */\n        Py_DECREF(exc);\n        return 0;\n    }\n\n    PyErr_DisplayException(exc);\n\n    PyObject *tb = PyException_GetTraceback(exc);\n    int has_tb = (tb != NULL) && (tb != Py_None);\n    Py_XDECREF(tb);\n    Py_DECREF(exc);\n\n    /* sys.stderr may be buffered: call sys.stderr.flush() */\n    PyObject *res = PyObject_CallMethodNoArgs(ferr, &_Py_ID(flush));\n    if (res == NULL) {\n        _PyErr_Clear(tstate);\n    }\n    else {\n        Py_DECREF(res);\n    }\n\n    return has_tb;\n}\n\n/* Print fatal error message and abort */\n\n#ifdef MS_WINDOWS\nstatic void\nfatal_output_debug(const char *msg)\n{\n    /* buffer of 256 bytes allocated on the stack */\n    WCHAR buffer[256 / sizeof(WCHAR)];\n    size_t buflen = Py_ARRAY_LENGTH(buffer) - 1;\n    size_t msglen;\n\n    OutputDebugStringW(L\"Fatal Python error: \");\n\n    msglen = strlen(msg);\n    while (msglen) {\n        size_t i;\n\n        if (buflen > msglen) {\n            buflen = msglen;\n        }\n\n        /* Convert the message to wchar_t. This uses a simple one-to-one\n           conversion, assuming that the this error message actually uses\n           ASCII only. If this ceases to be true, we will have to convert. */\n        for (i=0; i < buflen; ++i) {\n            buffer[i] = msg[i];\n        }\n        buffer[i] = L'\\0';\n        OutputDebugStringW(buffer);\n\n        msg += buflen;\n        msglen -= buflen;\n    }\n    OutputDebugStringW(L\"\\n\");\n}\n#endif\n\n\nstatic void\nfatal_error_dump_runtime(int fd, _PyRuntimeState *runtime)\n{\n    PUTS(fd, \"Python runtime state: \");\n    PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime);\n    if (finalizing) {\n        PUTS(fd, \"finalizing (tstate=0x\");\n        _Py_DumpHexadecimal(fd, (uintptr_t)finalizing, sizeof(finalizing) * 2);\n        PUTS(fd, \")\");\n    }\n    else if (runtime->initialized) {\n        PUTS(fd, \"initialized\");\n    }\n    else if (runtime->core_initialized) {\n        PUTS(fd, \"core initialized\");\n    }\n    else if (runtime->preinitialized) {\n        PUTS(fd, \"preinitialized\");\n    }\n    else if (runtime->preinitializing) {\n        PUTS(fd, \"preinitializing\");\n    }\n    else {\n        PUTS(fd, \"unknown\");\n    }\n    PUTS(fd, \"\\n\");\n}\n\n\nstatic inline void _Py_NO_RETURN\nfatal_error_exit(int status)\n{\n    if (status < 0) {\n#if defined(MS_WINDOWS) && defined(_DEBUG)\n        DebugBreak();\n#endif\n        abort();\n    }\n    else {\n        exit(status);\n    }\n}\n\n\n// Dump the list of extension modules of sys.modules, excluding stdlib modules\n// (sys.stdlib_module_names), into fd file descriptor.\n//\n// This function is called by a signal handler in faulthandler: avoid memory\n// allocations and keep the implementation simple. For example, the list is not\n// sorted on purpose.\nvoid\n_Py_DumpExtensionModules(int fd, PyInterpreterState *interp)\n{\n    if (interp == NULL) {\n        return;\n    }\n    PyObject *modules = _PyImport_GetModules(interp);\n    if (modules == NULL || !PyDict_Check(modules)) {\n        return;\n    }\n\n    Py_ssize_t pos;\n    PyObject *key, *value;\n\n    // Avoid PyDict_GetItemString() which calls PyUnicode_FromString(),\n    // memory cannot be allocated on the heap in a signal handler.\n    // Iterate on the dict instead.\n    PyObject *stdlib_module_names = NULL;\n    if (interp->sysdict != NULL) {\n        pos = 0;\n        while (PyDict_Next(interp->sysdict, &pos, &key, &value)) {\n            if (PyUnicode_Check(key)\n               && PyUnicode_CompareWithASCIIString(key, \"stdlib_module_names\") == 0) {\n                stdlib_module_names = value;\n                break;\n            }\n        }\n    }\n    // If we failed to get sys.stdlib_module_names or it's not a frozenset,\n    // don't exclude stdlib modules.\n    if (stdlib_module_names != NULL && !PyFrozenSet_Check(stdlib_module_names)) {\n        stdlib_module_names = NULL;\n    }\n\n    // List extensions\n    int header = 1;\n    Py_ssize_t count = 0;\n    pos = 0;\n    while (PyDict_Next(modules, &pos, &key, &value)) {\n        if (!PyUnicode_Check(key)) {\n            continue;\n        }\n        if (!_PyModule_IsExtension(value)) {\n            continue;\n        }\n        // Use the module name from the sys.modules key,\n        // don't attempt to get the module object name.\n        if (stdlib_module_names != NULL) {\n            int is_stdlib_ext = 0;\n\n            Py_ssize_t i = 0;\n            PyObject *item;\n            Py_hash_t hash;\n            while (_PySet_NextEntry(stdlib_module_names, &i, &item, &hash)) {\n                if (PyUnicode_Check(item)\n                    && PyUnicode_Compare(key, item) == 0)\n                {\n                    is_stdlib_ext = 1;\n                    break;\n                }\n            }\n            if (is_stdlib_ext) {\n                // Ignore stdlib extension\n                continue;\n            }\n        }\n\n        if (header) {\n            PUTS(fd, \"\\nExtension modules: \");\n            header = 0;\n        }\n        else {\n            PUTS(fd, \", \");\n        }\n\n        _Py_DumpASCII(fd, key);\n        count++;\n    }\n\n    if (count) {\n        PUTS(fd, \" (total: \");\n        _Py_DumpDecimal(fd, count);\n        PUTS(fd, \")\");\n        PUTS(fd, \"\\n\");\n    }\n}\n\n\nstatic void _Py_NO_RETURN\nfatal_error(int fd, int header, const char *prefix, const char *msg,\n            int status)\n{\n    static int reentrant = 0;\n\n    if (reentrant) {\n        /* Py_FatalError() caused a second fatal error.\n           Example: flush_std_files() raises a recursion error. */\n        fatal_error_exit(status);\n    }\n    reentrant = 1;\n\n    if (header) {\n        PUTS(fd, \"Fatal Python error: \");\n        if (prefix) {\n            PUTS(fd, prefix);\n            PUTS(fd, \": \");\n        }\n        if (msg) {\n            PUTS(fd, msg);\n        }\n        else {\n            PUTS(fd, \"<message not set>\");\n        }\n        PUTS(fd, \"\\n\");\n    }\n\n    _PyRuntimeState *runtime = &_PyRuntime;\n    fatal_error_dump_runtime(fd, runtime);\n\n    /* Check if the current thread has a Python thread state\n       and holds the GIL.\n\n       tss_tstate is NULL if Py_FatalError() is called from a C thread which\n       has no Python thread state.\n\n       tss_tstate != tstate if the current Python thread does not hold the GIL.\n       */\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyInterpreterState *interp = NULL;\n    PyThreadState *tss_tstate = PyGILState_GetThisThreadState();\n    if (tstate != NULL) {\n        interp = tstate->interp;\n    }\n    else if (tss_tstate != NULL) {\n        interp = tss_tstate->interp;\n    }\n    int has_tstate_and_gil = (tss_tstate != NULL && tss_tstate == tstate);\n\n    if (has_tstate_and_gil) {\n        /* If an exception is set, print the exception with its traceback */\n        if (!_Py_FatalError_PrintExc(tss_tstate)) {\n            /* No exception is set, or an exception is set without traceback */\n            _Py_FatalError_DumpTracebacks(fd, interp, tss_tstate);\n        }\n    }\n    else {\n        _Py_FatalError_DumpTracebacks(fd, interp, tss_tstate);\n    }\n\n    _Py_DumpExtensionModules(fd, interp);\n\n    /* The main purpose of faulthandler is to display the traceback.\n       This function already did its best to display a traceback.\n       Disable faulthandler to prevent writing a second traceback\n       on abort(). */\n    _PyFaulthandler_Fini();\n\n    /* Check if the current Python thread hold the GIL */\n    if (has_tstate_and_gil) {\n        /* Flush sys.stdout and sys.stderr */\n        flush_std_files();\n    }\n\n#ifdef MS_WINDOWS\n    fatal_output_debug(msg);\n#endif /* MS_WINDOWS */\n\n    fatal_error_exit(status);\n}\n\n\n#undef Py_FatalError\n\nvoid _Py_NO_RETURN\nPy_FatalError(const char *msg)\n{\n    fatal_error(fileno(stderr), 1, NULL, msg, -1);\n}\n\n\nvoid _Py_NO_RETURN\n_Py_FatalErrorFunc(const char *func, const char *msg)\n{\n    fatal_error(fileno(stderr), 1, func, msg, -1);\n}\n\n\nvoid _Py_NO_RETURN\n_Py_FatalErrorFormat(const char *func, const char *format, ...)\n{\n    static int reentrant = 0;\n    if (reentrant) {\n        /* _Py_FatalErrorFormat() caused a second fatal error */\n        fatal_error_exit(-1);\n    }\n    reentrant = 1;\n\n    FILE *stream = stderr;\n    const int fd = fileno(stream);\n    PUTS(fd, \"Fatal Python error: \");\n    if (func) {\n        PUTS(fd, func);\n        PUTS(fd, \": \");\n    }\n\n    va_list vargs;\n    va_start(vargs, format);\n    vfprintf(stream, format, vargs);\n    va_end(vargs);\n\n    fputs(\"\\n\", stream);\n    fflush(stream);\n\n    fatal_error(fd, 0, NULL, NULL, -1);\n}\n\n\nvoid _Py_NO_RETURN\n_Py_FatalRefcountErrorFunc(const char *func, const char *msg)\n{\n    _Py_FatalErrorFormat(func,\n                         \"%s: bug likely caused by a refcount error \"\n                         \"in a C extension\",\n                         msg);\n}\n\n\nvoid _Py_NO_RETURN\nPy_ExitStatusException(PyStatus status)\n{\n    if (_PyStatus_IS_EXIT(status)) {\n        exit(status.exitcode);\n    }\n    else if (_PyStatus_IS_ERROR(status)) {\n        fatal_error(fileno(stderr), 1, status.func, status.err_msg, 1);\n    }\n    else {\n        Py_FatalError(\"Py_ExitStatusException() must not be called on success\");\n    }\n}\n\n\n/* Wait until threading._shutdown completes, provided\n   the threading module was imported in the first place.\n   The shutdown routine will wait until all non-daemon\n   \"threading\" threads have completed. */\nstatic void\nwait_for_thread_shutdown(PyThreadState *tstate)\n{\n    PyObject *result;\n    PyObject *threading = PyImport_GetModule(&_Py_ID(threading));\n    if (threading == NULL) {\n        if (_PyErr_Occurred(tstate)) {\n            PyErr_WriteUnraisable(NULL);\n        }\n        /* else: threading not imported */\n        return;\n    }\n    result = PyObject_CallMethodNoArgs(threading, &_Py_ID(_shutdown));\n    if (result == NULL) {\n        PyErr_WriteUnraisable(threading);\n    }\n    else {\n        Py_DECREF(result);\n    }\n    Py_DECREF(threading);\n}\n\nint Py_AtExit(void (*func)(void))\n{\n    if (_PyRuntime.atexit.ncallbacks >= NEXITFUNCS)\n        return -1;\n    _PyRuntime.atexit.callbacks[_PyRuntime.atexit.ncallbacks++] = func;\n    return 0;\n}\n\nstatic void\ncall_ll_exitfuncs(_PyRuntimeState *runtime)\n{\n    struct _atexit_runtime_state *state = &runtime->atexit;\n    while (state->ncallbacks > 0) {\n        /* pop last function from the list */\n        state->ncallbacks--;\n        atexit_callbackfunc exitfunc = state->callbacks[state->ncallbacks];\n        state->callbacks[state->ncallbacks] = NULL;\n\n        exitfunc();\n    }\n\n    fflush(stdout);\n    fflush(stderr);\n}\n\nvoid _Py_NO_RETURN\nPy_Exit(int sts)\n{\n    if (Py_FinalizeEx() < 0) {\n        sts = 120;\n    }\n\n    exit(sts);\n}\n\n\n/*\n * The file descriptor fd is considered ``interactive'' if either\n *   a) isatty(fd) is TRUE, or\n *   b) the -i flag was given, and the filename associated with\n *      the descriptor is NULL or \"<stdin>\" or \"???\".\n */\nint\nPy_FdIsInteractive(FILE *fp, const char *filename)\n{\n    if (isatty(fileno(fp))) {\n        return 1;\n    }\n    if (!_Py_GetConfig()->interactive) {\n        return 0;\n    }\n    return ((filename == NULL)\n            || (strcmp(filename, \"<stdin>\") == 0)\n            || (strcmp(filename, \"???\") == 0));\n}\n\n\nint\n_Py_FdIsInteractive(FILE *fp, PyObject *filename)\n{\n    if (isatty(fileno(fp))) {\n        return 1;\n    }\n    if (!_Py_GetConfig()->interactive) {\n        return 0;\n    }\n    return ((filename == NULL)\n            || (PyUnicode_CompareWithASCIIString(filename, \"<stdin>\") == 0)\n            || (PyUnicode_CompareWithASCIIString(filename, \"???\") == 0));\n}\n\n\n/* Wrappers around sigaction() or signal(). */\n\nPyOS_sighandler_t\nPyOS_getsig(int sig)\n{\n#ifdef HAVE_SIGACTION\n    struct sigaction context;\n    if (sigaction(sig, NULL, &context) == -1)\n        return SIG_ERR;\n    return context.sa_handler;\n#else\n    PyOS_sighandler_t handler;\n/* Special signal handling for the secure CRT in Visual Studio 2005 */\n#if defined(_MSC_VER) && _MSC_VER >= 1400\n    switch (sig) {\n    /* Only these signals are valid */\n    case SIGINT:\n    case SIGILL:\n    case SIGFPE:\n    case SIGSEGV:\n    case SIGTERM:\n    case SIGBREAK:\n    case SIGABRT:\n        break;\n    /* Don't call signal() with other values or it will assert */\n    default:\n        return SIG_ERR;\n    }\n#endif /* _MSC_VER && _MSC_VER >= 1400 */\n    handler = signal(sig, SIG_IGN);\n    if (handler != SIG_ERR)\n        signal(sig, handler);\n    return handler;\n#endif\n}\n\n/*\n * All of the code in this function must only use async-signal-safe functions,\n * listed at `man 7 signal` or\n * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.\n */\nPyOS_sighandler_t\nPyOS_setsig(int sig, PyOS_sighandler_t handler)\n{\n#ifdef HAVE_SIGACTION\n    /* Some code in Modules/signalmodule.c depends on sigaction() being\n     * used here if HAVE_SIGACTION is defined.  Fix that if this code\n     * changes to invalidate that assumption.\n     */\n    struct sigaction context, ocontext;\n    context.sa_handler = handler;\n    sigemptyset(&context.sa_mask);\n    /* Using SA_ONSTACK is friendlier to other C/C++/Golang-VM code that\n     * extension module or embedding code may use where tiny thread stacks\n     * are used.  https://bugs.python.org/issue43390 */\n    context.sa_flags = SA_ONSTACK;\n    if (sigaction(sig, &context, &ocontext) == -1)\n        return SIG_ERR;\n    return ocontext.sa_handler;\n#else\n    PyOS_sighandler_t oldhandler;\n    oldhandler = signal(sig, handler);\n#ifdef HAVE_SIGINTERRUPT\n    siginterrupt(sig, 1);\n#endif\n    return oldhandler;\n#endif\n}\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "PyMath.c",
    "content": "#include \"Python.h\"\n\n\n#ifdef HAVE_GCC_ASM_FOR_X87\n// Inline assembly for getting and setting the 387 FPU control word on\n// GCC/x86.\n#ifdef _Py_MEMORY_SANITIZER\n__attribute__((no_sanitize_memory))\n#endif\nunsigned short _Py_get_387controlword(void) {\n    unsigned short cw;\n    __asm__ __volatile__ (\"fnstcw %0\" : \"=m\" (cw));\n    return cw;\n}\n\nvoid _Py_set_387controlword(unsigned short cw) {\n    __asm__ __volatile__ (\"fldcw %0\" : : \"m\" (cw));\n}\n#endif  // HAVE_GCC_ASM_FOR_X87\n"
  },
  {
    "path": "PyState.c",
    "content": "\n/* Thread and interpreter state structures and their interfaces */\n\n#include \"Python.h\"\n#include \"pycore_ceval.h\"\n#include \"pycore_code.h\"          // stats\n#include \"pycore_dtoa.h\"          // _dtoa_state_INIT()\n#include \"pycore_frame.h\"\n#include \"pycore_initconfig.h\"\n#include \"pycore_object.h\"        // _PyType_InitCache()\n#include \"pycore_pyerrors.h\"\n#include \"pycore_pylifecycle.h\"\n#include \"pycore_pymem.h\"         // _PyMem_SetDefaultAllocator()\n#include \"pycore_pystate.h\"\n#include \"pycore_runtime_init.h\"  // _PyRuntimeState_INIT\n#include \"pycore_sysmodule.h\"\n\n/* --------------------------------------------------------------------------\nCAUTION\n\nAlways use PyMem_RawMalloc() and PyMem_RawFree() directly in this file.  A\nnumber of these functions are advertised as safe to call when the GIL isn't\nheld, and in a debug build Python redirects (e.g.) PyMem_NEW (etc) to Python's\ndebugging obmalloc functions.  Those aren't thread-safe (they rely on the GIL\nto avoid the expense of doing their own locking).\n-------------------------------------------------------------------------- */\n\n#ifdef HAVE_DLOPEN\n#ifdef HAVE_DLFCN_H\n#include <dlfcn.h>\n#endif\n#if !HAVE_DECL_RTLD_LAZY\n#define RTLD_LAZY 1\n#endif\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n/****************************************/\n/* helpers for the current thread state */\n/****************************************/\n\n// API for the current thread state is further down.\n\n/* \"current\" means one of:\n   - bound to the current OS thread\n   - holds the GIL\n */\n\n//-------------------------------------------------\n// a highly efficient lookup for the current thread\n//-------------------------------------------------\n\n/*\n   The stored thread state is set by PyThreadState_Swap().\n\n   For each of these functions, the GIL must be held by the current thread.\n */\n\n\n#ifdef HAVE_THREAD_LOCAL\n_Py_thread_local PyThreadState *_Py_tss_tstate = NULL;\n#endif\n\nstatic inline PyThreadState *\ncurrent_fast_get(_PyRuntimeState *Py_UNUSED(runtime))\n{\n#ifdef HAVE_THREAD_LOCAL\n    return _Py_tss_tstate;\n#else\n    // XXX Fall back to the PyThread_tss_*() API.\n#  error \"no supported thread-local variable storage classifier\"\n#endif\n}\n\nstatic inline void\ncurrent_fast_set(_PyRuntimeState *Py_UNUSED(runtime), PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n#ifdef HAVE_THREAD_LOCAL\n    _Py_tss_tstate = tstate;\n#else\n    // XXX Fall back to the PyThread_tss_*() API.\n#  error \"no supported thread-local variable storage classifier\"\n#endif\n}\n\nstatic inline void\ncurrent_fast_clear(_PyRuntimeState *Py_UNUSED(runtime))\n{\n#ifdef HAVE_THREAD_LOCAL\n    _Py_tss_tstate = NULL;\n#else\n    // XXX Fall back to the PyThread_tss_*() API.\n#  error \"no supported thread-local variable storage classifier\"\n#endif\n}\n\n#define tstate_verify_not_active(tstate) \\\n    if (tstate == current_fast_get((tstate)->interp->runtime)) { \\\n        _Py_FatalErrorFormat(__func__, \"tstate %p is still current\", tstate); \\\n    }\n\nPyThreadState *\n_PyThreadState_GetCurrent(void)\n{\n    return current_fast_get(&_PyRuntime);\n}\n\n\n//------------------------------------------------\n// the thread state bound to the current OS thread\n//------------------------------------------------\n\nstatic inline int\ntstate_tss_initialized(Py_tss_t *key)\n{\n    return PyThread_tss_is_created(key);\n}\n\nstatic inline int\ntstate_tss_init(Py_tss_t *key)\n{\n    assert(!tstate_tss_initialized(key));\n    return PyThread_tss_create(key);\n}\n\nstatic inline void\ntstate_tss_fini(Py_tss_t *key)\n{\n    assert(tstate_tss_initialized(key));\n    PyThread_tss_delete(key);\n}\n\nstatic inline PyThreadState *\ntstate_tss_get(Py_tss_t *key)\n{\n    assert(tstate_tss_initialized(key));\n    return (PyThreadState *)PyThread_tss_get(key);\n}\n\nstatic inline int\ntstate_tss_set(Py_tss_t *key, PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n    assert(tstate_tss_initialized(key));\n    return PyThread_tss_set(key, (void *)tstate);\n}\n\nstatic inline int\ntstate_tss_clear(Py_tss_t *key)\n{\n    assert(tstate_tss_initialized(key));\n    return PyThread_tss_set(key, (void *)NULL);\n}\n\n#ifdef HAVE_FORK\n/* Reset the TSS key - called by PyOS_AfterFork_Child().\n * This should not be necessary, but some - buggy - pthread implementations\n * don't reset TSS upon fork(), see issue #10517.\n */\nstatic PyStatus\ntstate_tss_reinit(Py_tss_t *key)\n{\n    if (!tstate_tss_initialized(key)) {\n        return _PyStatus_OK();\n    }\n    PyThreadState *tstate = tstate_tss_get(key);\n\n    tstate_tss_fini(key);\n    if (tstate_tss_init(key) != 0) {\n        return _PyStatus_NO_MEMORY();\n    }\n\n    /* If the thread had an associated auto thread state, reassociate it with\n     * the new key. */\n    if (tstate && tstate_tss_set(key, tstate) != 0) {\n        return _PyStatus_ERR(\"failed to re-set autoTSSkey\");\n    }\n    return _PyStatus_OK();\n}\n#endif\n\n\n/*\n   The stored thread state is set by bind_tstate() (AKA PyThreadState_Bind().\n\n   The GIL does no need to be held for these.\n  */\n\n#define gilstate_tss_initialized(runtime) \\\n    tstate_tss_initialized(&(runtime)->autoTSSkey)\n#define gilstate_tss_init(runtime) \\\n    tstate_tss_init(&(runtime)->autoTSSkey)\n#define gilstate_tss_fini(runtime) \\\n    tstate_tss_fini(&(runtime)->autoTSSkey)\n#define gilstate_tss_get(runtime) \\\n    tstate_tss_get(&(runtime)->autoTSSkey)\n#define _gilstate_tss_set(runtime, tstate) \\\n    tstate_tss_set(&(runtime)->autoTSSkey, tstate)\n#define _gilstate_tss_clear(runtime) \\\n    tstate_tss_clear(&(runtime)->autoTSSkey)\n#define gilstate_tss_reinit(runtime) \\\n    tstate_tss_reinit(&(runtime)->autoTSSkey)\n\nstatic inline void\ngilstate_tss_set(_PyRuntimeState *runtime, PyThreadState *tstate)\n{\n    assert(tstate != NULL && tstate->interp->runtime == runtime);\n    if (_gilstate_tss_set(runtime, tstate) != 0) {\n        Py_FatalError(\"failed to set current tstate (TSS)\");\n    }\n}\n\nstatic inline void\ngilstate_tss_clear(_PyRuntimeState *runtime)\n{\n    if (_gilstate_tss_clear(runtime) != 0) {\n        Py_FatalError(\"failed to clear current tstate (TSS)\");\n    }\n}\n\n\n#ifndef NDEBUG\nstatic inline int tstate_is_alive(PyThreadState *tstate);\n\nstatic inline int\ntstate_is_bound(PyThreadState *tstate)\n{\n    return tstate->_status.bound && !tstate->_status.unbound;\n}\n#endif  // !NDEBUG\n\nstatic void bind_gilstate_tstate(PyThreadState *);\nstatic void unbind_gilstate_tstate(PyThreadState *);\n\nstatic void\nbind_tstate(PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n    assert(tstate_is_alive(tstate) && !tstate->_status.bound);\n    assert(!tstate->_status.unbound);  // just in case\n    assert(!tstate->_status.bound_gilstate);\n    assert(tstate != gilstate_tss_get(tstate->interp->runtime));\n    assert(!tstate->_status.active);\n    assert(tstate->thread_id == 0);\n    assert(tstate->native_thread_id == 0);\n\n    // Currently we don't necessarily store the thread state\n    // in thread-local storage (e.g. per-interpreter).\n\n    tstate->thread_id = PyThread_get_thread_ident();\n#ifdef PY_HAVE_THREAD_NATIVE_ID\n    tstate->native_thread_id = PyThread_get_thread_native_id();\n#endif\n\n    tstate->_status.bound = 1;\n}\n\nstatic void\nunbind_tstate(PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n    // XXX assert(tstate_is_alive(tstate));\n    assert(tstate_is_bound(tstate));\n    // XXX assert(!tstate->_status.active);\n    assert(tstate->thread_id > 0);\n#ifdef PY_HAVE_THREAD_NATIVE_ID\n    assert(tstate->native_thread_id > 0);\n#endif\n\n    // We leave thread_id and native_thread_id alone\n    // since they can be useful for debugging.\n    // Check the `_status` field to know if these values\n    // are still valid.\n\n    // We leave tstate->_status.bound set to 1\n    // to indicate it was previously bound.\n    tstate->_status.unbound = 1;\n}\n\n\n/* Stick the thread state for this thread in thread specific storage.\n\n   When a thread state is created for a thread by some mechanism\n   other than PyGILState_Ensure(), it's important that the GILState\n   machinery knows about it so it doesn't try to create another\n   thread state for the thread.\n   (This is a better fix for SF bug #1010677 than the first one attempted.)\n\n   The only situation where you can legitimately have more than one\n   thread state for an OS level thread is when there are multiple\n   interpreters.\n\n   Before 3.12, the PyGILState_*() APIs didn't work with multiple\n   interpreters (see bpo-10915 and bpo-15751), so this function used\n   to set TSS only once.  Thus, the first thread state created for that\n   given OS level thread would \"win\", which seemed reasonable behaviour.\n*/\n\nstatic void\nbind_gilstate_tstate(PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n    assert(tstate_is_alive(tstate));\n    assert(tstate_is_bound(tstate));\n    // XXX assert(!tstate->_status.active);\n    assert(!tstate->_status.bound_gilstate);\n\n    _PyRuntimeState *runtime = tstate->interp->runtime;\n    PyThreadState *tcur = gilstate_tss_get(runtime);\n    assert(tstate != tcur);\n\n    if (tcur != NULL) {\n        tcur->_status.bound_gilstate = 0;\n    }\n    gilstate_tss_set(runtime, tstate);\n    tstate->_status.bound_gilstate = 1;\n}\n\nstatic void\nunbind_gilstate_tstate(PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n    // XXX assert(tstate_is_alive(tstate));\n    assert(tstate_is_bound(tstate));\n    // XXX assert(!tstate->_status.active);\n    assert(tstate->_status.bound_gilstate);\n    assert(tstate == gilstate_tss_get(tstate->interp->runtime));\n\n    gilstate_tss_clear(tstate->interp->runtime);\n    tstate->_status.bound_gilstate = 0;\n}\n\n\n//----------------------------------------------\n// the thread state that currently holds the GIL\n//----------------------------------------------\n\n/* This is not exported, as it is not reliable!  It can only\n   ever be compared to the state for the *current* thread.\n   * If not equal, then it doesn't matter that the actual\n     value may change immediately after comparison, as it can't\n     possibly change to the current thread's state.\n   * If equal, then the current thread holds the lock, so the value can't\n     change until we yield the lock.\n*/\nstatic int\nholds_gil(PyThreadState *tstate)\n{\n    // XXX Fall back to tstate->interp->runtime->ceval.gil.last_holder\n    // (and tstate->interp->runtime->ceval.gil.locked).\n    assert(tstate != NULL);\n    _PyRuntimeState *runtime = tstate->interp->runtime;\n    /* Must be the tstate for this thread */\n    assert(tstate == gilstate_tss_get(runtime));\n    return tstate == current_fast_get(runtime);\n}\n\n\n/****************************/\n/* the global runtime state */\n/****************************/\n\n//----------\n// lifecycle\n//----------\n\n/* Suppress deprecation warning for PyBytesObject.ob_shash */\n_Py_COMP_DIAG_PUSH\n_Py_COMP_DIAG_IGNORE_DEPR_DECLS\n/* We use \"initial\" if the runtime gets re-used\n   (e.g. Py_Finalize() followed by Py_Initialize().\n   Note that we initialize \"initial\" relative to _PyRuntime,\n   to ensure pre-initialized pointers point to the active\n   runtime state (and not \"initial\"). */\nstatic const _PyRuntimeState initial = _PyRuntimeState_INIT(_PyRuntime);\n_Py_COMP_DIAG_POP\n\n#define NUMLOCKS 5\n\nstatic int\nalloc_for_runtime(PyThread_type_lock locks[NUMLOCKS])\n{\n    /* Force default allocator, since _PyRuntimeState_Fini() must\n       use the same allocator than this function. */\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    for (int i = 0; i < NUMLOCKS; i++) {\n        PyThread_type_lock lock = PyThread_allocate_lock();\n        if (lock == NULL) {\n            for (int j = 0; j < i; j++) {\n                PyThread_free_lock(locks[j]);\n                locks[j] = NULL;\n            }\n            break;\n        }\n        locks[i] = lock;\n    }\n\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n    return 0;\n}\n\nstatic void\ninit_runtime(_PyRuntimeState *runtime,\n             void *open_code_hook, void *open_code_userdata,\n             _Py_AuditHookEntry *audit_hook_head,\n             Py_ssize_t unicode_next_index,\n             PyThread_type_lock locks[NUMLOCKS])\n{\n    if (runtime->_initialized) {\n        Py_FatalError(\"runtime already initialized\");\n    }\n    assert(!runtime->preinitializing &&\n           !runtime->preinitialized &&\n           !runtime->core_initialized &&\n           !runtime->initialized);\n\n    runtime->open_code_hook = open_code_hook;\n    runtime->open_code_userdata = open_code_userdata;\n    runtime->audit_hook_head = audit_hook_head;\n\n    PyPreConfig_InitPythonConfig(&runtime->preconfig);\n\n    PyThread_type_lock *lockptrs[NUMLOCKS] = {\n        &runtime->interpreters.mutex,\n        &runtime->xidregistry.mutex,\n        &runtime->getargs.mutex,\n        &runtime->unicode_state.ids.lock,\n        &runtime->imports.extensions.mutex,\n    };\n    for (int i = 0; i < NUMLOCKS; i++) {\n        assert(locks[i] != NULL);\n        *lockptrs[i] = locks[i];\n    }\n\n    // Set it to the ID of the main thread of the main interpreter.\n    runtime->main_thread = PyThread_get_thread_ident();\n\n    runtime->unicode_state.ids.next_index = unicode_next_index;\n\n    runtime->_initialized = 1;\n}\n\nPyStatus\n_PyRuntimeState_Init(_PyRuntimeState *runtime)\n{\n    /* We preserve the hook across init, because there is\n       currently no public API to set it between runtime\n       initialization and interpreter initialization. */\n    void *open_code_hook = runtime->open_code_hook;\n    void *open_code_userdata = runtime->open_code_userdata;\n    _Py_AuditHookEntry *audit_hook_head = runtime->audit_hook_head;\n    // bpo-42882: Preserve next_index value if Py_Initialize()/Py_Finalize()\n    // is called multiple times.\n    Py_ssize_t unicode_next_index = runtime->unicode_state.ids.next_index;\n\n    PyThread_type_lock locks[NUMLOCKS];\n    if (alloc_for_runtime(locks) != 0) {\n        return _PyStatus_NO_MEMORY();\n    }\n\n    if (runtime->_initialized) {\n        // Py_Initialize() must be running again.\n        // Reset to _PyRuntimeState_INIT.\n        memcpy(runtime, &initial, sizeof(*runtime));\n    }\n\n    if (gilstate_tss_init(runtime) != 0) {\n        _PyRuntimeState_Fini(runtime);\n        return _PyStatus_NO_MEMORY();\n    }\n\n    if (PyThread_tss_create(&runtime->trashTSSkey) != 0) {\n        _PyRuntimeState_Fini(runtime);\n        return _PyStatus_NO_MEMORY();\n    }\n\n    init_runtime(runtime, open_code_hook, open_code_userdata, audit_hook_head,\n                 unicode_next_index, locks);\n\n    return _PyStatus_OK();\n}\n\nvoid\n_PyRuntimeState_Fini(_PyRuntimeState *runtime)\n{\n#ifdef Py_REF_DEBUG\n    /* The count is cleared by _Py_FinalizeRefTotal(). */\n    assert(runtime->object_state.interpreter_leaks == 0);\n#endif\n\n    if (gilstate_tss_initialized(runtime)) {\n        gilstate_tss_fini(runtime);\n    }\n\n    if (PyThread_tss_is_created(&runtime->trashTSSkey)) {\n        PyThread_tss_delete(&runtime->trashTSSkey);\n    }\n\n    /* Force the allocator used by _PyRuntimeState_Init(). */\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n#define FREE_LOCK(LOCK) \\\n    if (LOCK != NULL) { \\\n        PyThread_free_lock(LOCK); \\\n        LOCK = NULL; \\\n    }\n\n    PyThread_type_lock *lockptrs[NUMLOCKS] = {\n        &runtime->interpreters.mutex,\n        &runtime->xidregistry.mutex,\n        &runtime->getargs.mutex,\n        &runtime->unicode_state.ids.lock,\n        &runtime->imports.extensions.mutex,\n    };\n    for (int i = 0; i < NUMLOCKS; i++) {\n        FREE_LOCK(*lockptrs[i]);\n    }\n\n#undef FREE_LOCK\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n}\n\n#ifdef HAVE_FORK\n/* This function is called from PyOS_AfterFork_Child to ensure that\n   newly created child processes do not share locks with the parent. */\nPyStatus\n_PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)\n{\n    // This was initially set in _PyRuntimeState_Init().\n    runtime->main_thread = PyThread_get_thread_ident();\n\n    /* Force default allocator, since _PyRuntimeState_Fini() must\n       use the same allocator than this function. */\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    PyThread_type_lock *lockptrs[NUMLOCKS] = {\n        &runtime->interpreters.mutex,\n        &runtime->xidregistry.mutex,\n        &runtime->getargs.mutex,\n        &runtime->unicode_state.ids.lock,\n        &runtime->imports.extensions.mutex,\n    };\n    int reinit_err = 0;\n    for (int i = 0; i < NUMLOCKS; i++) {\n        reinit_err += _PyThread_at_fork_reinit(lockptrs[i]);\n    }\n\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    /* bpo-42540: id_mutex is freed by _PyInterpreterState_Delete, which does\n     * not force the default allocator. */\n    reinit_err += _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex);\n\n    if (reinit_err < 0) {\n        return _PyStatus_ERR(\"Failed to reinitialize runtime locks\");\n    }\n\n    PyStatus status = gilstate_tss_reinit(runtime);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    if (PyThread_tss_is_created(&runtime->trashTSSkey)) {\n        PyThread_tss_delete(&runtime->trashTSSkey);\n    }\n    if (PyThread_tss_create(&runtime->trashTSSkey) != 0) {\n        return _PyStatus_NO_MEMORY();\n    }\n\n    return _PyStatus_OK();\n}\n#endif\n\n\n/*************************************/\n/* the per-interpreter runtime state */\n/*************************************/\n\n//----------\n// lifecycle\n//----------\n\n/* Calling this indicates that the runtime is ready to create interpreters. */\n\nPyStatus\n_PyInterpreterState_Enable(_PyRuntimeState *runtime)\n{\n    struct pyinterpreters *interpreters = &runtime->interpreters;\n    interpreters->next_id = 0;\n\n    /* Py_Finalize() calls _PyRuntimeState_Fini() which clears the mutex.\n       Create a new mutex if needed. */\n    if (interpreters->mutex == NULL) {\n        /* Force default allocator, since _PyRuntimeState_Fini() must\n           use the same allocator than this function. */\n        PyMemAllocatorEx old_alloc;\n        _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n        interpreters->mutex = PyThread_allocate_lock();\n\n        PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n        if (interpreters->mutex == NULL) {\n            return _PyStatus_ERR(\"Can't initialize threads for interpreter\");\n        }\n    }\n\n    return _PyStatus_OK();\n}\n\n\nstatic PyInterpreterState *\nalloc_interpreter(void)\n{\n    return PyMem_RawCalloc(1, sizeof(PyInterpreterState));\n}\n\nstatic void\nfree_interpreter(PyInterpreterState *interp)\n{\n    // The main interpreter is statically allocated so\n    // should not be freed.\n    if (interp != &_PyRuntime._main_interpreter) {\n        PyMem_RawFree(interp);\n    }\n}\n\n/* Get the interpreter state to a minimal consistent state.\n   Further init happens in pylifecycle.c before it can be used.\n   All fields not initialized here are expected to be zeroed out,\n   e.g. by PyMem_RawCalloc() or memset(), or otherwise pre-initialized.\n   The runtime state is not manipulated.  Instead it is assumed that\n   the interpreter is getting added to the runtime.\n\n   Note that the main interpreter was statically initialized as part\n   of the runtime and most state is already set properly.  That leaves\n   a small number of fields to initialize dynamically, as well as some\n   that are initialized lazily.\n\n   For subinterpreters we memcpy() the main interpreter in\n   PyInterpreterState_New(), leaving it in the same mostly-initialized\n   state.  The only difference is that the interpreter has some\n   self-referential state that is statically initializexd to the\n   main interpreter.  We fix those fields here, in addition\n   to the other dynamically initialized fields.\n  */\nstatic void\ninit_interpreter(PyInterpreterState *interp,\n                 _PyRuntimeState *runtime, int64_t id,\n                 PyInterpreterState *next,\n                 PyThread_type_lock pending_lock)\n{\n    if (interp->_initialized) {\n        Py_FatalError(\"interpreter already initialized\");\n    }\n\n    assert(runtime != NULL);\n    interp->runtime = runtime;\n\n    assert(id > 0 || (id == 0 && interp == runtime->interpreters.main));\n    interp->id = id;\n\n    assert(runtime->interpreters.head == interp);\n    assert(next != NULL || (interp == runtime->interpreters.main));\n    interp->next = next;\n\n    /* Initialize obmalloc, but only for subinterpreters,\n       since the main interpreter is initialized statically. */\n    if (interp != &runtime->_main_interpreter) {\n        poolp temp[OBMALLOC_USED_POOLS_SIZE] = \\\n                _obmalloc_pools_INIT(interp->obmalloc.pools);\n        memcpy(&interp->obmalloc.pools.used, temp, sizeof(temp));\n    }\n\n    _PyEval_InitState(interp, pending_lock);\n    _PyGC_InitState(&interp->gc);\n    PyConfig_InitPythonConfig(&interp->config);\n    _PyType_InitCache(interp);\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        interp->monitors.tools[i] = 0;\n    }\n    for (int t = 0; t < PY_MONITORING_TOOL_IDS; t++) {\n        for (int e = 0; e < PY_MONITORING_EVENTS; e++) {\n            interp->monitoring_callables[t][e] = NULL;\n\n        }\n    }\n    interp->sys_profile_initialized = false;\n    interp->sys_trace_initialized = false;\n    if (interp != &runtime->_main_interpreter) {\n        /* Fix the self-referential, statically initialized fields. */\n        interp->dtoa = (struct _dtoa_state)_dtoa_state_INIT(interp);\n    }\n    interp->f_opcode_trace_set = false;\n    interp->_initialized = 1;\n}\n\nPyInterpreterState *\nPyInterpreterState_New(void)\n{\n    PyInterpreterState *interp;\n    _PyRuntimeState *runtime = &_PyRuntime;\n    PyThreadState *tstate = current_fast_get(runtime);\n\n    /* tstate is NULL when Py_InitializeFromConfig() calls\n       PyInterpreterState_New() to create the main interpreter. */\n    if (_PySys_Audit(tstate, \"cpython.PyInterpreterState_New\", NULL) < 0) {\n        return NULL;\n    }\n\n    PyThread_type_lock pending_lock = PyThread_allocate_lock();\n    if (pending_lock == NULL) {\n        if (tstate != NULL) {\n            _PyErr_NoMemory(tstate);\n        }\n        return NULL;\n    }\n\n    /* Don't get runtime from tstate since tstate can be NULL. */\n    struct pyinterpreters *interpreters = &runtime->interpreters;\n\n    /* We completely serialize creation of multiple interpreters, since\n       it simplifies things here and blocking concurrent calls isn't a problem.\n       Regardless, we must fully block subinterpreter creation until\n       after the main interpreter is created. */\n    HEAD_LOCK(runtime);\n\n    int64_t id = interpreters->next_id;\n    interpreters->next_id += 1;\n\n    // Allocate the interpreter and add it to the runtime state.\n    PyInterpreterState *old_head = interpreters->head;\n    if (old_head == NULL) {\n        // We are creating the main interpreter.\n        assert(interpreters->main == NULL);\n        assert(id == 0);\n\n        interp = &runtime->_main_interpreter;\n        assert(interp->id == 0);\n        assert(interp->next == NULL);\n\n        interpreters->main = interp;\n    }\n    else {\n        assert(interpreters->main != NULL);\n        assert(id != 0);\n\n        interp = alloc_interpreter();\n        if (interp == NULL) {\n            goto error;\n        }\n        // Set to _PyInterpreterState_INIT.\n        memcpy(interp, &initial._main_interpreter,\n               sizeof(*interp));\n\n        if (id < 0) {\n            /* overflow or Py_Initialize() not called yet! */\n            if (tstate != NULL) {\n                _PyErr_SetString(tstate, PyExc_RuntimeError,\n                                 \"failed to get an interpreter ID\");\n            }\n            goto error;\n        }\n    }\n    interpreters->head = interp;\n\n    init_interpreter(interp, runtime, id, old_head, pending_lock);\n\n    HEAD_UNLOCK(runtime);\n    return interp;\n\nerror:\n    HEAD_UNLOCK(runtime);\n\n    PyThread_free_lock(pending_lock);\n    if (interp != NULL) {\n        free_interpreter(interp);\n    }\n    return NULL;\n}\n\n\nstatic void\ninterpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)\n{\n    assert(interp != NULL);\n    assert(tstate != NULL);\n    _PyRuntimeState *runtime = interp->runtime;\n\n    /* XXX Conditions we need to enforce:\n\n       * the GIL must be held by the current thread\n       * tstate must be the \"current\" thread state (current_fast_get())\n       * tstate->interp must be interp\n       * for the main interpreter, tstate must be the main thread\n     */\n    // XXX Ideally, we would not rely on any thread state in this function\n    // (and we would drop the \"tstate\" argument).\n\n    if (_PySys_Audit(tstate, \"cpython.PyInterpreterState_Clear\", NULL) < 0) {\n        _PyErr_Clear(tstate);\n    }\n\n    // Clear the current/main thread state last.\n    HEAD_LOCK(runtime);\n    PyThreadState *p = interp->threads.head;\n    HEAD_UNLOCK(runtime);\n    while (p != NULL) {\n        // See https://github.com/python/cpython/issues/102126\n        // Must be called without HEAD_LOCK held as it can deadlock\n        // if any finalizer tries to acquire that lock.\n        PyThreadState_Clear(p);\n        HEAD_LOCK(runtime);\n        p = p->next;\n        HEAD_UNLOCK(runtime);\n    }\n\n    /* It is possible that any of the objects below have a finalizer\n       that runs Python code or otherwise relies on a thread state\n       or even the interpreter state.  For now we trust that isn't\n       a problem.\n     */\n    // XXX Make sure we properly deal with problematic finalizers.\n\n    Py_CLEAR(interp->audit_hooks);\n\n    for (int i = 0; i < PY_MONITORING_UNGROUPED_EVENTS; i++) {\n        interp->monitors.tools[i] = 0;\n    }\n    for (int t = 0; t < PY_MONITORING_TOOL_IDS; t++) {\n        for (int e = 0; e < PY_MONITORING_EVENTS; e++) {\n            Py_CLEAR(interp->monitoring_callables[t][e]);\n        }\n    }\n    interp->sys_profile_initialized = false;\n    interp->sys_trace_initialized = false;\n    for (int t = 0; t < PY_MONITORING_TOOL_IDS; t++) {\n        Py_CLEAR(interp->monitoring_tool_names[t]);\n    }\n\n    PyConfig_Clear(&interp->config);\n    Py_CLEAR(interp->codec_search_path);\n    Py_CLEAR(interp->codec_search_cache);\n    Py_CLEAR(interp->codec_error_registry);\n\n    assert(interp->imports.modules == NULL);\n    assert(interp->imports.modules_by_index == NULL);\n    assert(interp->imports.importlib == NULL);\n    assert(interp->imports.import_func == NULL);\n\n    Py_CLEAR(interp->sysdict_copy);\n    Py_CLEAR(interp->builtins_copy);\n    Py_CLEAR(interp->dict);\n#ifdef HAVE_FORK\n    Py_CLEAR(interp->before_forkers);\n    Py_CLEAR(interp->after_forkers_parent);\n    Py_CLEAR(interp->after_forkers_child);\n#endif\n\n    _PyAST_Fini(interp);\n    _PyWarnings_Fini(interp);\n    _PyAtExit_Fini(interp);\n\n    // All Python types must be destroyed before the last GC collection. Python\n    // types create a reference cycle to themselves in their in their\n    // PyTypeObject.tp_mro member (the tuple contains the type).\n\n    /* Last garbage collection on this interpreter */\n    _PyGC_CollectNoFail(tstate);\n    _PyGC_Fini(interp);\n\n    /* We don't clear sysdict and builtins until the end of this function.\n       Because clearing other attributes can execute arbitrary Python code\n       which requires sysdict and builtins. */\n    PyDict_Clear(interp->sysdict);\n    PyDict_Clear(interp->builtins);\n    Py_CLEAR(interp->sysdict);\n    Py_CLEAR(interp->builtins);\n    Py_CLEAR(interp->interpreter_trampoline);\n\n    for (int i=0; i < DICT_MAX_WATCHERS; i++) {\n        interp->dict_state.watchers[i] = NULL;\n    }\n\n    for (int i=0; i < TYPE_MAX_WATCHERS; i++) {\n        interp->type_watchers[i] = NULL;\n    }\n\n    for (int i=0; i < FUNC_MAX_WATCHERS; i++) {\n        interp->func_watchers[i] = NULL;\n    }\n    interp->active_func_watchers = 0;\n\n    for (int i=0; i < CODE_MAX_WATCHERS; i++) {\n        interp->code_watchers[i] = NULL;\n    }\n    interp->active_code_watchers = 0;\n    interp->f_opcode_trace_set = false;\n    // XXX Once we have one allocator per interpreter (i.e.\n    // per-interpreter GC) we must ensure that all of the interpreter's\n    // objects have been cleaned up at the point.\n}\n\n\nvoid\nPyInterpreterState_Clear(PyInterpreterState *interp)\n{\n    // Use the current Python thread state to call audit hooks and to collect\n    // garbage. It can be different than the current Python thread state\n    // of 'interp'.\n    PyThreadState *current_tstate = current_fast_get(interp->runtime);\n    _PyImport_ClearCore(interp);\n    interpreter_clear(interp, current_tstate);\n}\n\n\nvoid\n_PyInterpreterState_Clear(PyThreadState *tstate)\n{\n    _PyImport_ClearCore(tstate->interp);\n    interpreter_clear(tstate->interp, tstate);\n}\n\n\nstatic void zapthreads(PyInterpreterState *interp);\n\nvoid\nPyInterpreterState_Delete(PyInterpreterState *interp)\n{\n    _PyRuntimeState *runtime = interp->runtime;\n    struct pyinterpreters *interpreters = &runtime->interpreters;\n\n    // XXX Clearing the \"current\" thread state should happen before\n    // we start finalizing the interpreter (or the current thread state).\n    PyThreadState *tcur = current_fast_get(runtime);\n    if (tcur != NULL && interp == tcur->interp) {\n        /* Unset current thread.  After this, many C API calls become crashy. */\n        _PyThreadState_Swap(runtime, NULL);\n    }\n\n    zapthreads(interp);\n\n    _PyEval_FiniState(&interp->ceval);\n\n    // XXX These two calls should be done at the end of clear_interpreter(),\n    // but currently some objects get decref'ed after that.\n#ifdef Py_REF_DEBUG\n    _PyInterpreterState_FinalizeRefTotal(interp);\n#endif\n    _PyInterpreterState_FinalizeAllocatedBlocks(interp);\n\n    HEAD_LOCK(runtime);\n    PyInterpreterState **p;\n    for (p = &interpreters->head; ; p = &(*p)->next) {\n        if (*p == NULL) {\n            Py_FatalError(\"NULL interpreter\");\n        }\n        if (*p == interp) {\n            break;\n        }\n    }\n    if (interp->threads.head != NULL) {\n        Py_FatalError(\"remaining threads\");\n    }\n    *p = interp->next;\n\n    if (interpreters->main == interp) {\n        interpreters->main = NULL;\n        if (interpreters->head != NULL) {\n            Py_FatalError(\"remaining subinterpreters\");\n        }\n    }\n    HEAD_UNLOCK(runtime);\n\n    if (interp->id_mutex != NULL) {\n        PyThread_free_lock(interp->id_mutex);\n    }\n    free_interpreter(interp);\n}\n\n\n#ifdef HAVE_FORK\n/*\n * Delete all interpreter states except the main interpreter.  If there\n * is a current interpreter state, it *must* be the main interpreter.\n */\nPyStatus\n_PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)\n{\n    struct pyinterpreters *interpreters = &runtime->interpreters;\n\n    PyThreadState *tstate = _PyThreadState_Swap(runtime, NULL);\n    if (tstate != NULL && tstate->interp != interpreters->main) {\n        return _PyStatus_ERR(\"not main interpreter\");\n    }\n\n    HEAD_LOCK(runtime);\n    PyInterpreterState *interp = interpreters->head;\n    interpreters->head = NULL;\n    while (interp != NULL) {\n        if (interp == interpreters->main) {\n            interpreters->main->next = NULL;\n            interpreters->head = interp;\n            interp = interp->next;\n            continue;\n        }\n\n        // XXX Won't this fail since PyInterpreterState_Clear() requires\n        // the \"current\" tstate to be set?\n        PyInterpreterState_Clear(interp);  // XXX must activate?\n        zapthreads(interp);\n        if (interp->id_mutex != NULL) {\n            PyThread_free_lock(interp->id_mutex);\n        }\n        PyInterpreterState *prev_interp = interp;\n        interp = interp->next;\n        free_interpreter(prev_interp);\n    }\n    HEAD_UNLOCK(runtime);\n\n    if (interpreters->head == NULL) {\n        return _PyStatus_ERR(\"missing main interpreter\");\n    }\n    _PyThreadState_Swap(runtime, tstate);\n    return _PyStatus_OK();\n}\n#endif\n\n\n//----------\n// accessors\n//----------\n\nint64_t\nPyInterpreterState_GetID(PyInterpreterState *interp)\n{\n    if (interp == NULL) {\n        PyErr_SetString(PyExc_RuntimeError, \"no interpreter provided\");\n        return -1;\n    }\n    return interp->id;\n}\n\n\nint\n_PyInterpreterState_IDInitref(PyInterpreterState *interp)\n{\n    if (interp->id_mutex != NULL) {\n        return 0;\n    }\n    interp->id_mutex = PyThread_allocate_lock();\n    if (interp->id_mutex == NULL) {\n        PyErr_SetString(PyExc_RuntimeError,\n                        \"failed to create init interpreter ID mutex\");\n        return -1;\n    }\n    interp->id_refcount = 0;\n    return 0;\n}\n\n\nint\n_PyInterpreterState_IDIncref(PyInterpreterState *interp)\n{\n    if (_PyInterpreterState_IDInitref(interp) < 0) {\n        return -1;\n    }\n\n    PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK);\n    interp->id_refcount += 1;\n    PyThread_release_lock(interp->id_mutex);\n    return 0;\n}\n\n\nvoid\n_PyInterpreterState_IDDecref(PyInterpreterState *interp)\n{\n    assert(interp->id_mutex != NULL);\n    _PyRuntimeState *runtime = interp->runtime;\n\n    PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK);\n    assert(interp->id_refcount != 0);\n    interp->id_refcount -= 1;\n    int64_t refcount = interp->id_refcount;\n    PyThread_release_lock(interp->id_mutex);\n\n    if (refcount == 0 && interp->requires_idref) {\n        // XXX Using the \"head\" thread isn't strictly correct.\n        PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);\n        // XXX Possible GILState issues?\n        PyThreadState *save_tstate = _PyThreadState_Swap(runtime, tstate);\n        Py_EndInterpreter(tstate);\n        _PyThreadState_Swap(runtime, save_tstate);\n    }\n}\n\nint\n_PyInterpreterState_RequiresIDRef(PyInterpreterState *interp)\n{\n    return interp->requires_idref;\n}\n\nvoid\n_PyInterpreterState_RequireIDRef(PyInterpreterState *interp, int required)\n{\n    interp->requires_idref = required ? 1 : 0;\n}\n\nPyObject *\n_PyInterpreterState_GetMainModule(PyInterpreterState *interp)\n{\n    PyObject *modules = _PyImport_GetModules(interp);\n    if (modules == NULL) {\n        PyErr_SetString(PyExc_RuntimeError, \"interpreter not initialized\");\n        return NULL;\n    }\n    return PyMapping_GetItemString(modules, \"__main__\");\n}\n\nPyObject *\nPyInterpreterState_GetDict(PyInterpreterState *interp)\n{\n    if (interp->dict == NULL) {\n        interp->dict = PyDict_New();\n        if (interp->dict == NULL) {\n            PyErr_Clear();\n        }\n    }\n    /* Returning NULL means no per-interpreter dict is available. */\n    return interp->dict;\n}\n\n\n//-----------------------------\n// look up an interpreter state\n//-----------------------------\n\n/* Return the interpreter associated with the current OS thread.\n\n   The GIL must be held.\n  */\n\nPyInterpreterState *\nPyInterpreterState_Get(void)\n{\n    PyThreadState *tstate = current_fast_get(&_PyRuntime);\n    _Py_EnsureTstateNotNULL(tstate);\n    PyInterpreterState *interp = tstate->interp;\n    if (interp == NULL) {\n        Py_FatalError(\"no current interpreter\");\n    }\n    return interp;\n}\n\n\nstatic PyInterpreterState *\ninterp_look_up_id(_PyRuntimeState *runtime, int64_t requested_id)\n{\n    PyInterpreterState *interp = runtime->interpreters.head;\n    while (interp != NULL) {\n        int64_t id = PyInterpreterState_GetID(interp);\n        if (id < 0) {\n            return NULL;\n        }\n        if (requested_id == id) {\n            return interp;\n        }\n        interp = PyInterpreterState_Next(interp);\n    }\n    return NULL;\n}\n\n/* Return the interpreter state with the given ID.\n\n   Fail with RuntimeError if the interpreter is not found. */\n\nPyInterpreterState *\n_PyInterpreterState_LookUpID(int64_t requested_id)\n{\n    PyInterpreterState *interp = NULL;\n    if (requested_id >= 0) {\n        _PyRuntimeState *runtime = &_PyRuntime;\n        HEAD_LOCK(runtime);\n        interp = interp_look_up_id(runtime, requested_id);\n        HEAD_UNLOCK(runtime);\n    }\n    if (interp == NULL && !PyErr_Occurred()) {\n        PyErr_Format(PyExc_RuntimeError,\n                     \"unrecognized interpreter ID %lld\", requested_id);\n    }\n    return interp;\n}\n\n\n/********************************/\n/* the per-thread runtime state */\n/********************************/\n\n#ifndef NDEBUG\nstatic inline int\ntstate_is_alive(PyThreadState *tstate)\n{\n    return (tstate->_status.initialized &&\n            !tstate->_status.finalized &&\n            !tstate->_status.cleared &&\n            !tstate->_status.finalizing);\n}\n#endif\n\n\n//----------\n// lifecycle\n//----------\n\n/* Minimum size of data stack chunk */\n#define DATA_STACK_CHUNK_SIZE (16*1024)\n\nstatic _PyStackChunk*\nallocate_chunk(int size_in_bytes, _PyStackChunk* previous)\n{\n    assert(size_in_bytes % sizeof(PyObject **) == 0);\n    _PyStackChunk *res = _PyObject_VirtualAlloc(size_in_bytes);\n    if (res == NULL) {\n        return NULL;\n    }\n    res->previous = previous;\n    res->size = size_in_bytes;\n    res->top = 0;\n    return res;\n}\n\nstatic PyThreadState *\nalloc_threadstate(void)\n{\n    return PyMem_RawCalloc(1, sizeof(PyThreadState));\n}\n\nstatic void\nfree_threadstate(PyThreadState *tstate)\n{\n    // The initial thread state of the interpreter is allocated\n    // as part of the interpreter state so should not be freed.\n    if (tstate != &tstate->interp->_initial_thread) {\n        PyMem_RawFree(tstate);\n    }\n}\n\n/* Get the thread state to a minimal consistent state.\n   Further init happens in pylifecycle.c before it can be used.\n   All fields not initialized here are expected to be zeroed out,\n   e.g. by PyMem_RawCalloc() or memset(), or otherwise pre-initialized.\n   The interpreter state is not manipulated.  Instead it is assumed that\n   the thread is getting added to the interpreter.\n  */\n\nstatic void\ninit_threadstate(PyThreadState *tstate,\n                 PyInterpreterState *interp, uint64_t id)\n{\n    if (tstate->_status.initialized) {\n        Py_FatalError(\"thread state already initialized\");\n    }\n\n    assert(interp != NULL);\n    tstate->interp = interp;\n\n    // next/prev are set in add_threadstate().\n    assert(tstate->next == NULL);\n    assert(tstate->prev == NULL);\n\n    assert(id > 0);\n    tstate->id = id;\n\n    // thread_id and native_thread_id are set in bind_tstate().\n\n    tstate->py_recursion_limit = interp->ceval.recursion_limit,\n    tstate->py_recursion_remaining = interp->ceval.recursion_limit,\n    tstate->c_recursion_remaining = C_RECURSION_LIMIT;\n\n    tstate->exc_info = &tstate->exc_state;\n\n    // PyGILState_Release must not try to delete this thread state.\n    // This is cleared when PyGILState_Ensure() creates the thread state.\n    tstate->gilstate_counter = 1;\n\n    tstate->cframe = &tstate->root_cframe;\n    tstate->datastack_chunk = NULL;\n    tstate->datastack_top = NULL;\n    tstate->datastack_limit = NULL;\n    tstate->what_event = -1;\n\n    tstate->_status.initialized = 1;\n}\n\nstatic void\nadd_threadstate(PyInterpreterState *interp, PyThreadState *tstate,\n                PyThreadState *next)\n{\n    assert(interp->threads.head != tstate);\n    assert((next != NULL && tstate->id != 1) ||\n           (next == NULL && tstate->id == 1));\n    if (next != NULL) {\n        assert(next->prev == NULL || next->prev == tstate);\n        next->prev = tstate;\n    }\n    tstate->next = next;\n    assert(tstate->prev == NULL);\n    interp->threads.head = tstate;\n}\n\nstatic PyThreadState *\nnew_threadstate(PyInterpreterState *interp)\n{\n    PyThreadState *tstate;\n    _PyRuntimeState *runtime = interp->runtime;\n    // We don't need to allocate a thread state for the main interpreter\n    // (the common case), but doing it later for the other case revealed a\n    // reentrancy problem (deadlock).  So for now we always allocate before\n    // taking the interpreters lock.  See GH-96071.\n    PyThreadState *new_tstate = alloc_threadstate();\n    int used_newtstate;\n    if (new_tstate == NULL) {\n        return NULL;\n    }\n    /* We serialize concurrent creation to protect global state. */\n    HEAD_LOCK(runtime);\n\n    interp->threads.next_unique_id += 1;\n    uint64_t id = interp->threads.next_unique_id;\n\n    // Allocate the thread state and add it to the interpreter.\n    PyThreadState *old_head = interp->threads.head;\n    if (old_head == NULL) {\n        // It's the interpreter's initial thread state.\n        assert(id == 1);\n        used_newtstate = 0;\n        tstate = &interp->_initial_thread;\n    }\n    else {\n        // Every valid interpreter must have at least one thread.\n        assert(id > 1);\n        assert(old_head->prev == NULL);\n        used_newtstate = 1;\n        tstate = new_tstate;\n        // Set to _PyThreadState_INIT.\n        memcpy(tstate,\n               &initial._main_interpreter._initial_thread,\n               sizeof(*tstate));\n    }\n\n    init_threadstate(tstate, interp, id);\n    add_threadstate(interp, tstate, old_head);\n\n    HEAD_UNLOCK(runtime);\n    if (!used_newtstate) {\n        // Must be called with lock unlocked to avoid re-entrancy deadlock.\n        PyMem_RawFree(new_tstate);\n    }\n    return tstate;\n}\n\nPyThreadState *\nPyThreadState_New(PyInterpreterState *interp)\n{\n    PyThreadState *tstate = new_threadstate(interp);\n    if (tstate) {\n        bind_tstate(tstate);\n        // This makes sure there's a gilstate tstate bound\n        // as soon as possible.\n        if (gilstate_tss_get(tstate->interp->runtime) == NULL) {\n            bind_gilstate_tstate(tstate);\n        }\n    }\n    return tstate;\n}\n\n// This must be followed by a call to _PyThreadState_Bind();\nPyThreadState *\n_PyThreadState_New(PyInterpreterState *interp)\n{\n    return new_threadstate(interp);\n}\n\n// We keep this for stable ABI compabibility.\nPyThreadState *\n_PyThreadState_Prealloc(PyInterpreterState *interp)\n{\n    return _PyThreadState_New(interp);\n}\n\n// We keep this around for (accidental) stable ABI compatibility.\n// Realistically, no extensions are using it.\nvoid\n_PyThreadState_Init(PyThreadState *tstate)\n{\n    Py_FatalError(\"_PyThreadState_Init() is for internal use only\");\n}\n\n\nstatic void\nclear_datastack(PyThreadState *tstate)\n{\n    _PyStackChunk *chunk = tstate->datastack_chunk;\n    tstate->datastack_chunk = NULL;\n    while (chunk != NULL) {\n        _PyStackChunk *prev = chunk->previous;\n        _PyObject_VirtualFree(chunk, chunk->size);\n        chunk = prev;\n    }\n}\n\nvoid\nPyThreadState_Clear(PyThreadState *tstate)\n{\n    assert(tstate->_status.initialized && !tstate->_status.cleared);\n    // XXX assert(!tstate->_status.bound || tstate->_status.unbound);\n    tstate->_status.finalizing = 1;  // just in case\n\n    /* XXX Conditions we need to enforce:\n\n       * the GIL must be held by the current thread\n       * current_fast_get()->interp must match tstate->interp\n       * for the main interpreter, current_fast_get() must be the main thread\n     */\n\n    int verbose = _PyInterpreterState_GetConfig(tstate->interp)->verbose;\n\n    if (verbose && tstate->cframe->current_frame != NULL) {\n        /* bpo-20526: After the main thread calls\n           _PyInterpreterState_SetFinalizing() in Py_FinalizeEx()\n           (or in Py_EndInterpreter() for subinterpreters),\n           threads must exit when trying to take the GIL.\n           If a thread exit in the middle of _PyEval_EvalFrameDefault(),\n           tstate->frame is not reset to its previous value.\n           It is more likely with daemon threads, but it can happen\n           with regular threads if threading._shutdown() fails\n           (ex: interrupted by CTRL+C). */\n        fprintf(stderr,\n          \"PyThreadState_Clear: warning: thread still has a frame\\n\");\n    }\n\n    /* At this point tstate shouldn't be used any more,\n       neither to run Python code nor for other uses.\n\n       This is tricky when current_fast_get() == tstate, in the same way\n       as noted in interpreter_clear() above.  The below finalizers\n       can possibly run Python code or otherwise use the partially\n       cleared thread state.  For now we trust that isn't a problem\n       in practice.\n     */\n    // XXX Deal with the possibility of problematic finalizers.\n\n    /* Don't clear tstate->pyframe: it is a borrowed reference */\n\n    Py_CLEAR(tstate->dict);\n    Py_CLEAR(tstate->async_exc);\n\n    Py_CLEAR(tstate->current_exception);\n\n    Py_CLEAR(tstate->exc_state.exc_value);\n\n    /* The stack of exception states should contain just this thread. */\n    if (verbose && tstate->exc_info != &tstate->exc_state) {\n        fprintf(stderr,\n          \"PyThreadState_Clear: warning: thread still has a generator\\n\");\n    }\n\n    if (tstate->c_profilefunc != NULL) {\n        tstate->interp->sys_profiling_threads--;\n        tstate->c_profilefunc = NULL;\n    }\n    if (tstate->c_tracefunc != NULL) {\n        tstate->interp->sys_tracing_threads--;\n        tstate->c_tracefunc = NULL;\n    }\n    Py_CLEAR(tstate->c_profileobj);\n    Py_CLEAR(tstate->c_traceobj);\n\n    Py_CLEAR(tstate->async_gen_firstiter);\n    Py_CLEAR(tstate->async_gen_finalizer);\n\n    Py_CLEAR(tstate->context);\n\n    if (tstate->on_delete != NULL) {\n        tstate->on_delete(tstate->on_delete_data);\n    }\n\n    tstate->_status.cleared = 1;\n\n    // XXX Call _PyThreadStateSwap(runtime, NULL) here if \"current\".\n    // XXX Do it as early in the function as possible.\n}\n\n/* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */\nstatic void\ntstate_delete_common(PyThreadState *tstate)\n{\n    assert(tstate->_status.cleared && !tstate->_status.finalized);\n\n    PyInterpreterState *interp = tstate->interp;\n    if (interp == NULL) {\n        Py_FatalError(\"NULL interpreter\");\n    }\n    _PyRuntimeState *runtime = interp->runtime;\n\n    HEAD_LOCK(runtime);\n    if (tstate->prev) {\n        tstate->prev->next = tstate->next;\n    }\n    else {\n        interp->threads.head = tstate->next;\n    }\n    if (tstate->next) {\n        tstate->next->prev = tstate->prev;\n    }\n    HEAD_UNLOCK(runtime);\n\n    // XXX Unbind in PyThreadState_Clear(), or earlier\n    // (and assert not-equal here)?\n    if (tstate->_status.bound_gilstate) {\n        unbind_gilstate_tstate(tstate);\n    }\n    unbind_tstate(tstate);\n\n    // XXX Move to PyThreadState_Clear()?\n    clear_datastack(tstate);\n\n    tstate->_status.finalized = 1;\n}\n\nstatic void\nzapthreads(PyInterpreterState *interp)\n{\n    PyThreadState *tstate;\n    /* No need to lock the mutex here because this should only happen\n       when the threads are all really dead (XXX famous last words). */\n    while ((tstate = interp->threads.head) != NULL) {\n        tstate_verify_not_active(tstate);\n        tstate_delete_common(tstate);\n        free_threadstate(tstate);\n    }\n}\n\n\nvoid\nPyThreadState_Delete(PyThreadState *tstate)\n{\n    _Py_EnsureTstateNotNULL(tstate);\n    tstate_verify_not_active(tstate);\n    tstate_delete_common(tstate);\n    free_threadstate(tstate);\n}\n\n\nvoid\n_PyThreadState_DeleteCurrent(PyThreadState *tstate)\n{\n    _Py_EnsureTstateNotNULL(tstate);\n    tstate_delete_common(tstate);\n    current_fast_clear(tstate->interp->runtime);\n    _PyEval_ReleaseLock(tstate);\n    free_threadstate(tstate);\n}\n\nvoid\nPyThreadState_DeleteCurrent(void)\n{\n    PyThreadState *tstate = current_fast_get(&_PyRuntime);\n    _PyThreadState_DeleteCurrent(tstate);\n}\n\n\n/*\n * Delete all thread states except the one passed as argument.\n * Note that, if there is a current thread state, it *must* be the one\n * passed as argument.  Also, this won't touch any other interpreters\n * than the current one, since we don't know which thread state should\n * be kept in those other interpreters.\n */\nvoid\n_PyThreadState_DeleteExcept(PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n    PyInterpreterState *interp = tstate->interp;\n    _PyRuntimeState *runtime = interp->runtime;\n\n    HEAD_LOCK(runtime);\n    /* Remove all thread states, except tstate, from the linked list of\n       thread states.  This will allow calling PyThreadState_Clear()\n       without holding the lock. */\n    PyThreadState *list = interp->threads.head;\n    if (list == tstate) {\n        list = tstate->next;\n    }\n    if (tstate->prev) {\n        tstate->prev->next = tstate->next;\n    }\n    if (tstate->next) {\n        tstate->next->prev = tstate->prev;\n    }\n    tstate->prev = tstate->next = NULL;\n    interp->threads.head = tstate;\n    HEAD_UNLOCK(runtime);\n\n    /* Clear and deallocate all stale thread states.  Even if this\n       executes Python code, we should be safe since it executes\n       in the current thread, not one of the stale threads. */\n    PyThreadState *p, *next;\n    for (p = list; p; p = next) {\n        next = p->next;\n        PyThreadState_Clear(p);\n        free_threadstate(p);\n    }\n}\n\n\n//-------------------------\n// \"detached\" thread states\n//-------------------------\n\nvoid\n_PyThreadState_InitDetached(PyThreadState *tstate, PyInterpreterState *interp)\n{\n    _PyRuntimeState *runtime = interp->runtime;\n\n    HEAD_LOCK(runtime);\n    interp->threads.next_unique_id += 1;\n    uint64_t id = interp->threads.next_unique_id;\n    HEAD_UNLOCK(runtime);\n\n    init_threadstate(tstate, interp, id);\n    // We do not call add_threadstate().\n}\n\nvoid\n_PyThreadState_ClearDetached(PyThreadState *tstate)\n{\n    assert(!tstate->_status.bound);\n    assert(!tstate->_status.bound_gilstate);\n    assert(tstate->datastack_chunk == NULL);\n    assert(tstate->thread_id == 0);\n    assert(tstate->native_thread_id == 0);\n    assert(tstate->next == NULL);\n    assert(tstate->prev == NULL);\n\n    PyThreadState_Clear(tstate);\n    clear_datastack(tstate);\n}\n\nvoid\n_PyThreadState_BindDetached(PyThreadState *tstate)\n{\n    assert(!_Py_IsMainInterpreter(\n        current_fast_get(tstate->interp->runtime)->interp));\n    assert(_Py_IsMainInterpreter(tstate->interp));\n    bind_tstate(tstate);\n    /* Unlike _PyThreadState_Bind(), we do not modify gilstate TSS. */\n}\n\nvoid\n_PyThreadState_UnbindDetached(PyThreadState *tstate)\n{\n    assert(!_Py_IsMainInterpreter(\n        current_fast_get(tstate->interp->runtime)->interp));\n    assert(_Py_IsMainInterpreter(tstate->interp));\n    assert(tstate_is_alive(tstate));\n    assert(!tstate->_status.active);\n    assert(gilstate_tss_get(tstate->interp->runtime) != tstate);\n\n    unbind_tstate(tstate);\n\n    /* This thread state may be bound/unbound repeatedly,\n       so we must erase evidence that it was ever bound (or unbound). */\n    tstate->_status.bound = 0;\n    tstate->_status.unbound = 0;\n\n    /* We must fully unlink the thread state from any OS thread,\n       to allow it to be bound more than once. */\n    tstate->thread_id = 0;\n#ifdef PY_HAVE_THREAD_NATIVE_ID\n    tstate->native_thread_id = 0;\n#endif\n}\n\n\n//----------\n// accessors\n//----------\n\n/* An extension mechanism to store arbitrary additional per-thread state.\n   PyThreadState_GetDict() returns a dictionary that can be used to hold such\n   state; the caller should pick a unique key and store its state there.  If\n   PyThreadState_GetDict() returns NULL, an exception has *not* been raised\n   and the caller should assume no per-thread state is available. */\n\nPyObject *\n_PyThreadState_GetDict(PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n    if (tstate->dict == NULL) {\n        tstate->dict = PyDict_New();\n        if (tstate->dict == NULL) {\n            _PyErr_Clear(tstate);\n        }\n    }\n    return tstate->dict;\n}\n\n\nPyObject *\nPyThreadState_GetDict(void)\n{\n    PyThreadState *tstate = current_fast_get(&_PyRuntime);\n    if (tstate == NULL) {\n        return NULL;\n    }\n    return _PyThreadState_GetDict(tstate);\n}\n\n\nPyInterpreterState *\nPyThreadState_GetInterpreter(PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n    return tstate->interp;\n}\n\n\nPyFrameObject*\nPyThreadState_GetFrame(PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n    _PyInterpreterFrame *f = _PyThreadState_GetFrame(tstate);\n    if (f == NULL) {\n        return NULL;\n    }\n    PyFrameObject *frame = _PyFrame_GetFrameObject(f);\n    if (frame == NULL) {\n        PyErr_Clear();\n    }\n    return (PyFrameObject*)Py_XNewRef(frame);\n}\n\n\nuint64_t\nPyThreadState_GetID(PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n    return tstate->id;\n}\n\n\nstatic inline void\ntstate_activate(PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n    // XXX assert(tstate_is_alive(tstate));\n    assert(tstate_is_bound(tstate));\n    assert(!tstate->_status.active);\n\n    assert(!tstate->_status.bound_gilstate ||\n           tstate == gilstate_tss_get((tstate->interp->runtime)));\n    if (!tstate->_status.bound_gilstate) {\n        bind_gilstate_tstate(tstate);\n    }\n\n    tstate->_status.active = 1;\n}\n\nstatic inline void\ntstate_deactivate(PyThreadState *tstate)\n{\n    assert(tstate != NULL);\n    // XXX assert(tstate_is_alive(tstate));\n    assert(tstate_is_bound(tstate));\n    assert(tstate->_status.active);\n\n    tstate->_status.active = 0;\n\n    // We do not unbind the gilstate tstate here.\n    // It will still be used in PyGILState_Ensure().\n}\n\n\n//----------\n// other API\n//----------\n\n/* Asynchronously raise an exception in a thread.\n   Requested by Just van Rossum and Alex Martelli.\n   To prevent naive misuse, you must write your own extension\n   to call this, or use ctypes.  Must be called with the GIL held.\n   Returns the number of tstates modified (normally 1, but 0 if `id` didn't\n   match any known thread id).  Can be called with exc=NULL to clear an\n   existing async exception.  This raises no exceptions. */\n\n// XXX Move this to Python/ceval_gil.c?\n// XXX Deprecate this.\nint\nPyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)\n{\n    _PyRuntimeState *runtime = &_PyRuntime;\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n\n    /* Although the GIL is held, a few C API functions can be called\n     * without the GIL held, and in particular some that create and\n     * destroy thread and interpreter states.  Those can mutate the\n     * list of thread states we're traversing, so to prevent that we lock\n     * head_mutex for the duration.\n     */\n    HEAD_LOCK(runtime);\n    for (PyThreadState *tstate = interp->threads.head; tstate != NULL; tstate = tstate->next) {\n        if (tstate->thread_id != id) {\n            continue;\n        }\n\n        /* Tricky:  we need to decref the current value\n         * (if any) in tstate->async_exc, but that can in turn\n         * allow arbitrary Python code to run, including\n         * perhaps calls to this function.  To prevent\n         * deadlock, we need to release head_mutex before\n         * the decref.\n         */\n        PyObject *old_exc = tstate->async_exc;\n        tstate->async_exc = Py_XNewRef(exc);\n        HEAD_UNLOCK(runtime);\n\n        Py_XDECREF(old_exc);\n        _PyEval_SignalAsyncExc(tstate->interp);\n        return 1;\n    }\n    HEAD_UNLOCK(runtime);\n    return 0;\n}\n\n\n//---------------------------------\n// API for the current thread state\n//---------------------------------\n\nPyThreadState *\n_PyThreadState_UncheckedGet(void)\n{\n    return current_fast_get(&_PyRuntime);\n}\n\n\nPyThreadState *\nPyThreadState_Get(void)\n{\n    PyThreadState *tstate = current_fast_get(&_PyRuntime);\n    _Py_EnsureTstateNotNULL(tstate);\n    return tstate;\n}\n\n\nstatic void\n_swap_thread_states(_PyRuntimeState *runtime,\n                    PyThreadState *oldts, PyThreadState *newts)\n{\n    // XXX Do this only if oldts != NULL?\n    current_fast_clear(runtime);\n\n    if (oldts != NULL) {\n        // XXX assert(tstate_is_alive(oldts) && tstate_is_bound(oldts));\n        tstate_deactivate(oldts);\n    }\n\n    if (newts != NULL) {\n        // XXX assert(tstate_is_alive(newts));\n        assert(tstate_is_bound(newts));\n        current_fast_set(runtime, newts);\n        tstate_activate(newts);\n    }\n}\n\nPyThreadState *\n_PyThreadState_SwapNoGIL(PyThreadState *newts)\n{\n#if defined(Py_DEBUG)\n    /* This can be called from PyEval_RestoreThread(). Similar\n       to it, we need to ensure errno doesn't change.\n    */\n    int err = errno;\n#endif\n\n    PyThreadState *oldts = current_fast_get(&_PyRuntime);\n    _swap_thread_states(&_PyRuntime, oldts, newts);\n\n#if defined(Py_DEBUG)\n    errno = err;\n#endif\n    return oldts;\n}\n\nPyThreadState *\n_PyThreadState_Swap(_PyRuntimeState *runtime, PyThreadState *newts)\n{\n    PyThreadState *oldts = current_fast_get(runtime);\n    if (oldts != NULL) {\n        _PyEval_ReleaseLock(oldts);\n    }\n    _swap_thread_states(runtime, oldts, newts);\n    if (newts != NULL) {\n        _PyEval_AcquireLock(newts);\n    }\n    return oldts;\n}\n\nPyThreadState *\nPyThreadState_Swap(PyThreadState *newts)\n{\n    return _PyThreadState_Swap(&_PyRuntime, newts);\n}\n\n\nvoid\n_PyThreadState_Bind(PyThreadState *tstate)\n{\n    bind_tstate(tstate);\n    // This makes sure there's a gilstate tstate bound\n    // as soon as possible.\n    if (gilstate_tss_get(tstate->interp->runtime) == NULL) {\n        bind_gilstate_tstate(tstate);\n    }\n}\n\n\n/***********************************/\n/* routines for advanced debuggers */\n/***********************************/\n\n// (requested by David Beazley)\n// Don't use unless you know what you are doing!\n\nPyInterpreterState *\nPyInterpreterState_Head(void)\n{\n    return _PyRuntime.interpreters.head;\n}\n\nPyInterpreterState *\nPyInterpreterState_Main(void)\n{\n    return _PyInterpreterState_Main();\n}\n\nPyInterpreterState *\nPyInterpreterState_Next(PyInterpreterState *interp) {\n    return interp->next;\n}\n\nPyThreadState *\nPyInterpreterState_ThreadHead(PyInterpreterState *interp) {\n    return interp->threads.head;\n}\n\nPyThreadState *\nPyThreadState_Next(PyThreadState *tstate) {\n    return tstate->next;\n}\n\n\n/********************************************/\n/* reporting execution state of all threads */\n/********************************************/\n\n/* The implementation of sys._current_frames().  This is intended to be\n   called with the GIL held, as it will be when called via\n   sys._current_frames().  It's possible it would work fine even without\n   the GIL held, but haven't thought enough about that.\n*/\nPyObject *\n_PyThread_CurrentFrames(void)\n{\n    _PyRuntimeState *runtime = &_PyRuntime;\n    PyThreadState *tstate = current_fast_get(runtime);\n    if (_PySys_Audit(tstate, \"sys._current_frames\", NULL) < 0) {\n        return NULL;\n    }\n\n    PyObject *result = PyDict_New();\n    if (result == NULL) {\n        return NULL;\n    }\n\n    /* for i in all interpreters:\n     *     for t in all of i's thread states:\n     *          if t's frame isn't NULL, map t's id to its frame\n     * Because these lists can mutate even when the GIL is held, we\n     * need to grab head_mutex for the duration.\n     */\n    HEAD_LOCK(runtime);\n    PyInterpreterState *i;\n    for (i = runtime->interpreters.head; i != NULL; i = i->next) {\n        PyThreadState *t;\n        for (t = i->threads.head; t != NULL; t = t->next) {\n            _PyInterpreterFrame *frame = t->cframe->current_frame;\n            frame = _PyFrame_GetFirstComplete(frame);\n            if (frame == NULL) {\n                continue;\n            }\n            PyObject *id = PyLong_FromUnsignedLong(t->thread_id);\n            if (id == NULL) {\n                goto fail;\n            }\n            PyObject *frameobj = (PyObject *)_PyFrame_GetFrameObject(frame);\n            if (frameobj == NULL) {\n                Py_DECREF(id);\n                goto fail;\n            }\n            int stat = PyDict_SetItem(result, id, frameobj);\n            Py_DECREF(id);\n            if (stat < 0) {\n                goto fail;\n            }\n        }\n    }\n    goto done;\n\nfail:\n    Py_CLEAR(result);\n\ndone:\n    HEAD_UNLOCK(runtime);\n    return result;\n}\n\n/* The implementation of sys._current_exceptions().  This is intended to be\n   called with the GIL held, as it will be when called via\n   sys._current_exceptions().  It's possible it would work fine even without\n   the GIL held, but haven't thought enough about that.\n*/\nPyObject *\n_PyThread_CurrentExceptions(void)\n{\n    _PyRuntimeState *runtime = &_PyRuntime;\n    PyThreadState *tstate = current_fast_get(runtime);\n\n    _Py_EnsureTstateNotNULL(tstate);\n\n    if (_PySys_Audit(tstate, \"sys._current_exceptions\", NULL) < 0) {\n        return NULL;\n    }\n\n    PyObject *result = PyDict_New();\n    if (result == NULL) {\n        return NULL;\n    }\n\n    /* for i in all interpreters:\n     *     for t in all of i's thread states:\n     *          if t's frame isn't NULL, map t's id to its frame\n     * Because these lists can mutate even when the GIL is held, we\n     * need to grab head_mutex for the duration.\n     */\n    HEAD_LOCK(runtime);\n    PyInterpreterState *i;\n    for (i = runtime->interpreters.head; i != NULL; i = i->next) {\n        PyThreadState *t;\n        for (t = i->threads.head; t != NULL; t = t->next) {\n            _PyErr_StackItem *err_info = _PyErr_GetTopmostException(t);\n            if (err_info == NULL) {\n                continue;\n            }\n            PyObject *id = PyLong_FromUnsignedLong(t->thread_id);\n            if (id == NULL) {\n                goto fail;\n            }\n            PyObject *exc = err_info->exc_value;\n            assert(exc == NULL ||\n                   exc == Py_None ||\n                   PyExceptionInstance_Check(exc));\n\n            int stat = PyDict_SetItem(result, id, exc == NULL ? Py_None : exc);\n            Py_DECREF(id);\n            if (stat < 0) {\n                goto fail;\n            }\n        }\n    }\n    goto done;\n\nfail:\n    Py_CLEAR(result);\n\ndone:\n    HEAD_UNLOCK(runtime);\n    return result;\n}\n\n\n/***********************************/\n/* Python \"auto thread state\" API. */\n/***********************************/\n\n/* Internal initialization/finalization functions called by\n   Py_Initialize/Py_FinalizeEx\n*/\nPyStatus\n_PyGILState_Init(PyInterpreterState *interp)\n{\n    if (!_Py_IsMainInterpreter(interp)) {\n        /* Currently, PyGILState is shared by all interpreters. The main\n         * interpreter is responsible to initialize it. */\n        return _PyStatus_OK();\n    }\n    _PyRuntimeState *runtime = interp->runtime;\n    assert(gilstate_tss_get(runtime) == NULL);\n    assert(runtime->gilstate.autoInterpreterState == NULL);\n    runtime->gilstate.autoInterpreterState = interp;\n    return _PyStatus_OK();\n}\n\nvoid\n_PyGILState_Fini(PyInterpreterState *interp)\n{\n    if (!_Py_IsMainInterpreter(interp)) {\n        /* Currently, PyGILState is shared by all interpreters. The main\n         * interpreter is responsible to initialize it. */\n        return;\n    }\n    interp->runtime->gilstate.autoInterpreterState = NULL;\n}\n\n\n// XXX Drop this.\nPyStatus\n_PyGILState_SetTstate(PyThreadState *tstate)\n{\n    /* must init with valid states */\n    assert(tstate != NULL);\n    assert(tstate->interp != NULL);\n\n    if (!_Py_IsMainInterpreter(tstate->interp)) {\n        /* Currently, PyGILState is shared by all interpreters. The main\n         * interpreter is responsible to initialize it. */\n        return _PyStatus_OK();\n    }\n\n#ifndef NDEBUG\n    _PyRuntimeState *runtime = tstate->interp->runtime;\n\n    assert(runtime->gilstate.autoInterpreterState == tstate->interp);\n    assert(gilstate_tss_get(runtime) == tstate);\n    assert(tstate->gilstate_counter == 1);\n#endif\n\n    return _PyStatus_OK();\n}\n\nPyInterpreterState *\n_PyGILState_GetInterpreterStateUnsafe(void)\n{\n    return _PyRuntime.gilstate.autoInterpreterState;\n}\n\n/* The public functions */\n\nPyThreadState *\nPyGILState_GetThisThreadState(void)\n{\n    _PyRuntimeState *runtime = &_PyRuntime;\n    if (!gilstate_tss_initialized(runtime)) {\n        return NULL;\n    }\n    return gilstate_tss_get(runtime);\n}\n\nint\nPyGILState_Check(void)\n{\n    _PyRuntimeState *runtime = &_PyRuntime;\n    if (!runtime->gilstate.check_enabled) {\n        return 1;\n    }\n\n    if (!gilstate_tss_initialized(runtime)) {\n        return 1;\n    }\n\n    PyThreadState *tstate = current_fast_get(runtime);\n    if (tstate == NULL) {\n        return 0;\n    }\n\n    return (tstate == gilstate_tss_get(runtime));\n}\n\nPyGILState_STATE\nPyGILState_Ensure(void)\n{\n    _PyRuntimeState *runtime = &_PyRuntime;\n\n    /* Note that we do not auto-init Python here - apart from\n       potential races with 2 threads auto-initializing, pep-311\n       spells out other issues.  Embedders are expected to have\n       called Py_Initialize(). */\n\n    /* Ensure that _PyEval_InitThreads() and _PyGILState_Init() have been\n       called by Py_Initialize() */\n    assert(_PyEval_ThreadsInitialized());\n    assert(gilstate_tss_initialized(runtime));\n    assert(runtime->gilstate.autoInterpreterState != NULL);\n\n    PyThreadState *tcur = gilstate_tss_get(runtime);\n    int has_gil;\n    if (tcur == NULL) {\n        /* Create a new Python thread state for this thread */\n        tcur = new_threadstate(runtime->gilstate.autoInterpreterState);\n        if (tcur == NULL) {\n            Py_FatalError(\"Couldn't create thread-state for new thread\");\n        }\n        bind_tstate(tcur);\n        bind_gilstate_tstate(tcur);\n\n        /* This is our thread state!  We'll need to delete it in the\n           matching call to PyGILState_Release(). */\n        assert(tcur->gilstate_counter == 1);\n        tcur->gilstate_counter = 0;\n        has_gil = 0; /* new thread state is never current */\n    }\n    else {\n        has_gil = holds_gil(tcur);\n    }\n\n    if (!has_gil) {\n        PyEval_RestoreThread(tcur);\n    }\n\n    /* Update our counter in the thread-state - no need for locks:\n       - tcur will remain valid as we hold the GIL.\n       - the counter is safe as we are the only thread \"allowed\"\n         to modify this value\n    */\n    ++tcur->gilstate_counter;\n\n    return has_gil ? PyGILState_LOCKED : PyGILState_UNLOCKED;\n}\n\nvoid\nPyGILState_Release(PyGILState_STATE oldstate)\n{\n    _PyRuntimeState *runtime = &_PyRuntime;\n    PyThreadState *tstate = gilstate_tss_get(runtime);\n    if (tstate == NULL) {\n        Py_FatalError(\"auto-releasing thread-state, \"\n                      \"but no thread-state for this thread\");\n    }\n\n    /* We must hold the GIL and have our thread state current */\n    /* XXX - remove the check - the assert should be fine,\n       but while this is very new (April 2003), the extra check\n       by release-only users can't hurt.\n    */\n    if (!holds_gil(tstate)) {\n        _Py_FatalErrorFormat(__func__,\n                             \"thread state %p must be current when releasing\",\n                             tstate);\n    }\n    assert(holds_gil(tstate));\n    --tstate->gilstate_counter;\n    assert(tstate->gilstate_counter >= 0); /* illegal counter value */\n\n    /* If we're going to destroy this thread-state, we must\n     * clear it while the GIL is held, as destructors may run.\n     */\n    if (tstate->gilstate_counter == 0) {\n        /* can't have been locked when we created it */\n        assert(oldstate == PyGILState_UNLOCKED);\n        // XXX Unbind tstate here.\n        PyThreadState_Clear(tstate);\n        /* Delete the thread-state.  Note this releases the GIL too!\n         * It's vital that the GIL be held here, to avoid shutdown\n         * races; see bugs 225673 and 1061968 (that nasty bug has a\n         * habit of coming back).\n         */\n        assert(current_fast_get(runtime) == tstate);\n        _PyThreadState_DeleteCurrent(tstate);\n    }\n    /* Release the lock if necessary */\n    else if (oldstate == PyGILState_UNLOCKED) {\n        PyEval_SaveThread();\n    }\n}\n\n\n/**************************/\n/* cross-interpreter data */\n/**************************/\n\n/* cross-interpreter data */\n\nstatic inline void\n_xidata_init(_PyCrossInterpreterData *data)\n{\n    // If the value is being reused\n    // then _xidata_clear() should have been called already.\n    assert(data->data == NULL);\n    assert(data->obj == NULL);\n    *data = (_PyCrossInterpreterData){0};\n    data->interp = -1;\n}\n\nstatic inline void\n_xidata_clear(_PyCrossInterpreterData *data)\n{\n    if (data->free != NULL) {\n        data->free(data->data);\n    }\n    data->data = NULL;\n    Py_CLEAR(data->obj);\n}\n\nvoid\n_PyCrossInterpreterData_Init(_PyCrossInterpreterData *data,\n                             PyInterpreterState *interp,\n                             void *shared, PyObject *obj,\n                             xid_newobjectfunc new_object)\n{\n    assert(data != NULL);\n    assert(new_object != NULL);\n    _xidata_init(data);\n    data->data = shared;\n    if (obj != NULL) {\n        assert(interp != NULL);\n        // released in _PyCrossInterpreterData_Clear()\n        data->obj = Py_NewRef(obj);\n    }\n    // Ideally every object would know its owning interpreter.\n    // Until then, we have to rely on the caller to identify it\n    // (but we don't need it in all cases).\n    data->interp = (interp != NULL) ? interp->id : -1;\n    data->new_object = new_object;\n}\n\nint\n_PyCrossInterpreterData_InitWithSize(_PyCrossInterpreterData *data,\n                                     PyInterpreterState *interp,\n                                     const size_t size, PyObject *obj,\n                                     xid_newobjectfunc new_object)\n{\n    assert(size > 0);\n    // For now we always free the shared data in the same interpreter\n    // where it was allocated, so the interpreter is required.\n    assert(interp != NULL);\n    _PyCrossInterpreterData_Init(data, interp, NULL, obj, new_object);\n    data->data = PyMem_RawMalloc(size);\n    if (data->data == NULL) {\n        return -1;\n    }\n    data->free = PyMem_RawFree;\n    return 0;\n}\n\nvoid\n_PyCrossInterpreterData_Clear(PyInterpreterState *interp,\n                              _PyCrossInterpreterData *data)\n{\n    assert(data != NULL);\n    // This must be called in the owning interpreter.\n    assert(interp == NULL || data->interp == interp->id);\n    _xidata_clear(data);\n}\n\nstatic int\n_check_xidata(PyThreadState *tstate, _PyCrossInterpreterData *data)\n{\n    // data->data can be anything, including NULL, so we don't check it.\n\n    // data->obj may be NULL, so we don't check it.\n\n    if (data->interp < 0) {\n        _PyErr_SetString(tstate, PyExc_SystemError, \"missing interp\");\n        return -1;\n    }\n\n    if (data->new_object == NULL) {\n        _PyErr_SetString(tstate, PyExc_SystemError, \"missing new_object func\");\n        return -1;\n    }\n\n    // data->free may be NULL, so we don't check it.\n\n    return 0;\n}\n\ncrossinterpdatafunc _PyCrossInterpreterData_Lookup(PyObject *);\n\n/* This is a separate func from _PyCrossInterpreterData_Lookup in order\n   to keep the registry code separate. */\nstatic crossinterpdatafunc\n_lookup_getdata(PyObject *obj)\n{\n    crossinterpdatafunc getdata = _PyCrossInterpreterData_Lookup(obj);\n    if (getdata == NULL && PyErr_Occurred() == 0)\n        PyErr_Format(PyExc_ValueError,\n                     \"%S does not support cross-interpreter data\", obj);\n    return getdata;\n}\n\nint\n_PyObject_CheckCrossInterpreterData(PyObject *obj)\n{\n    crossinterpdatafunc getdata = _lookup_getdata(obj);\n    if (getdata == NULL) {\n        return -1;\n    }\n    return 0;\n}\n\nint\n_PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)\n{\n    _PyRuntimeState *runtime = &_PyRuntime;\n    PyThreadState *tstate = current_fast_get(runtime);\n#ifdef Py_DEBUG\n    // The caller must hold the GIL\n    _Py_EnsureTstateNotNULL(tstate);\n#endif\n    PyInterpreterState *interp = tstate->interp;\n\n    // Reset data before re-populating.\n    *data = (_PyCrossInterpreterData){0};\n    data->interp = -1;\n\n    // Call the \"getdata\" func for the object.\n    Py_INCREF(obj);\n    crossinterpdatafunc getdata = _lookup_getdata(obj);\n    if (getdata == NULL) {\n        Py_DECREF(obj);\n        return -1;\n    }\n    int res = getdata(tstate, obj, data);\n    Py_DECREF(obj);\n    if (res != 0) {\n        return -1;\n    }\n\n    // Fill in the blanks and validate the result.\n    data->interp = interp->id;\n    if (_check_xidata(tstate, data) != 0) {\n        (void)_PyCrossInterpreterData_Release(data);\n        return -1;\n    }\n\n    return 0;\n}\n\nPyObject *\n_PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data)\n{\n    return data->new_object(data);\n}\n\ntypedef void (*releasefunc)(PyInterpreterState *, void *);\n\nstatic void\n_call_in_interpreter(PyInterpreterState *interp, releasefunc func, void *arg)\n{\n    /* We would use Py_AddPendingCall() if it weren't specific to the\n     * main interpreter (see bpo-33608).  In the meantime we take a\n     * naive approach.\n     */\n    _PyRuntimeState *runtime = interp->runtime;\n    PyThreadState *save_tstate = NULL;\n    if (interp != current_fast_get(runtime)->interp) {\n        // XXX Using the \"head\" thread isn't strictly correct.\n        PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);\n        // XXX Possible GILState issues?\n        save_tstate = _PyThreadState_Swap(runtime, tstate);\n    }\n\n    // XXX Once the GIL is per-interpreter, this should be called with the\n    // calling interpreter's GIL released and the target interpreter's held.\n    func(interp, arg);\n\n    // Switch back.\n    if (save_tstate != NULL) {\n        _PyThreadState_Swap(runtime, save_tstate);\n    }\n}\n\nint\n_PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)\n{\n    if (data->free == NULL && data->obj == NULL) {\n        // Nothing to release!\n        data->data = NULL;\n        return 0;\n    }\n\n    // Switch to the original interpreter.\n    PyInterpreterState *interp = _PyInterpreterState_LookUpID(data->interp);\n    if (interp == NULL) {\n        // The interpreter was already destroyed.\n        // This function shouldn't have been called.\n        // XXX Someone leaked some memory...\n        assert(PyErr_Occurred());\n        return -1;\n    }\n\n    // \"Release\" the data and/or the object.\n    _call_in_interpreter(interp,\n                         (releasefunc)_PyCrossInterpreterData_Clear, data);\n    return 0;\n}\n\n/* registry of {type -> crossinterpdatafunc} */\n\n/* For now we use a global registry of shareable classes.  An\n   alternative would be to add a tp_* slot for a class's\n   crossinterpdatafunc. It would be simpler and more efficient. */\n\nstatic int\n_xidregistry_add_type(struct _xidregistry *xidregistry, PyTypeObject *cls,\n                 crossinterpdatafunc getdata)\n{\n    // Note that we effectively replace already registered classes\n    // rather than failing.\n    struct _xidregitem *newhead = PyMem_RawMalloc(sizeof(struct _xidregitem));\n    if (newhead == NULL) {\n        return -1;\n    }\n    // XXX Assign a callback to clear the entry from the registry?\n    newhead->cls = PyWeakref_NewRef((PyObject *)cls, NULL);\n    if (newhead->cls == NULL) {\n        PyMem_RawFree(newhead);\n        return -1;\n    }\n    newhead->getdata = getdata;\n    newhead->prev = NULL;\n    newhead->next = xidregistry->head;\n    if (newhead->next != NULL) {\n        newhead->next->prev = newhead;\n    }\n    xidregistry->head = newhead;\n    return 0;\n}\n\nstatic struct _xidregitem *\n_xidregistry_remove_entry(struct _xidregistry *xidregistry,\n                          struct _xidregitem *entry)\n{\n    struct _xidregitem *next = entry->next;\n    if (entry->prev != NULL) {\n        assert(entry->prev->next == entry);\n        entry->prev->next = next;\n    }\n    else {\n        assert(xidregistry->head == entry);\n        xidregistry->head = next;\n    }\n    if (next != NULL) {\n        next->prev = entry->prev;\n    }\n    Py_DECREF(entry->cls);\n    PyMem_RawFree(entry);\n    return next;\n}\n\nstatic struct _xidregitem *\n_xidregistry_find_type(struct _xidregistry *xidregistry, PyTypeObject *cls)\n{\n    struct _xidregitem *cur = xidregistry->head;\n    while (cur != NULL) {\n        PyObject *registered = PyWeakref_GetObject(cur->cls);\n        if (registered == Py_None) {\n            // The weakly ref'ed object was freed.\n            cur = _xidregistry_remove_entry(xidregistry, cur);\n        }\n        else {\n            assert(PyType_Check(registered));\n            if (registered == (PyObject *)cls) {\n                return cur;\n            }\n            cur = cur->next;\n        }\n    }\n    return NULL;\n}\n\nstatic void _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry);\n\nint\n_PyCrossInterpreterData_RegisterClass(PyTypeObject *cls,\n                                       crossinterpdatafunc getdata)\n{\n    if (!PyType_Check(cls)) {\n        PyErr_Format(PyExc_ValueError, \"only classes may be registered\");\n        return -1;\n    }\n    if (getdata == NULL) {\n        PyErr_Format(PyExc_ValueError, \"missing 'getdata' func\");\n        return -1;\n    }\n\n    struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ;\n    PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK);\n    if (xidregistry->head == NULL) {\n        _register_builtins_for_crossinterpreter_data(xidregistry);\n    }\n    int res = _xidregistry_add_type(xidregistry, cls, getdata);\n    PyThread_release_lock(xidregistry->mutex);\n    return res;\n}\n\nint\n_PyCrossInterpreterData_UnregisterClass(PyTypeObject *cls)\n{\n    int res = 0;\n    struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ;\n    PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK);\n    struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls);\n    if (matched != NULL) {\n        (void)_xidregistry_remove_entry(xidregistry, matched);\n        res = 1;\n    }\n    PyThread_release_lock(xidregistry->mutex);\n    return res;\n}\n\n\n/* Cross-interpreter objects are looked up by exact match on the class.\n   We can reassess this policy when we move from a global registry to a\n   tp_* slot. */\n\ncrossinterpdatafunc\n_PyCrossInterpreterData_Lookup(PyObject *obj)\n{\n    struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ;\n    PyObject *cls = PyObject_Type(obj);\n    PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK);\n    if (xidregistry->head == NULL) {\n        _register_builtins_for_crossinterpreter_data(xidregistry);\n    }\n    struct _xidregitem *matched = _xidregistry_find_type(xidregistry,\n                                                         (PyTypeObject *)cls);\n    Py_DECREF(cls);\n    PyThread_release_lock(xidregistry->mutex);\n    return matched != NULL ? matched->getdata : NULL;\n}\n\n/* cross-interpreter data for builtin types */\n\nstruct _shared_bytes_data {\n    char *bytes;\n    Py_ssize_t len;\n};\n\nstatic PyObject *\n_new_bytes_object(_PyCrossInterpreterData *data)\n{\n    struct _shared_bytes_data *shared = (struct _shared_bytes_data *)(data->data);\n    return PyBytes_FromStringAndSize(shared->bytes, shared->len);\n}\n\nstatic int\n_bytes_shared(PyThreadState *tstate, PyObject *obj,\n              _PyCrossInterpreterData *data)\n{\n    if (_PyCrossInterpreterData_InitWithSize(\n            data, tstate->interp, sizeof(struct _shared_bytes_data), obj,\n            _new_bytes_object\n            ) < 0)\n    {\n        return -1;\n    }\n    struct _shared_bytes_data *shared = (struct _shared_bytes_data *)data->data;\n    if (PyBytes_AsStringAndSize(obj, &shared->bytes, &shared->len) < 0) {\n        _PyCrossInterpreterData_Clear(tstate->interp, data);\n        return -1;\n    }\n    return 0;\n}\n\nstruct _shared_str_data {\n    int kind;\n    const void *buffer;\n    Py_ssize_t len;\n};\n\nstatic PyObject *\n_new_str_object(_PyCrossInterpreterData *data)\n{\n    struct _shared_str_data *shared = (struct _shared_str_data *)(data->data);\n    return PyUnicode_FromKindAndData(shared->kind, shared->buffer, shared->len);\n}\n\nstatic int\n_str_shared(PyThreadState *tstate, PyObject *obj,\n            _PyCrossInterpreterData *data)\n{\n    if (_PyCrossInterpreterData_InitWithSize(\n            data, tstate->interp, sizeof(struct _shared_str_data), obj,\n            _new_str_object\n            ) < 0)\n    {\n        return -1;\n    }\n    struct _shared_str_data *shared = (struct _shared_str_data *)data->data;\n    shared->kind = PyUnicode_KIND(obj);\n    shared->buffer = PyUnicode_DATA(obj);\n    shared->len = PyUnicode_GET_LENGTH(obj);\n    return 0;\n}\n\nstatic PyObject *\n_new_long_object(_PyCrossInterpreterData *data)\n{\n    return PyLong_FromSsize_t((Py_ssize_t)(data->data));\n}\n\nstatic int\n_long_shared(PyThreadState *tstate, PyObject *obj,\n             _PyCrossInterpreterData *data)\n{\n    /* Note that this means the size of shareable ints is bounded by\n     * sys.maxsize.  Hence on 32-bit architectures that is half the\n     * size of maximum shareable ints on 64-bit.\n     */\n    Py_ssize_t value = PyLong_AsSsize_t(obj);\n    if (value == -1 && PyErr_Occurred()) {\n        if (PyErr_ExceptionMatches(PyExc_OverflowError)) {\n            PyErr_SetString(PyExc_OverflowError, \"try sending as bytes\");\n        }\n        return -1;\n    }\n    _PyCrossInterpreterData_Init(data, tstate->interp, (void *)value, NULL,\n            _new_long_object);\n    // data->obj and data->free remain NULL\n    return 0;\n}\n\nstatic PyObject *\n_new_none_object(_PyCrossInterpreterData *data)\n{\n    // XXX Singleton refcounts are problematic across interpreters...\n    return Py_NewRef(Py_None);\n}\n\nstatic int\n_none_shared(PyThreadState *tstate, PyObject *obj,\n             _PyCrossInterpreterData *data)\n{\n    _PyCrossInterpreterData_Init(data, tstate->interp, NULL, NULL,\n            _new_none_object);\n    // data->data, data->obj and data->free remain NULL\n    return 0;\n}\n\nstatic void\n_register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry)\n{\n    // None\n    if (_xidregistry_add_type(xidregistry, (PyTypeObject *)PyObject_Type(Py_None), _none_shared) != 0) {\n        Py_FatalError(\"could not register None for cross-interpreter sharing\");\n    }\n\n    // int\n    if (_xidregistry_add_type(xidregistry, &PyLong_Type, _long_shared) != 0) {\n        Py_FatalError(\"could not register int for cross-interpreter sharing\");\n    }\n\n    // bytes\n    if (_xidregistry_add_type(xidregistry, &PyBytes_Type, _bytes_shared) != 0) {\n        Py_FatalError(\"could not register bytes for cross-interpreter sharing\");\n    }\n\n    // str\n    if (_xidregistry_add_type(xidregistry, &PyUnicode_Type, _str_shared) != 0) {\n        Py_FatalError(\"could not register str for cross-interpreter sharing\");\n    }\n}\n\n\n_PyFrameEvalFunction\n_PyInterpreterState_GetEvalFrameFunc(PyInterpreterState *interp)\n{\n    if (interp->eval_frame == NULL) {\n        return _PyEval_EvalFrameDefault;\n    }\n    return interp->eval_frame;\n}\n\n\nvoid\n_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp,\n                                     _PyFrameEvalFunction eval_frame)\n{\n    if (eval_frame == _PyEval_EvalFrameDefault) {\n        interp->eval_frame = NULL;\n    }\n    else {\n        interp->eval_frame = eval_frame;\n    }\n}\n\n\nconst PyConfig*\n_PyInterpreterState_GetConfig(PyInterpreterState *interp)\n{\n    return &interp->config;\n}\n\n\nint\n_PyInterpreterState_GetConfigCopy(PyConfig *config)\n{\n    PyInterpreterState *interp = PyInterpreterState_Get();\n\n    PyStatus status = _PyConfig_Copy(config, &interp->config);\n    if (PyStatus_Exception(status)) {\n        _PyErr_SetFromPyStatus(status);\n        return -1;\n    }\n    return 0;\n}\n\n\nconst PyConfig*\n_Py_GetConfig(void)\n{\n    _PyRuntimeState *runtime = &_PyRuntime;\n    assert(PyGILState_Check());\n    PyThreadState *tstate = current_fast_get(runtime);\n    _Py_EnsureTstateNotNULL(tstate);\n    return _PyInterpreterState_GetConfig(tstate->interp);\n}\n\n\nint\n_PyInterpreterState_HasFeature(PyInterpreterState *interp, unsigned long feature)\n{\n    return ((interp->feature_flags & feature) != 0);\n}\n\n\n#define MINIMUM_OVERHEAD 1000\n\nstatic PyObject **\npush_chunk(PyThreadState *tstate, int size)\n{\n    int allocate_size = DATA_STACK_CHUNK_SIZE;\n    while (allocate_size < (int)sizeof(PyObject*)*(size + MINIMUM_OVERHEAD)) {\n        allocate_size *= 2;\n    }\n    _PyStackChunk *new = allocate_chunk(allocate_size, tstate->datastack_chunk);\n    if (new == NULL) {\n        return NULL;\n    }\n    if (tstate->datastack_chunk) {\n        tstate->datastack_chunk->top = tstate->datastack_top -\n                                       &tstate->datastack_chunk->data[0];\n    }\n    tstate->datastack_chunk = new;\n    tstate->datastack_limit = (PyObject **)(((char *)new) + allocate_size);\n    // When new is the \"root\" chunk (i.e. new->previous == NULL), we can keep\n    // _PyThreadState_PopFrame from freeing it later by \"skipping\" over the\n    // first element:\n    PyObject **res = &new->data[new->previous == NULL];\n    tstate->datastack_top = res + size;\n    return res;\n}\n\n_PyInterpreterFrame *\n_PyThreadState_PushFrame(PyThreadState *tstate, size_t size)\n{\n    assert(size < INT_MAX/sizeof(PyObject *));\n    if (_PyThreadState_HasStackSpace(tstate, (int)size)) {\n        _PyInterpreterFrame *res = (_PyInterpreterFrame *)tstate->datastack_top;\n        tstate->datastack_top += size;\n        return res;\n    }\n    return (_PyInterpreterFrame *)push_chunk(tstate, (int)size);\n}\n\nvoid\n_PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame * frame)\n{\n    assert(tstate->datastack_chunk);\n    PyObject **base = (PyObject **)frame;\n    if (base == &tstate->datastack_chunk->data[0]) {\n        _PyStackChunk *chunk = tstate->datastack_chunk;\n        _PyStackChunk *previous = chunk->previous;\n        // push_chunk ensures that the root chunk is never popped:\n        assert(previous);\n        tstate->datastack_top = &previous->data[previous->top];\n        tstate->datastack_chunk = previous;\n        _PyObject_VirtualFree(chunk, chunk->size);\n        tstate->datastack_limit = (PyObject **)(((char *)previous) + previous->size);\n    }\n    else {\n        assert(tstate->datastack_top);\n        assert(tstate->datastack_top >= base);\n        tstate->datastack_top = base;\n    }\n}\n\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "PyStrcmp.c",
    "content": "/* Cross platform case insensitive string compare functions\n */\n\n#include \"Python.h\"\n\nint\nPyOS_mystrnicmp(const char *s1, const char *s2, Py_ssize_t size)\n{\n    const unsigned char *p1, *p2;\n    if (size == 0)\n        return 0;\n    p1 = (const unsigned char *)s1;\n    p2 = (const unsigned char *)s2;\n    for (; (--size > 0) && *p1 && *p2 && (tolower(*p1) == tolower(*p2));\n         p1++, p2++) {\n        ;\n    }\n    return tolower(*p1) - tolower(*p2);\n}\n\nint\nPyOS_mystricmp(const char *s1, const char *s2)\n{\n    const unsigned char *p1 = (const unsigned char *)s1;\n    const unsigned char *p2 = (const unsigned char *)s2;\n    for (; *p1 && *p2 && (tolower(*p1) == tolower(*p2)); p1++, p2++) {\n        ;\n    }\n    return (tolower(*p1) - tolower(*p2));\n}\n"
  },
  {
    "path": "PyStrhex.c",
    "content": "/* Format bytes as hexadecimal */\n\n#include \"Python.h\"\n#include \"pycore_strhex.h\"        // _Py_strhex_with_sep()\n#include <stdlib.h>               // abs()\n\nstatic PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen,\n                                 PyObject* sep, int bytes_per_sep_group,\n                                 const int return_bytes)\n{\n    assert(arglen >= 0);\n\n    Py_UCS1 sep_char = 0;\n    if (sep) {\n        Py_ssize_t seplen = PyObject_Length((PyObject*)sep);\n        if (seplen < 0) {\n            return NULL;\n        }\n        if (seplen != 1) {\n            PyErr_SetString(PyExc_ValueError, \"sep must be length 1.\");\n            return NULL;\n        }\n        if (PyUnicode_Check(sep)) {\n            if (PyUnicode_READY(sep))\n                return NULL;\n            if (PyUnicode_KIND(sep) != PyUnicode_1BYTE_KIND) {\n                PyErr_SetString(PyExc_ValueError, \"sep must be ASCII.\");\n                return NULL;\n            }\n            sep_char = PyUnicode_READ_CHAR(sep, 0);\n        }\n        else if (PyBytes_Check(sep)) {\n            sep_char = PyBytes_AS_STRING(sep)[0];\n        }\n        else {\n            PyErr_SetString(PyExc_TypeError, \"sep must be str or bytes.\");\n            return NULL;\n        }\n        if (sep_char > 127 && !return_bytes) {\n            PyErr_SetString(PyExc_ValueError, \"sep must be ASCII.\");\n            return NULL;\n        }\n    }\n    else {\n        bytes_per_sep_group = 0;\n    }\n\n    unsigned int abs_bytes_per_sep = abs(bytes_per_sep_group);\n    Py_ssize_t resultlen = 0;\n    if (bytes_per_sep_group && arglen > 0) {\n        /* How many sep characters we'll be inserting. */\n        resultlen = (arglen - 1) / abs_bytes_per_sep;\n    }\n    /* Bounds checking for our Py_ssize_t indices. */\n    if (arglen >= PY_SSIZE_T_MAX / 2 - resultlen) {\n        return PyErr_NoMemory();\n    }\n    resultlen += arglen * 2;\n\n    if ((size_t)abs_bytes_per_sep >= (size_t)arglen) {\n        bytes_per_sep_group = 0;\n        abs_bytes_per_sep = 0;\n    }\n\n    PyObject *retval;\n    Py_UCS1 *retbuf;\n    if (return_bytes) {\n        /* If _PyBytes_FromSize() were public we could avoid malloc+copy. */\n        retval = PyBytes_FromStringAndSize(NULL, resultlen);\n        if (!retval) {\n            return NULL;\n        }\n        retbuf = (Py_UCS1 *)PyBytes_AS_STRING(retval);\n    }\n    else {\n        retval = PyUnicode_New(resultlen, 127);\n        if (!retval) {\n            return NULL;\n        }\n        retbuf = PyUnicode_1BYTE_DATA(retval);\n    }\n\n    /* Hexlify */\n    Py_ssize_t i, j;\n    unsigned char c;\n\n    if (bytes_per_sep_group == 0) {\n        for (i = j = 0; i < arglen; ++i) {\n            assert((j + 1) < resultlen);\n            c = argbuf[i];\n            retbuf[j++] = Py_hexdigits[c >> 4];\n            retbuf[j++] = Py_hexdigits[c & 0x0f];\n        }\n        assert(j == resultlen);\n    }\n    else {\n        /* The number of complete chunk+sep periods */\n        Py_ssize_t chunks = (arglen - 1) / abs_bytes_per_sep;\n        Py_ssize_t chunk;\n        unsigned int k;\n\n        if (bytes_per_sep_group < 0) {\n            i = j = 0;\n            for (chunk = 0; chunk < chunks; chunk++) {\n                for (k = 0; k < abs_bytes_per_sep; k++) {\n                    c = argbuf[i++];\n                    retbuf[j++] = Py_hexdigits[c >> 4];\n                    retbuf[j++] = Py_hexdigits[c & 0x0f];\n                }\n                retbuf[j++] = sep_char;\n            }\n            while (i < arglen) {\n                c = argbuf[i++];\n                retbuf[j++] = Py_hexdigits[c >> 4];\n                retbuf[j++] = Py_hexdigits[c & 0x0f];\n            }\n            assert(j == resultlen);\n        }\n        else {\n            i = arglen - 1;\n            j = resultlen - 1;\n            for (chunk = 0; chunk < chunks; chunk++) {\n                for (k = 0; k < abs_bytes_per_sep; k++) {\n                    c = argbuf[i--];\n                    retbuf[j--] = Py_hexdigits[c & 0x0f];\n                    retbuf[j--] = Py_hexdigits[c >> 4];\n                }\n                retbuf[j--] = sep_char;\n            }\n            while (i >= 0) {\n                c = argbuf[i--];\n                retbuf[j--] = Py_hexdigits[c & 0x0f];\n                retbuf[j--] = Py_hexdigits[c >> 4];\n            }\n            assert(j == -1);\n        }\n    }\n\n#ifdef Py_DEBUG\n    if (!return_bytes) {\n        assert(_PyUnicode_CheckConsistency(retval, 1));\n    }\n#endif\n\n    return retval;\n}\n\nPyObject * _Py_strhex(const char* argbuf, const Py_ssize_t arglen)\n{\n    return _Py_strhex_impl(argbuf, arglen, NULL, 0, 0);\n}\n\n/* Same as above but returns a bytes() instead of str() to avoid the\n * need to decode the str() when bytes are needed. */\nPyObject* _Py_strhex_bytes(const char* argbuf, const Py_ssize_t arglen)\n{\n    return _Py_strhex_impl(argbuf, arglen, NULL, 0, 1);\n}\n\n/* These variants include support for a separator between every N bytes: */\n\nPyObject* _Py_strhex_with_sep(const char* argbuf, const Py_ssize_t arglen,\n                              PyObject* sep, const int bytes_per_group)\n{\n    return _Py_strhex_impl(argbuf, arglen, sep, bytes_per_group, 0);\n}\n\n/* Same as above but returns a bytes() instead of str() to avoid the\n * need to decode the str() when bytes are needed. */\nPyObject* _Py_strhex_bytes_with_sep(const char* argbuf, const Py_ssize_t arglen,\n                                    PyObject* sep, const int bytes_per_group)\n{\n    return _Py_strhex_impl(argbuf, arglen, sep, bytes_per_group, 1);\n}\n"
  },
  {
    "path": "PyStrtod.c",
    "content": "/* -*- Mode: C; c-file-style: \"python\" -*- */\n\n#include <Python.h>\n#include \"pycore_dtoa.h\"          // _Py_dg_strtod()\n#include \"pycore_pymath.h\"        // _PY_SHORT_FLOAT_REPR\n#include <locale.h>\n\n/* Case-insensitive string match used for nan and inf detection; t should be\n   lower-case.  Returns 1 for a successful match, 0 otherwise. */\n\nstatic int\ncase_insensitive_match(const char *s, const char *t)\n{\n    while(*t && Py_TOLOWER(*s) == *t) {\n        s++;\n        t++;\n    }\n    return *t ? 0 : 1;\n}\n\n/* _Py_parse_inf_or_nan: Attempt to parse a string of the form \"nan\", \"inf\" or\n   \"infinity\", with an optional leading sign of \"+\" or \"-\".  On success,\n   return the NaN or Infinity as a double and set *endptr to point just beyond\n   the successfully parsed portion of the string.  On failure, return -1.0 and\n   set *endptr to point to the start of the string. */\ndouble\n_Py_parse_inf_or_nan(const char *p, char **endptr)\n{\n    double retval;\n    const char *s;\n    int negate = 0;\n\n    s = p;\n    if (*s == '-') {\n        negate = 1;\n        s++;\n    }\n    else if (*s == '+') {\n        s++;\n    }\n    if (case_insensitive_match(s, \"inf\")) {\n        s += 3;\n        if (case_insensitive_match(s, \"inity\"))\n            s += 5;\n        retval = negate ? -Py_HUGE_VAL : Py_HUGE_VAL;\n    }\n    else if (case_insensitive_match(s, \"nan\")) {\n        s += 3;\n        retval = negate ? -fabs(Py_NAN) : fabs(Py_NAN);\n    }\n    else {\n        s = p;\n        retval = -1.0;\n    }\n    *endptr = (char *)s;\n    return retval;\n}\n\n\n/**\n * _PyOS_ascii_strtod:\n * @nptr:    the string to convert to a numeric value.\n * @endptr:  if non-%NULL, it returns the character after\n *           the last character used in the conversion.\n *\n * Converts a string to a #gdouble value.\n * This function behaves like the standard strtod() function\n * does in the C locale. It does this without actually\n * changing the current locale, since that would not be\n * thread-safe.\n *\n * This function is typically used when reading configuration\n * files or other non-user input that should be locale independent.\n * To handle input from the user you should normally use the\n * locale-sensitive system strtod() function.\n *\n * If the correct value would cause overflow, plus or minus %HUGE_VAL\n * is returned (according to the sign of the value), and %ERANGE is\n * stored in %errno. If the correct value would cause underflow,\n * zero is returned and %ERANGE is stored in %errno.\n * If memory allocation fails, %ENOMEM is stored in %errno.\n *\n * This function resets %errno before calling strtod() so that\n * you can reliably detect overflow and underflow.\n *\n * Return value: the #gdouble value.\n **/\n\n#if _PY_SHORT_FLOAT_REPR == 1\n\nstatic double\n_PyOS_ascii_strtod(const char *nptr, char **endptr)\n{\n    double result;\n    _Py_SET_53BIT_PRECISION_HEADER;\n\n    assert(nptr != NULL);\n    /* Set errno to zero, so that we can distinguish zero results\n       and underflows */\n    errno = 0;\n\n    _Py_SET_53BIT_PRECISION_START;\n    result = _Py_dg_strtod(nptr, endptr);\n    _Py_SET_53BIT_PRECISION_END;\n\n    if (*endptr == nptr)\n        /* string might represent an inf or nan */\n        result = _Py_parse_inf_or_nan(nptr, endptr);\n\n    return result;\n\n}\n\n#else\n\n/*\n   Use system strtod;  since strtod is locale aware, we may\n   have to first fix the decimal separator.\n\n   Note that unlike _Py_dg_strtod, the system strtod may not always give\n   correctly rounded results.\n*/\n\nstatic double\n_PyOS_ascii_strtod(const char *nptr, char **endptr)\n{\n    char *fail_pos;\n    double val;\n    struct lconv *locale_data;\n    const char *decimal_point;\n    size_t decimal_point_len;\n    const char *p, *decimal_point_pos;\n    const char *end = NULL; /* Silence gcc */\n    const char *digits_pos = NULL;\n    int negate = 0;\n\n    assert(nptr != NULL);\n\n    fail_pos = NULL;\n\n    locale_data = localeconv();\n    decimal_point = locale_data->decimal_point;\n    decimal_point_len = strlen(decimal_point);\n\n    assert(decimal_point_len != 0);\n\n    decimal_point_pos = NULL;\n\n    /* Parse infinities and nans */\n    val = _Py_parse_inf_or_nan(nptr, endptr);\n    if (*endptr != nptr)\n        return val;\n\n    /* Set errno to zero, so that we can distinguish zero results\n       and underflows */\n    errno = 0;\n\n    /* We process the optional sign manually, then pass the remainder to\n       the system strtod.  This ensures that the result of an underflow\n       has the correct sign. (bug #1725)  */\n    p = nptr;\n    /* Process leading sign, if present */\n    if (*p == '-') {\n        negate = 1;\n        p++;\n    }\n    else if (*p == '+') {\n        p++;\n    }\n\n    /* Some platform strtods accept hex floats; Python shouldn't (at the\n       moment), so we check explicitly for strings starting with '0x'. */\n    if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X'))\n        goto invalid_string;\n\n    /* Check that what's left begins with a digit or decimal point */\n    if (!Py_ISDIGIT(*p) && *p != '.')\n        goto invalid_string;\n\n    digits_pos = p;\n    if (decimal_point[0] != '.' ||\n        decimal_point[1] != 0)\n    {\n        /* Look for a '.' in the input; if present, it'll need to be\n           swapped for the current locale's decimal point before we\n           call strtod.  On the other hand, if we find the current\n           locale's decimal point then the input is invalid. */\n        while (Py_ISDIGIT(*p))\n            p++;\n\n        if (*p == '.')\n        {\n            decimal_point_pos = p++;\n\n            /* locate end of number */\n            while (Py_ISDIGIT(*p))\n                p++;\n\n            if (*p == 'e' || *p == 'E')\n                p++;\n            if (*p == '+' || *p == '-')\n                p++;\n            while (Py_ISDIGIT(*p))\n                p++;\n            end = p;\n        }\n        else if (strncmp(p, decimal_point, decimal_point_len) == 0)\n            /* Python bug #1417699 */\n            goto invalid_string;\n        /* For the other cases, we need not convert the decimal\n           point */\n    }\n\n    if (decimal_point_pos) {\n        char *copy, *c;\n        /* Create a copy of the input, with the '.' converted to the\n           locale-specific decimal point */\n        copy = (char *)PyMem_Malloc(end - digits_pos +\n                                    1 + decimal_point_len);\n        if (copy == NULL) {\n            *endptr = (char *)nptr;\n            errno = ENOMEM;\n            return val;\n        }\n\n        c = copy;\n        memcpy(c, digits_pos, decimal_point_pos - digits_pos);\n        c += decimal_point_pos - digits_pos;\n        memcpy(c, decimal_point, decimal_point_len);\n        c += decimal_point_len;\n        memcpy(c, decimal_point_pos + 1,\n               end - (decimal_point_pos + 1));\n        c += end - (decimal_point_pos + 1);\n        *c = 0;\n\n        val = strtod(copy, &fail_pos);\n\n        if (fail_pos)\n        {\n            if (fail_pos > decimal_point_pos)\n                fail_pos = (char *)digits_pos +\n                    (fail_pos - copy) -\n                    (decimal_point_len - 1);\n            else\n                fail_pos = (char *)digits_pos +\n                    (fail_pos - copy);\n        }\n\n        PyMem_Free(copy);\n\n    }\n    else {\n        val = strtod(digits_pos, &fail_pos);\n    }\n\n    if (fail_pos == digits_pos)\n        goto invalid_string;\n\n    if (negate && fail_pos != nptr)\n        val = -val;\n    *endptr = fail_pos;\n\n    return val;\n\n  invalid_string:\n    *endptr = (char*)nptr;\n    errno = EINVAL;\n    return -1.0;\n}\n\n#endif\n\n/* PyOS_string_to_double converts a null-terminated byte string s (interpreted\n   as a string of ASCII characters) to a float.  The string should not have\n   leading or trailing whitespace.  The conversion is independent of the\n   current locale.\n\n   If endptr is NULL, try to convert the whole string.  Raise ValueError and\n   return -1.0 if the string is not a valid representation of a floating-point\n   number.\n\n   If endptr is non-NULL, try to convert as much of the string as possible.\n   If no initial segment of the string is the valid representation of a\n   floating-point number then *endptr is set to point to the beginning of the\n   string, -1.0 is returned and again ValueError is raised.\n\n   On overflow (e.g., when trying to convert '1e500' on an IEEE 754 machine),\n   if overflow_exception is NULL then +-Py_HUGE_VAL is returned, and no Python\n   exception is raised.  Otherwise, overflow_exception should point to\n   a Python exception, this exception will be raised, -1.0 will be returned,\n   and *endptr will point just past the end of the converted value.\n\n   If any other failure occurs (for example lack of memory), -1.0 is returned\n   and the appropriate Python exception will have been set.\n*/\n\ndouble\nPyOS_string_to_double(const char *s,\n                      char **endptr,\n                      PyObject *overflow_exception)\n{\n    double x, result=-1.0;\n    char *fail_pos;\n\n    errno = 0;\n    x = _PyOS_ascii_strtod(s, &fail_pos);\n\n    if (errno == ENOMEM) {\n        PyErr_NoMemory();\n        fail_pos = (char *)s;\n    }\n    else if (!endptr && (fail_pos == s || *fail_pos != '\\0'))\n        PyErr_Format(PyExc_ValueError,\n                      \"could not convert string to float: \"\n                      \"'%.200s'\", s);\n    else if (fail_pos == s)\n        PyErr_Format(PyExc_ValueError,\n                      \"could not convert string to float: \"\n                      \"'%.200s'\", s);\n    else if (errno == ERANGE && fabs(x) >= 1.0 && overflow_exception)\n        PyErr_Format(overflow_exception,\n                      \"value too large to convert to float: \"\n                      \"'%.200s'\", s);\n    else\n        result = x;\n\n    if (endptr != NULL)\n        *endptr = fail_pos;\n    return result;\n}\n\n/* Remove underscores that follow the underscore placement rule from\n   the string and then call the `innerfunc` function on the result.\n   It should return a new object or NULL on exception.\n\n   `what` is used for the error message emitted when underscores are detected\n   that don't follow the rule. `arg` is an opaque pointer passed to the inner\n   function.\n\n   This is used to implement underscore-agnostic conversion for floats\n   and complex numbers.\n*/\nPyObject *\n_Py_string_to_number_with_underscores(\n    const char *s, Py_ssize_t orig_len, const char *what, PyObject *obj, void *arg,\n    PyObject *(*innerfunc)(const char *, Py_ssize_t, void *))\n{\n    char prev;\n    const char *p, *last;\n    char *dup, *end;\n    PyObject *result;\n\n    assert(s[orig_len] == '\\0');\n\n    if (strchr(s, '_') == NULL) {\n        return innerfunc(s, orig_len, arg);\n    }\n\n    dup = PyMem_Malloc(orig_len + 1);\n    if (dup == NULL) {\n        return PyErr_NoMemory();\n    }\n    end = dup;\n    prev = '\\0';\n    last = s + orig_len;\n    for (p = s; *p; p++) {\n        if (*p == '_') {\n            /* Underscores are only allowed after digits. */\n            if (!(prev >= '0' && prev <= '9')) {\n                goto error;\n            }\n        }\n        else {\n            *end++ = *p;\n            /* Underscores are only allowed before digits. */\n            if (prev == '_' && !(*p >= '0' && *p <= '9')) {\n                goto error;\n            }\n        }\n        prev = *p;\n    }\n    /* Underscores are not allowed at the end. */\n    if (prev == '_') {\n        goto error;\n    }\n    /* No embedded NULs allowed. */\n    if (p != last) {\n        goto error;\n    }\n    *end = '\\0';\n    result = innerfunc(dup, end - dup, arg);\n    PyMem_Free(dup);\n    return result;\n\n  error:\n    PyMem_Free(dup);\n    PyErr_Format(PyExc_ValueError,\n                 \"could not convert string to %s: \"\n                 \"%R\", what, obj);\n    return NULL;\n}\n\n#if _PY_SHORT_FLOAT_REPR == 0\n\n/* Given a string that may have a decimal point in the current\n   locale, change it back to a dot.  Since the string cannot get\n   longer, no need for a maximum buffer size parameter. */\nPy_LOCAL_INLINE(void)\nchange_decimal_from_locale_to_dot(char* buffer)\n{\n    struct lconv *locale_data = localeconv();\n    const char *decimal_point = locale_data->decimal_point;\n\n    if (decimal_point[0] != '.' || decimal_point[1] != 0) {\n        size_t decimal_point_len = strlen(decimal_point);\n\n        if (*buffer == '+' || *buffer == '-')\n            buffer++;\n        while (Py_ISDIGIT(*buffer))\n            buffer++;\n        if (strncmp(buffer, decimal_point, decimal_point_len) == 0) {\n            *buffer = '.';\n            buffer++;\n            if (decimal_point_len > 1) {\n                /* buffer needs to get smaller */\n                size_t rest_len = strlen(buffer +\n                                     (decimal_point_len - 1));\n                memmove(buffer,\n                    buffer + (decimal_point_len - 1),\n                    rest_len);\n                buffer[rest_len] = 0;\n            }\n        }\n    }\n}\n\n\n/* From the C99 standard, section 7.19.6:\nThe exponent always contains at least two digits, and only as many more digits\nas necessary to represent the exponent.\n*/\n#define MIN_EXPONENT_DIGITS 2\n\n/* Ensure that any exponent, if present, is at least MIN_EXPONENT_DIGITS\n   in length. */\nPy_LOCAL_INLINE(void)\nensure_minimum_exponent_length(char* buffer, size_t buf_size)\n{\n    char *p = strpbrk(buffer, \"eE\");\n    if (p && (*(p + 1) == '-' || *(p + 1) == '+')) {\n        char *start = p + 2;\n        int exponent_digit_cnt = 0;\n        int leading_zero_cnt = 0;\n        int in_leading_zeros = 1;\n        int significant_digit_cnt;\n\n        /* Skip over the exponent and the sign. */\n        p += 2;\n\n        /* Find the end of the exponent, keeping track of leading\n           zeros. */\n        while (*p && Py_ISDIGIT(*p)) {\n            if (in_leading_zeros && *p == '0')\n                ++leading_zero_cnt;\n            if (*p != '0')\n                in_leading_zeros = 0;\n            ++p;\n            ++exponent_digit_cnt;\n        }\n\n        significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt;\n        if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) {\n            /* If there are 2 exactly digits, we're done,\n               regardless of what they contain */\n        }\n        else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) {\n            int extra_zeros_cnt;\n\n            /* There are more than 2 digits in the exponent.  See\n               if we can delete some of the leading zeros */\n            if (significant_digit_cnt < MIN_EXPONENT_DIGITS)\n                significant_digit_cnt = MIN_EXPONENT_DIGITS;\n            extra_zeros_cnt = exponent_digit_cnt -\n                significant_digit_cnt;\n\n            /* Delete extra_zeros_cnt worth of characters from the\n               front of the exponent */\n            assert(extra_zeros_cnt >= 0);\n\n            /* Add one to significant_digit_cnt to copy the\n               trailing 0 byte, thus setting the length */\n            memmove(start,\n                start + extra_zeros_cnt,\n                significant_digit_cnt + 1);\n        }\n        else {\n            /* If there are fewer than 2 digits, add zeros\n               until there are 2, if there's enough room */\n            int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt;\n            if (start + zeros + exponent_digit_cnt + 1\n                  < buffer + buf_size) {\n                memmove(start + zeros, start,\n                    exponent_digit_cnt + 1);\n                memset(start, '0', zeros);\n            }\n        }\n    }\n}\n\n/* Remove trailing zeros after the decimal point from a numeric string; also\n   remove the decimal point if all digits following it are zero.  The numeric\n   string must end in '\\0', and should not have any leading or trailing\n   whitespace.  Assumes that the decimal point is '.'. */\nPy_LOCAL_INLINE(void)\nremove_trailing_zeros(char *buffer)\n{\n    char *old_fraction_end, *new_fraction_end, *end, *p;\n\n    p = buffer;\n    if (*p == '-' || *p == '+')\n        /* Skip leading sign, if present */\n        ++p;\n    while (Py_ISDIGIT(*p))\n        ++p;\n\n    /* if there's no decimal point there's nothing to do */\n    if (*p++ != '.')\n        return;\n\n    /* scan any digits after the point */\n    while (Py_ISDIGIT(*p))\n        ++p;\n    old_fraction_end = p;\n\n    /* scan up to ending '\\0' */\n    while (*p != '\\0')\n        p++;\n    /* +1 to make sure that we move the null byte as well */\n    end = p+1;\n\n    /* scan back from fraction_end, looking for removable zeros */\n    p = old_fraction_end;\n    while (*(p-1) == '0')\n        --p;\n    /* and remove point if we've got that far */\n    if (*(p-1) == '.')\n        --p;\n    new_fraction_end = p;\n\n    memmove(new_fraction_end, old_fraction_end, end-old_fraction_end);\n}\n\n/* Ensure that buffer has a decimal point in it.  The decimal point will not\n   be in the current locale, it will always be '.'. Don't add a decimal point\n   if an exponent is present.  Also, convert to exponential notation where\n   adding a '.0' would produce too many significant digits (see issue 5864).\n\n   Returns a pointer to the fixed buffer, or NULL on failure.\n*/\nPy_LOCAL_INLINE(char *)\nensure_decimal_point(char* buffer, size_t buf_size, int precision)\n{\n    int digit_count, insert_count = 0, convert_to_exp = 0;\n    const char *chars_to_insert;\n    char *digits_start;\n\n    /* search for the first non-digit character */\n    char *p = buffer;\n    if (*p == '-' || *p == '+')\n        /* Skip leading sign, if present.  I think this could only\n           ever be '-', but it can't hurt to check for both. */\n        ++p;\n    digits_start = p;\n    while (*p && Py_ISDIGIT(*p))\n        ++p;\n    digit_count = Py_SAFE_DOWNCAST(p - digits_start, Py_ssize_t, int);\n\n    if (*p == '.') {\n        if (Py_ISDIGIT(*(p+1))) {\n            /* Nothing to do, we already have a decimal\n               point and a digit after it */\n        }\n        else {\n            /* We have a decimal point, but no following\n               digit.  Insert a zero after the decimal. */\n            /* can't ever get here via PyOS_double_to_string */\n            assert(precision == -1);\n            ++p;\n            chars_to_insert = \"0\";\n            insert_count = 1;\n        }\n    }\n    else if (!(*p == 'e' || *p == 'E')) {\n        /* Don't add \".0\" if we have an exponent. */\n        if (digit_count == precision) {\n            /* issue 5864: don't add a trailing .0 in the case\n               where the '%g'-formatted result already has as many\n               significant digits as were requested.  Switch to\n               exponential notation instead. */\n            convert_to_exp = 1;\n            /* no exponent, no point, and we shouldn't land here\n               for infs and nans, so we must be at the end of the\n               string. */\n            assert(*p == '\\0');\n        }\n        else {\n            assert(precision == -1 || digit_count < precision);\n            chars_to_insert = \".0\";\n            insert_count = 2;\n        }\n    }\n    if (insert_count) {\n        size_t buf_len = strlen(buffer);\n        if (buf_len + insert_count + 1 >= buf_size) {\n            /* If there is not enough room in the buffer\n               for the additional text, just skip it.  It's\n               not worth generating an error over. */\n        }\n        else {\n            memmove(p + insert_count, p,\n                buffer + strlen(buffer) - p + 1);\n            memcpy(p, chars_to_insert, insert_count);\n        }\n    }\n    if (convert_to_exp) {\n        int written;\n        size_t buf_avail;\n        p = digits_start;\n        /* insert decimal point */\n        assert(digit_count >= 1);\n        memmove(p+2, p+1, digit_count); /* safe, but overwrites nul */\n        p[1] = '.';\n        p += digit_count+1;\n        assert(p <= buf_size+buffer);\n        buf_avail = buf_size+buffer-p;\n        if (buf_avail == 0)\n            return NULL;\n        /* Add exponent.  It's okay to use lower case 'e': we only\n           arrive here as a result of using the empty format code or\n           repr/str builtins and those never want an upper case 'E' */\n        written = PyOS_snprintf(p, buf_avail, \"e%+.02d\", digit_count-1);\n        if (!(0 <= written &&\n              written < Py_SAFE_DOWNCAST(buf_avail, size_t, int)))\n            /* output truncated, or something else bad happened */\n            return NULL;\n        remove_trailing_zeros(buffer);\n    }\n    return buffer;\n}\n\n/* see FORMATBUFLEN in unicodeobject.c */\n#define FLOAT_FORMATBUFLEN 120\n\n/**\n * _PyOS_ascii_formatd:\n * @buffer: A buffer to place the resulting string in\n * @buf_size: The length of the buffer.\n * @format: The printf()-style format to use for the\n *          code to use for converting.\n * @d: The #gdouble to convert\n * @precision: The precision to use when formatting.\n *\n * Converts a #gdouble to a string, using the '.' as\n * decimal point. To format the number you pass in\n * a printf()-style format string. Allowed conversion\n * specifiers are 'e', 'E', 'f', 'F', 'g', 'G', and 'Z'.\n *\n * 'Z' is the same as 'g', except it always has a decimal and\n *     at least one digit after the decimal.\n *\n * Return value: The pointer to the buffer with the converted string.\n * On failure returns NULL but does not set any Python exception.\n **/\nstatic char *\n_PyOS_ascii_formatd(char       *buffer,\n                   size_t      buf_size,\n                   const char *format,\n                   double      d,\n                   int         precision)\n{\n    char format_char;\n    size_t format_len = strlen(format);\n\n    /* Issue 2264: code 'Z' requires copying the format.  'Z' is 'g', but\n       also with at least one character past the decimal. */\n    char tmp_format[FLOAT_FORMATBUFLEN];\n\n    /* The last character in the format string must be the format char */\n    format_char = format[format_len - 1];\n\n    if (format[0] != '%')\n        return NULL;\n\n    /* I'm not sure why this test is here.  It's ensuring that the format\n       string after the first character doesn't have a single quote, a\n       lowercase l, or a percent. This is the reverse of the commented-out\n       test about 10 lines ago. */\n    if (strpbrk(format + 1, \"'l%\"))\n        return NULL;\n\n    /* Also curious about this function is that it accepts format strings\n       like \"%xg\", which are invalid for floats.  In general, the\n       interface to this function is not very good, but changing it is\n       difficult because it's a public API. */\n\n    if (!(format_char == 'e' || format_char == 'E' ||\n          format_char == 'f' || format_char == 'F' ||\n          format_char == 'g' || format_char == 'G' ||\n          format_char == 'Z'))\n        return NULL;\n\n    /* Map 'Z' format_char to 'g', by copying the format string and\n       replacing the final char with a 'g' */\n    if (format_char == 'Z') {\n        if (format_len + 1 >= sizeof(tmp_format)) {\n            /* The format won't fit in our copy.  Error out.  In\n               practice, this will never happen and will be\n               detected by returning NULL */\n            return NULL;\n        }\n        strcpy(tmp_format, format);\n        tmp_format[format_len - 1] = 'g';\n        format = tmp_format;\n    }\n\n\n    /* Have PyOS_snprintf do the hard work */\n    PyOS_snprintf(buffer, buf_size, format, d);\n\n    /* Do various fixups on the return string */\n\n    /* Get the current locale, and find the decimal point string.\n       Convert that string back to a dot. */\n    change_decimal_from_locale_to_dot(buffer);\n\n    /* If an exponent exists, ensure that the exponent is at least\n       MIN_EXPONENT_DIGITS digits, providing the buffer is large enough\n       for the extra zeros.  Also, if there are more than\n       MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get\n       back to MIN_EXPONENT_DIGITS */\n    ensure_minimum_exponent_length(buffer, buf_size);\n\n    /* If format_char is 'Z', make sure we have at least one character\n       after the decimal point (and make sure we have a decimal point);\n       also switch to exponential notation in some edge cases where the\n       extra character would produce more significant digits that we\n       really want. */\n    if (format_char == 'Z')\n        buffer = ensure_decimal_point(buffer, buf_size, precision);\n\n    return buffer;\n}\n\n/* The fallback code to use if _Py_dg_dtoa is not available. */\n\nchar * PyOS_double_to_string(double val,\n                                         char format_code,\n                                         int precision,\n                                         int flags,\n                                         int *type)\n{\n    char format[32];\n    Py_ssize_t bufsize;\n    char *buf;\n    int t, exp;\n    int upper = 0;\n\n    /* Validate format_code, and map upper and lower case */\n    switch (format_code) {\n    case 'e':          /* exponent */\n    case 'f':          /* fixed */\n    case 'g':          /* general */\n        break;\n    case 'E':\n        upper = 1;\n        format_code = 'e';\n        break;\n    case 'F':\n        upper = 1;\n        format_code = 'f';\n        break;\n    case 'G':\n        upper = 1;\n        format_code = 'g';\n        break;\n    case 'r':          /* repr format */\n        /* Supplied precision is unused, must be 0. */\n        if (precision != 0) {\n            PyErr_BadInternalCall();\n            return NULL;\n        }\n        /* The repr() precision (17 significant decimal digits) is the\n           minimal number that is guaranteed to have enough precision\n           so that if the number is read back in the exact same binary\n           value is recreated.  This is true for IEEE floating point\n           by design, and also happens to work for all other modern\n           hardware. */\n        precision = 17;\n        format_code = 'g';\n        break;\n    default:\n        PyErr_BadInternalCall();\n        return NULL;\n    }\n\n    /* Here's a quick-and-dirty calculation to figure out how big a buffer\n       we need.  In general, for a finite float we need:\n\n         1 byte for each digit of the decimal significand, and\n\n         1 for a possible sign\n         1 for a possible decimal point\n         2 for a possible [eE][+-]\n         1 for each digit of the exponent;  if we allow 19 digits\n           total then we're safe up to exponents of 2**63.\n         1 for the trailing nul byte\n\n       This gives a total of 24 + the number of digits in the significand,\n       and the number of digits in the significand is:\n\n         for 'g' format: at most precision, except possibly\n           when precision == 0, when it's 1.\n         for 'e' format: precision+1\n         for 'f' format: precision digits after the point, at least 1\n           before.  To figure out how many digits appear before the point\n           we have to examine the size of the number.  If fabs(val) < 1.0\n           then there will be only one digit before the point.  If\n           fabs(val) >= 1.0, then there are at most\n\n         1+floor(log10(ceiling(fabs(val))))\n\n           digits before the point (where the 'ceiling' allows for the\n           possibility that the rounding rounds the integer part of val\n           up).  A safe upper bound for the above quantity is\n           1+floor(exp/3), where exp is the unique integer such that 0.5\n           <= fabs(val)/2**exp < 1.0.  This exp can be obtained from\n           frexp.\n\n       So we allow room for precision+1 digits for all formats, plus an\n       extra floor(exp/3) digits for 'f' format.\n\n    */\n\n    if (Py_IS_NAN(val) || Py_IS_INFINITY(val))\n        /* 3 for 'inf'/'nan', 1 for sign, 1 for '\\0' */\n        bufsize = 5;\n    else {\n        bufsize = 25 + precision;\n        if (format_code == 'f' && fabs(val) >= 1.0) {\n            frexp(val, &exp);\n            bufsize += exp/3;\n        }\n    }\n\n    buf = PyMem_Malloc(bufsize);\n    if (buf == NULL) {\n        PyErr_NoMemory();\n        return NULL;\n    }\n\n    /* Handle nan and inf. */\n    if (Py_IS_NAN(val)) {\n        strcpy(buf, \"nan\");\n        t = Py_DTST_NAN;\n    } else if (Py_IS_INFINITY(val)) {\n        if (copysign(1., val) == 1.)\n            strcpy(buf, \"inf\");\n        else\n            strcpy(buf, \"-inf\");\n        t = Py_DTST_INFINITE;\n    } else {\n        t = Py_DTST_FINITE;\n        if (flags & Py_DTSF_ADD_DOT_0)\n            format_code = 'Z';\n\n        PyOS_snprintf(format, sizeof(format), \"%%%s.%i%c\",\n                      (flags & Py_DTSF_ALT ? \"#\" : \"\"), precision,\n                      format_code);\n        _PyOS_ascii_formatd(buf, bufsize, format, val, precision);\n\n        if (flags & Py_DTSF_NO_NEG_0 && buf[0] == '-') {\n            char *buf2 = buf + 1;\n            while (*buf2 == '0' || *buf2 == '.') {\n                ++buf2;\n            }\n            if (*buf2 == 0 || *buf2 == 'e') {\n                size_t len = buf2 - buf + strlen(buf2);\n                assert(buf[len] == 0);\n                memmove(buf, buf+1, len);\n            }\n        }\n    }\n\n    /* Add sign when requested.  It's convenient (esp. when formatting\n     complex numbers) to include a sign even for inf and nan. */\n    if (flags & Py_DTSF_SIGN && buf[0] != '-') {\n        size_t len = strlen(buf);\n        /* the bufsize calculations above should ensure that we've got\n           space to add a sign */\n        assert((size_t)bufsize >= len+2);\n        memmove(buf+1, buf, len+1);\n        buf[0] = '+';\n    }\n    if (upper) {\n        /* Convert to upper case. */\n        char *p1;\n        for (p1 = buf; *p1; p1++)\n            *p1 = Py_TOUPPER(*p1);\n    }\n\n    if (type)\n        *type = t;\n    return buf;\n}\n\n#else  // _PY_SHORT_FLOAT_REPR == 1\n\n/* _Py_dg_dtoa is available. */\n\n/* I'm using a lookup table here so that I don't have to invent a non-locale\n   specific way to convert to uppercase */\n#define OFS_INF 0\n#define OFS_NAN 1\n#define OFS_E 2\n\n/* The lengths of these are known to the code below, so don't change them */\nstatic const char * const lc_float_strings[] = {\n    \"inf\",\n    \"nan\",\n    \"e\",\n};\nstatic const char * const uc_float_strings[] = {\n    \"INF\",\n    \"NAN\",\n    \"E\",\n};\n\n\n/* Convert a double d to a string, and return a PyMem_Malloc'd block of\n   memory contain the resulting string.\n\n   Arguments:\n     d is the double to be converted\n     format_code is one of 'e', 'f', 'g', 'r'.  'e', 'f' and 'g'\n       correspond to '%e', '%f' and '%g';  'r' corresponds to repr.\n     mode is one of '0', '2' or '3', and is completely determined by\n       format_code: 'e' and 'g' use mode 2; 'f' mode 3, 'r' mode 0.\n     precision is the desired precision\n     always_add_sign is nonzero if a '+' sign should be included for positive\n       numbers\n     add_dot_0_if_integer is nonzero if integers in non-exponential form\n       should have \".0\" added.  Only applies to format codes 'r' and 'g'.\n     use_alt_formatting is nonzero if alternative formatting should be\n       used.  Only applies to format codes 'e', 'f' and 'g'.  For code 'g',\n       at most one of use_alt_formatting and add_dot_0_if_integer should\n       be nonzero.\n     type, if non-NULL, will be set to one of these constants to identify\n       the type of the 'd' argument:\n     Py_DTST_FINITE\n     Py_DTST_INFINITE\n     Py_DTST_NAN\n\n   Returns a PyMem_Malloc'd block of memory containing the resulting string,\n    or NULL on error. If NULL is returned, the Python error has been set.\n */\n\nstatic char *\nformat_float_short(double d, char format_code,\n                   int mode, int precision,\n                   int always_add_sign, int add_dot_0_if_integer,\n                   int use_alt_formatting, int no_negative_zero,\n                   const char * const *float_strings, int *type)\n{\n    char *buf = NULL;\n    char *p = NULL;\n    Py_ssize_t bufsize = 0;\n    char *digits, *digits_end;\n    int decpt_as_int, sign, exp_len, exp = 0, use_exp = 0;\n    Py_ssize_t decpt, digits_len, vdigits_start, vdigits_end;\n    _Py_SET_53BIT_PRECISION_HEADER;\n\n    /* _Py_dg_dtoa returns a digit string (no decimal point or exponent).\n       Must be matched by a call to _Py_dg_freedtoa. */\n    _Py_SET_53BIT_PRECISION_START;\n    digits = _Py_dg_dtoa(d, mode, precision, &decpt_as_int, &sign,\n                         &digits_end);\n    _Py_SET_53BIT_PRECISION_END;\n\n    decpt = (Py_ssize_t)decpt_as_int;\n    if (digits == NULL) {\n        /* The only failure mode is no memory. */\n        PyErr_NoMemory();\n        goto exit;\n    }\n    assert(digits_end != NULL && digits_end >= digits);\n    digits_len = digits_end - digits;\n\n    if (no_negative_zero && sign == 1 &&\n            (digits_len == 0 || (digits_len == 1 && digits[0] == '0'))) {\n        sign = 0;\n    }\n\n    if (digits_len && !Py_ISDIGIT(digits[0])) {\n        /* Infinities and nans here; adapt Gay's output,\n           so convert Infinity to inf and NaN to nan, and\n           ignore sign of nan. Then return. */\n\n        /* ignore the actual sign of a nan */\n        if (digits[0] == 'n' || digits[0] == 'N')\n            sign = 0;\n\n        /* We only need 5 bytes to hold the result \"+inf\\0\" . */\n        bufsize = 5; /* Used later in an assert. */\n        buf = (char *)PyMem_Malloc(bufsize);\n        if (buf == NULL) {\n            PyErr_NoMemory();\n            goto exit;\n        }\n        p = buf;\n\n        if (sign == 1) {\n            *p++ = '-';\n        }\n        else if (always_add_sign) {\n            *p++ = '+';\n        }\n        if (digits[0] == 'i' || digits[0] == 'I') {\n            strncpy(p, float_strings[OFS_INF], 3);\n            p += 3;\n\n            if (type)\n                *type = Py_DTST_INFINITE;\n        }\n        else if (digits[0] == 'n' || digits[0] == 'N') {\n            strncpy(p, float_strings[OFS_NAN], 3);\n            p += 3;\n\n            if (type)\n                *type = Py_DTST_NAN;\n        }\n        else {\n            /* shouldn't get here: Gay's code should always return\n               something starting with a digit, an 'I',  or 'N' */\n            Py_UNREACHABLE();\n        }\n        goto exit;\n    }\n\n    /* The result must be finite (not inf or nan). */\n    if (type)\n        *type = Py_DTST_FINITE;\n\n\n    /* We got digits back, format them.  We may need to pad 'digits'\n       either on the left or right (or both) with extra zeros, so in\n       general the resulting string has the form\n\n         [<sign>]<zeros><digits><zeros>[<exponent>]\n\n       where either of the <zeros> pieces could be empty, and there's a\n       decimal point that could appear either in <digits> or in the\n       leading or trailing <zeros>.\n\n       Imagine an infinite 'virtual' string vdigits, consisting of the\n       string 'digits' (starting at index 0) padded on both the left and\n       right with infinite strings of zeros.  We want to output a slice\n\n         vdigits[vdigits_start : vdigits_end]\n\n       of this virtual string.  Thus if vdigits_start < 0 then we'll end\n       up producing some leading zeros; if vdigits_end > digits_len there\n       will be trailing zeros in the output.  The next section of code\n       determines whether to use an exponent or not, figures out the\n       position 'decpt' of the decimal point, and computes 'vdigits_start'\n       and 'vdigits_end'. */\n    vdigits_end = digits_len;\n    switch (format_code) {\n    case 'e':\n        use_exp = 1;\n        vdigits_end = precision;\n        break;\n    case 'f':\n        vdigits_end = decpt + precision;\n        break;\n    case 'g':\n        if (decpt <= -4 || decpt >\n            (add_dot_0_if_integer ? precision-1 : precision))\n            use_exp = 1;\n        if (use_alt_formatting)\n            vdigits_end = precision;\n        break;\n    case 'r':\n        /* convert to exponential format at 1e16.  We used to convert\n           at 1e17, but that gives odd-looking results for some values\n           when a 16-digit 'shortest' repr is padded with bogus zeros.\n           For example, repr(2e16+8) would give 20000000000000010.0;\n           the true value is 20000000000000008.0. */\n        if (decpt <= -4 || decpt > 16)\n            use_exp = 1;\n        break;\n    default:\n        PyErr_BadInternalCall();\n        goto exit;\n    }\n\n    /* if using an exponent, reset decimal point position to 1 and adjust\n       exponent accordingly.*/\n    if (use_exp) {\n        exp = (int)decpt - 1;\n        decpt = 1;\n    }\n    /* ensure vdigits_start < decpt <= vdigits_end, or vdigits_start <\n       decpt < vdigits_end if add_dot_0_if_integer and no exponent */\n    vdigits_start = decpt <= 0 ? decpt-1 : 0;\n    if (!use_exp && add_dot_0_if_integer)\n        vdigits_end = vdigits_end > decpt ? vdigits_end : decpt + 1;\n    else\n        vdigits_end = vdigits_end > decpt ? vdigits_end : decpt;\n\n    /* double check inequalities */\n    assert(vdigits_start <= 0 &&\n           0 <= digits_len &&\n           digits_len <= vdigits_end);\n    /* decimal point should be in (vdigits_start, vdigits_end] */\n    assert(vdigits_start < decpt && decpt <= vdigits_end);\n\n    /* Compute an upper bound how much memory we need. This might be a few\n       chars too long, but no big deal. */\n    bufsize =\n        /* sign, decimal point and trailing 0 byte */\n        3 +\n\n        /* total digit count (including zero padding on both sides) */\n        (vdigits_end - vdigits_start) +\n\n        /* exponent \"e+100\", max 3 numerical digits */\n        (use_exp ? 5 : 0);\n\n    /* Now allocate the memory and initialize p to point to the start of\n       it. */\n    buf = (char *)PyMem_Malloc(bufsize);\n    if (buf == NULL) {\n        PyErr_NoMemory();\n        goto exit;\n    }\n    p = buf;\n\n    /* Add a negative sign if negative, and a plus sign if non-negative\n       and always_add_sign is true. */\n    if (sign == 1)\n        *p++ = '-';\n    else if (always_add_sign)\n        *p++ = '+';\n\n    /* note that exactly one of the three 'if' conditions is true,\n       so we include exactly one decimal point */\n    /* Zero padding on left of digit string */\n    if (decpt <= 0) {\n        memset(p, '0', decpt-vdigits_start);\n        p += decpt - vdigits_start;\n        *p++ = '.';\n        memset(p, '0', 0-decpt);\n        p += 0-decpt;\n    }\n    else {\n        memset(p, '0', 0-vdigits_start);\n        p += 0 - vdigits_start;\n    }\n\n    /* Digits, with included decimal point */\n    if (0 < decpt && decpt <= digits_len) {\n        strncpy(p, digits, decpt-0);\n        p += decpt-0;\n        *p++ = '.';\n        strncpy(p, digits+decpt, digits_len-decpt);\n        p += digits_len-decpt;\n    }\n    else {\n        strncpy(p, digits, digits_len);\n        p += digits_len;\n    }\n\n    /* And zeros on the right */\n    if (digits_len < decpt) {\n        memset(p, '0', decpt-digits_len);\n        p += decpt-digits_len;\n        *p++ = '.';\n        memset(p, '0', vdigits_end-decpt);\n        p += vdigits_end-decpt;\n    }\n    else {\n        memset(p, '0', vdigits_end-digits_len);\n        p += vdigits_end-digits_len;\n    }\n\n    /* Delete a trailing decimal pt unless using alternative formatting. */\n    if (p[-1] == '.' && !use_alt_formatting)\n        p--;\n\n    /* Now that we've done zero padding, add an exponent if needed. */\n    if (use_exp) {\n        *p++ = float_strings[OFS_E][0];\n        exp_len = sprintf(p, \"%+.02d\", exp);\n        p += exp_len;\n    }\n  exit:\n    if (buf) {\n        *p = '\\0';\n        /* It's too late if this fails, as we've already stepped on\n           memory that isn't ours. But it's an okay debugging test. */\n        assert(p-buf < bufsize);\n    }\n    if (digits)\n        _Py_dg_freedtoa(digits);\n\n    return buf;\n}\n\n\nchar * PyOS_double_to_string(double val,\n                                         char format_code,\n                                         int precision,\n                                         int flags,\n                                         int *type)\n{\n    const char * const *float_strings = lc_float_strings;\n    int mode;\n\n    /* Validate format_code, and map upper and lower case. Compute the\n       mode and make any adjustments as needed. */\n    switch (format_code) {\n    /* exponent */\n    case 'E':\n        float_strings = uc_float_strings;\n        format_code = 'e';\n        /* Fall through. */\n    case 'e':\n        mode = 2;\n        precision++;\n        break;\n\n    /* fixed */\n    case 'F':\n        float_strings = uc_float_strings;\n        format_code = 'f';\n        /* Fall through. */\n    case 'f':\n        mode = 3;\n        break;\n\n    /* general */\n    case 'G':\n        float_strings = uc_float_strings;\n        format_code = 'g';\n        /* Fall through. */\n    case 'g':\n        mode = 2;\n        /* precision 0 makes no sense for 'g' format; interpret as 1 */\n        if (precision == 0)\n            precision = 1;\n        break;\n\n    /* repr format */\n    case 'r':\n        mode = 0;\n        /* Supplied precision is unused, must be 0. */\n        if (precision != 0) {\n            PyErr_BadInternalCall();\n            return NULL;\n        }\n        break;\n\n    default:\n        PyErr_BadInternalCall();\n        return NULL;\n    }\n\n    return format_float_short(val, format_code, mode, precision,\n                              flags & Py_DTSF_SIGN,\n                              flags & Py_DTSF_ADD_DOT_0,\n                              flags & Py_DTSF_ALT,\n                              flags & Py_DTSF_NO_NEG_0,\n                              float_strings, type);\n}\n#endif  // _PY_SHORT_FLOAT_REPR == 1\n"
  },
  {
    "path": "PyTime.c",
    "content": "#include \"Python.h\"\n#ifdef MS_WINDOWS\n#  include <winsock2.h>           // struct timeval\n#endif\n\n#if defined(__APPLE__)\n#  include <mach/mach_time.h>     // mach_absolute_time(), mach_timebase_info()\n\n#if defined(__APPLE__) && defined(__has_builtin)\n#  if __has_builtin(__builtin_available)\n#    define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)\n#  endif\n#endif\n#endif\n\n/* To millisecond (10^-3) */\n#define SEC_TO_MS 1000\n\n/* To microseconds (10^-6) */\n#define MS_TO_US 1000\n#define SEC_TO_US (SEC_TO_MS * MS_TO_US)\n\n/* To nanoseconds (10^-9) */\n#define US_TO_NS 1000\n#define MS_TO_NS (MS_TO_US * US_TO_NS)\n#define SEC_TO_NS (SEC_TO_MS * MS_TO_NS)\n\n/* Conversion from nanoseconds */\n#define NS_TO_MS (1000 * 1000)\n#define NS_TO_US (1000)\n#define NS_TO_100NS (100)\n\n#if SIZEOF_TIME_T == SIZEOF_LONG_LONG\n#  define PY_TIME_T_MAX LLONG_MAX\n#  define PY_TIME_T_MIN LLONG_MIN\n#elif SIZEOF_TIME_T == SIZEOF_LONG\n#  define PY_TIME_T_MAX LONG_MAX\n#  define PY_TIME_T_MIN LONG_MIN\n#else\n#  error \"unsupported time_t size\"\n#endif\n\n#if PY_TIME_T_MAX + PY_TIME_T_MIN != -1\n#  error \"time_t is not a two's complement integer type\"\n#endif\n\n#if _PyTime_MIN + _PyTime_MAX != -1\n#  error \"_PyTime_t is not a two's complement integer type\"\n#endif\n\n\nstatic void\npytime_time_t_overflow(void)\n{\n    PyErr_SetString(PyExc_OverflowError,\n                    \"timestamp out of range for platform time_t\");\n}\n\n\nstatic void\npytime_overflow(void)\n{\n    PyErr_SetString(PyExc_OverflowError,\n                    \"timestamp too large to convert to C _PyTime_t\");\n}\n\n\nstatic inline _PyTime_t\npytime_from_nanoseconds(_PyTime_t t)\n{\n    // _PyTime_t is a number of nanoseconds\n    return t;\n}\n\n\nstatic inline _PyTime_t\npytime_as_nanoseconds(_PyTime_t t)\n{\n    // _PyTime_t is a number of nanoseconds: see pytime_from_nanoseconds()\n    return t;\n}\n\n\n// Compute t1 + t2. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow.\nstatic inline int\npytime_add(_PyTime_t *t1, _PyTime_t t2)\n{\n    if (t2 > 0 && *t1 > _PyTime_MAX - t2) {\n        *t1 = _PyTime_MAX;\n        return -1;\n    }\n    else if (t2 < 0 && *t1 < _PyTime_MIN - t2) {\n        *t1 = _PyTime_MIN;\n        return -1;\n    }\n    else {\n        *t1 += t2;\n        return 0;\n    }\n}\n\n\n_PyTime_t\n_PyTime_Add(_PyTime_t t1, _PyTime_t t2)\n{\n    (void)pytime_add(&t1, t2);\n    return t1;\n}\n\n\nstatic inline int\npytime_mul_check_overflow(_PyTime_t a, _PyTime_t b)\n{\n    if (b != 0) {\n        assert(b > 0);\n        return ((a < _PyTime_MIN / b) || (_PyTime_MAX / b < a));\n    }\n    else {\n        return 0;\n    }\n}\n\n\n// Compute t * k. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow.\nstatic inline int\npytime_mul(_PyTime_t *t, _PyTime_t k)\n{\n    assert(k >= 0);\n    if (pytime_mul_check_overflow(*t, k)) {\n        *t = (*t >= 0) ? _PyTime_MAX : _PyTime_MIN;\n        return -1;\n    }\n    else {\n        *t *= k;\n        return 0;\n    }\n}\n\n\n// Compute t * k. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow.\nstatic inline _PyTime_t\n_PyTime_Mul(_PyTime_t t, _PyTime_t k)\n{\n    (void)pytime_mul(&t, k);\n    return t;\n}\n\n\n\n\n_PyTime_t\n_PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div)\n{\n    /* Compute (ticks * mul / div) in two parts to reduce the risk of integer\n       overflow: compute the integer part, and then the remaining part.\n\n       (ticks * mul) / div == (ticks / div) * mul + (ticks % div) * mul / div\n    */\n    _PyTime_t intpart, remaining;\n    intpart = ticks / div;\n    ticks %= div;\n    remaining = _PyTime_Mul(ticks, mul) / div;\n    // intpart * mul + remaining\n    return _PyTime_Add(_PyTime_Mul(intpart, mul), remaining);\n}\n\n\ntime_t\n_PyLong_AsTime_t(PyObject *obj)\n{\n#if SIZEOF_TIME_T == SIZEOF_LONG_LONG\n    long long val = PyLong_AsLongLong(obj);\n#elif SIZEOF_TIME_T <= SIZEOF_LONG\n    long val = PyLong_AsLong(obj);\n#else\n#   error \"unsupported time_t size\"\n#endif\n    if (val == -1 && PyErr_Occurred()) {\n        if (PyErr_ExceptionMatches(PyExc_OverflowError)) {\n            pytime_time_t_overflow();\n        }\n        return -1;\n    }\n    return (time_t)val;\n}\n\n\nPyObject *\n_PyLong_FromTime_t(time_t t)\n{\n#if SIZEOF_TIME_T == SIZEOF_LONG_LONG\n    return PyLong_FromLongLong((long long)t);\n#elif SIZEOF_TIME_T <= SIZEOF_LONG\n    return PyLong_FromLong((long)t);\n#else\n#   error \"unsupported time_t size\"\n#endif\n}\n\n\n// Convert _PyTime_t to time_t.\n// Return 0 on success. Return -1 and clamp the value on overflow.\nstatic int\n_PyTime_AsTime_t(_PyTime_t t, time_t *t2)\n{\n#if SIZEOF_TIME_T < _SIZEOF_PYTIME_T\n    if ((_PyTime_t)PY_TIME_T_MAX < t) {\n        *t2 = PY_TIME_T_MAX;\n        return -1;\n    }\n    if (t < (_PyTime_t)PY_TIME_T_MIN) {\n        *t2 = PY_TIME_T_MIN;\n        return -1;\n    }\n#endif\n    *t2 = (time_t)t;\n    return 0;\n}\n\n\n#ifdef MS_WINDOWS\n// Convert _PyTime_t to long.\n// Return 0 on success. Return -1 and clamp the value on overflow.\nstatic int\n_PyTime_AsLong(_PyTime_t t, long *t2)\n{\n#if SIZEOF_LONG < _SIZEOF_PYTIME_T\n    if ((_PyTime_t)LONG_MAX < t) {\n        *t2 = LONG_MAX;\n        return -1;\n    }\n    if (t < (_PyTime_t)LONG_MIN) {\n        *t2 = LONG_MIN;\n        return -1;\n    }\n#endif\n    *t2 = (long)t;\n    return 0;\n}\n#endif\n\n\n/* Round to nearest with ties going to nearest even integer\n   (_PyTime_ROUND_HALF_EVEN) */\nstatic double\npytime_round_half_even(double x)\n{\n    double rounded = round(x);\n    if (fabs(x-rounded) == 0.5) {\n        /* halfway case: round to even */\n        rounded = 2.0 * round(x / 2.0);\n    }\n    return rounded;\n}\n\n\nstatic double\npytime_round(double x, _PyTime_round_t round)\n{\n    /* volatile avoids optimization changing how numbers are rounded */\n    volatile double d;\n\n    d = x;\n    if (round == _PyTime_ROUND_HALF_EVEN) {\n        d = pytime_round_half_even(d);\n    }\n    else if (round == _PyTime_ROUND_CEILING) {\n        d = ceil(d);\n    }\n    else if (round == _PyTime_ROUND_FLOOR) {\n        d = floor(d);\n    }\n    else {\n        assert(round == _PyTime_ROUND_UP);\n        d = (d >= 0.0) ? ceil(d) : floor(d);\n    }\n    return d;\n}\n\n\nstatic int\npytime_double_to_denominator(double d, time_t *sec, long *numerator,\n                             long idenominator, _PyTime_round_t round)\n{\n    double denominator = (double)idenominator;\n    double intpart;\n    /* volatile avoids optimization changing how numbers are rounded */\n    volatile double floatpart;\n\n    floatpart = modf(d, &intpart);\n\n    floatpart *= denominator;\n    floatpart = pytime_round(floatpart, round);\n    if (floatpart >= denominator) {\n        floatpart -= denominator;\n        intpart += 1.0;\n    }\n    else if (floatpart < 0) {\n        floatpart += denominator;\n        intpart -= 1.0;\n    }\n    assert(0.0 <= floatpart && floatpart < denominator);\n\n    /*\n       Conversion of an out-of-range value to time_t gives undefined behaviour\n       (C99 §6.3.1.4p1), so we must guard against it. However, checking that\n       `intpart` is in range is delicate: the obvious expression `intpart <=\n       PY_TIME_T_MAX` will first convert the value `PY_TIME_T_MAX` to a double,\n       potentially changing its value and leading to us failing to catch some\n       UB-inducing values. The code below works correctly under the mild\n       assumption that time_t is a two's complement integer type with no trap\n       representation, and that `PY_TIME_T_MIN` is within the representable\n       range of a C double.\n\n       Note: we want the `if` condition below to be true for NaNs; therefore,\n       resist any temptation to simplify by applying De Morgan's laws.\n    */\n    if (!((double)PY_TIME_T_MIN <= intpart && intpart < -(double)PY_TIME_T_MIN)) {\n        pytime_time_t_overflow();\n        return -1;\n    }\n    *sec = (time_t)intpart;\n    *numerator = (long)floatpart;\n    assert(0 <= *numerator && *numerator < idenominator);\n    return 0;\n}\n\n\nstatic int\npytime_object_to_denominator(PyObject *obj, time_t *sec, long *numerator,\n                             long denominator, _PyTime_round_t round)\n{\n    assert(denominator >= 1);\n\n    if (PyFloat_Check(obj)) {\n        double d = PyFloat_AsDouble(obj);\n        if (Py_IS_NAN(d)) {\n            *numerator = 0;\n            PyErr_SetString(PyExc_ValueError, \"Invalid value NaN (not a number)\");\n            return -1;\n        }\n        return pytime_double_to_denominator(d, sec, numerator,\n                                            denominator, round);\n    }\n    else {\n        *sec = _PyLong_AsTime_t(obj);\n        *numerator = 0;\n        if (*sec == (time_t)-1 && PyErr_Occurred()) {\n            return -1;\n        }\n        return 0;\n    }\n}\n\n\nint\n_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)\n{\n    if (PyFloat_Check(obj)) {\n        double intpart;\n        /* volatile avoids optimization changing how numbers are rounded */\n        volatile double d;\n\n        d = PyFloat_AsDouble(obj);\n        if (Py_IS_NAN(d)) {\n            PyErr_SetString(PyExc_ValueError, \"Invalid value NaN (not a number)\");\n            return -1;\n        }\n\n        d = pytime_round(d, round);\n        (void)modf(d, &intpart);\n\n        /* See comments in pytime_double_to_denominator */\n        if (!((double)PY_TIME_T_MIN <= intpart && intpart < -(double)PY_TIME_T_MIN)) {\n            pytime_time_t_overflow();\n            return -1;\n        }\n        *sec = (time_t)intpart;\n        return 0;\n    }\n    else {\n        *sec = _PyLong_AsTime_t(obj);\n        if (*sec == (time_t)-1 && PyErr_Occurred()) {\n            return -1;\n        }\n        return 0;\n    }\n}\n\n\nint\n_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,\n                         _PyTime_round_t round)\n{\n    return pytime_object_to_denominator(obj, sec, nsec, SEC_TO_NS, round);\n}\n\n\nint\n_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,\n                        _PyTime_round_t round)\n{\n    return pytime_object_to_denominator(obj, sec, usec, SEC_TO_US, round);\n}\n\n\n_PyTime_t\n_PyTime_FromSeconds(int seconds)\n{\n    /* ensure that integer overflow cannot happen, int type should have 32\n       bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_NS takes 30\n       bits). */\n    static_assert(INT_MAX <= _PyTime_MAX / SEC_TO_NS, \"_PyTime_t overflow\");\n    static_assert(INT_MIN >= _PyTime_MIN / SEC_TO_NS, \"_PyTime_t underflow\");\n\n    _PyTime_t t = (_PyTime_t)seconds;\n    assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS)\n           || (t < 0 && t >= _PyTime_MIN / SEC_TO_NS));\n    t *= SEC_TO_NS;\n    return pytime_from_nanoseconds(t);\n}\n\n\n_PyTime_t\n_PyTime_FromNanoseconds(_PyTime_t ns)\n{\n    return pytime_from_nanoseconds(ns);\n}\n\n\n_PyTime_t\n_PyTime_FromMicrosecondsClamp(_PyTime_t us)\n{\n    _PyTime_t ns = _PyTime_Mul(us, US_TO_NS);\n    return pytime_from_nanoseconds(ns);\n}\n\n\nint\n_PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj)\n{\n\n    if (!PyLong_Check(obj)) {\n        PyErr_Format(PyExc_TypeError, \"expect int, got %s\",\n                     Py_TYPE(obj)->tp_name);\n        return -1;\n    }\n\n    static_assert(sizeof(long long) == sizeof(_PyTime_t),\n                  \"_PyTime_t is not long long\");\n    long long nsec = PyLong_AsLongLong(obj);\n    if (nsec == -1 && PyErr_Occurred()) {\n        if (PyErr_ExceptionMatches(PyExc_OverflowError)) {\n            pytime_overflow();\n        }\n        return -1;\n    }\n\n    _PyTime_t t = (_PyTime_t)nsec;\n    *tp = pytime_from_nanoseconds(t);\n    return 0;\n}\n\n\n#ifdef HAVE_CLOCK_GETTIME\nstatic int\npytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise_exc)\n{\n    _PyTime_t t, tv_nsec;\n\n    static_assert(sizeof(ts->tv_sec) <= sizeof(_PyTime_t),\n                  \"timespec.tv_sec is larger than _PyTime_t\");\n    t = (_PyTime_t)ts->tv_sec;\n\n    int res1 = pytime_mul(&t, SEC_TO_NS);\n\n    tv_nsec = ts->tv_nsec;\n    int res2 = pytime_add(&t, tv_nsec);\n\n    *tp = pytime_from_nanoseconds(t);\n\n    if (raise_exc && (res1 < 0 || res2 < 0)) {\n        pytime_overflow();\n        return -1;\n    }\n    return 0;\n}\n\nint\n_PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts)\n{\n    return pytime_fromtimespec(tp, ts, 1);\n}\n#endif\n\n\n#ifndef MS_WINDOWS\nstatic int\npytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise_exc)\n{\n    static_assert(sizeof(tv->tv_sec) <= sizeof(_PyTime_t),\n                  \"timeval.tv_sec is larger than _PyTime_t\");\n    _PyTime_t t = (_PyTime_t)tv->tv_sec;\n\n    int res1 = pytime_mul(&t, SEC_TO_NS);\n\n    _PyTime_t usec = (_PyTime_t)tv->tv_usec * US_TO_NS;\n    int res2 = pytime_add(&t, usec);\n\n    *tp = pytime_from_nanoseconds(t);\n\n    if (raise_exc && (res1 < 0 || res2 < 0)) {\n        pytime_overflow();\n        return -1;\n    }\n    return 0;\n}\n\n\nint\n_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv)\n{\n    return pytime_fromtimeval(tp, tv, 1);\n}\n#endif\n\n\nstatic int\npytime_from_double(_PyTime_t *tp, double value, _PyTime_round_t round,\n                   long unit_to_ns)\n{\n    /* volatile avoids optimization changing how numbers are rounded */\n    volatile double d;\n\n    /* convert to a number of nanoseconds */\n    d = value;\n    d *= (double)unit_to_ns;\n    d = pytime_round(d, round);\n\n    /* See comments in pytime_double_to_denominator */\n    if (!((double)_PyTime_MIN <= d && d < -(double)_PyTime_MIN)) {\n        pytime_time_t_overflow();\n        return -1;\n    }\n    _PyTime_t ns = (_PyTime_t)d;\n\n    *tp = pytime_from_nanoseconds(ns);\n    return 0;\n}\n\n\nstatic int\npytime_from_object(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round,\n                   long unit_to_ns)\n{\n    if (PyFloat_Check(obj)) {\n        double d;\n        d = PyFloat_AsDouble(obj);\n        if (Py_IS_NAN(d)) {\n            PyErr_SetString(PyExc_ValueError, \"Invalid value NaN (not a number)\");\n            return -1;\n        }\n        return pytime_from_double(tp, d, round, unit_to_ns);\n    }\n    else {\n        long long sec = PyLong_AsLongLong(obj);\n        if (sec == -1 && PyErr_Occurred()) {\n            if (PyErr_ExceptionMatches(PyExc_OverflowError)) {\n                pytime_overflow();\n            }\n            return -1;\n        }\n\n        static_assert(sizeof(long long) <= sizeof(_PyTime_t),\n                      \"_PyTime_t is smaller than long long\");\n        _PyTime_t ns = (_PyTime_t)sec;\n        if (pytime_mul(&ns, unit_to_ns) < 0) {\n            pytime_overflow();\n            return -1;\n        }\n\n        *tp = pytime_from_nanoseconds(ns);\n        return 0;\n    }\n}\n\n\nint\n_PyTime_FromSecondsObject(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round)\n{\n    return pytime_from_object(tp, obj, round, SEC_TO_NS);\n}\n\n\nint\n_PyTime_FromMillisecondsObject(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round)\n{\n    return pytime_from_object(tp, obj, round, MS_TO_NS);\n}\n\n\ndouble\n_PyTime_AsSecondsDouble(_PyTime_t t)\n{\n    /* volatile avoids optimization changing how numbers are rounded */\n    volatile double d;\n\n    _PyTime_t ns = pytime_as_nanoseconds(t);\n    if (ns % SEC_TO_NS == 0) {\n        /* Divide using integers to avoid rounding issues on the integer part.\n           1e-9 cannot be stored exactly in IEEE 64-bit. */\n        _PyTime_t secs = ns / SEC_TO_NS;\n        d = (double)secs;\n    }\n    else {\n        d = (double)ns;\n        d /= 1e9;\n    }\n    return d;\n}\n\n\nPyObject *\n_PyTime_AsNanosecondsObject(_PyTime_t t)\n{\n    _PyTime_t ns =  pytime_as_nanoseconds(t);\n    static_assert(sizeof(long long) >= sizeof(_PyTime_t),\n                  \"_PyTime_t is larger than long long\");\n    return PyLong_FromLongLong((long long)ns);\n}\n\n\nstatic _PyTime_t\npytime_divide_round_up(const _PyTime_t t, const _PyTime_t k)\n{\n    assert(k > 1);\n    if (t >= 0) {\n        // Don't use (t + k - 1) / k to avoid integer overflow\n        // if t is equal to _PyTime_MAX\n        _PyTime_t q = t / k;\n        if (t % k) {\n            q += 1;\n        }\n        return q;\n    }\n    else {\n        // Don't use (t - (k - 1)) / k to avoid integer overflow\n        // if t is equals to _PyTime_MIN.\n        _PyTime_t q = t / k;\n        if (t % k) {\n            q -= 1;\n        }\n        return q;\n    }\n}\n\n\nstatic _PyTime_t\npytime_divide(const _PyTime_t t, const _PyTime_t k,\n              const _PyTime_round_t round)\n{\n    assert(k > 1);\n    if (round == _PyTime_ROUND_HALF_EVEN) {\n        _PyTime_t x = t / k;\n        _PyTime_t r = t % k;\n        _PyTime_t abs_r = Py_ABS(r);\n        if (abs_r > k / 2 || (abs_r == k / 2 && (Py_ABS(x) & 1))) {\n            if (t >= 0) {\n                x++;\n            }\n            else {\n                x--;\n            }\n        }\n        return x;\n    }\n    else if (round == _PyTime_ROUND_CEILING) {\n        if (t >= 0) {\n            return pytime_divide_round_up(t, k);\n        }\n        else {\n            return t / k;\n        }\n    }\n    else if (round == _PyTime_ROUND_FLOOR){\n        if (t >= 0) {\n            return t / k;\n        }\n        else {\n            return pytime_divide_round_up(t, k);\n        }\n    }\n    else {\n        assert(round == _PyTime_ROUND_UP);\n        return pytime_divide_round_up(t, k);\n    }\n}\n\n\n// Compute (t / k, t % k) in (pq, pr).\n// Make sure that 0 <= pr < k.\n// Return 0 on success.\n// Return -1 on underflow and store (_PyTime_MIN, 0) in (pq, pr).\nstatic int\npytime_divmod(const _PyTime_t t, const _PyTime_t k,\n              _PyTime_t *pq, _PyTime_t *pr)\n{\n    assert(k > 1);\n    _PyTime_t q = t / k;\n    _PyTime_t r = t % k;\n    if (r < 0) {\n        if (q == _PyTime_MIN) {\n            *pq = _PyTime_MIN;\n            *pr = 0;\n            return -1;\n        }\n        r += k;\n        q -= 1;\n    }\n    assert(0 <= r && r < k);\n\n    *pq = q;\n    *pr = r;\n    return 0;\n}\n\n\n_PyTime_t\n_PyTime_AsNanoseconds(_PyTime_t t)\n{\n    return pytime_as_nanoseconds(t);\n}\n\n\n#ifdef MS_WINDOWS\n_PyTime_t\n_PyTime_As100Nanoseconds(_PyTime_t t, _PyTime_round_t round)\n{\n    _PyTime_t ns = pytime_as_nanoseconds(t);\n    return pytime_divide(ns, NS_TO_100NS, round);\n}\n#endif\n\n\n_PyTime_t\n_PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round)\n{\n    _PyTime_t ns = pytime_as_nanoseconds(t);\n    return pytime_divide(ns, NS_TO_US, round);\n}\n\n\n_PyTime_t\n_PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round)\n{\n    _PyTime_t ns = pytime_as_nanoseconds(t);\n    return pytime_divide(ns, NS_TO_MS, round);\n}\n\n\nstatic int\npytime_as_timeval(_PyTime_t t, _PyTime_t *ptv_sec, int *ptv_usec,\n                  _PyTime_round_t round)\n{\n    _PyTime_t ns = pytime_as_nanoseconds(t);\n    _PyTime_t us = pytime_divide(ns, US_TO_NS, round);\n\n    _PyTime_t tv_sec, tv_usec;\n    int res = pytime_divmod(us, SEC_TO_US, &tv_sec, &tv_usec);\n    *ptv_sec = tv_sec;\n    *ptv_usec = (int)tv_usec;\n    return res;\n}\n\n\nstatic int\npytime_as_timeval_struct(_PyTime_t t, struct timeval *tv,\n                         _PyTime_round_t round, int raise_exc)\n{\n    _PyTime_t tv_sec;\n    int tv_usec;\n    int res = pytime_as_timeval(t, &tv_sec, &tv_usec, round);\n    int res2;\n#ifdef MS_WINDOWS\n    // On Windows, timeval.tv_sec type is long\n    res2 = _PyTime_AsLong(tv_sec, &tv->tv_sec);\n#else\n    res2 = _PyTime_AsTime_t(tv_sec, &tv->tv_sec);\n#endif\n    if (res2 < 0) {\n        tv_usec = 0;\n    }\n    tv->tv_usec = tv_usec;\n\n    if (raise_exc && (res < 0 || res2 < 0)) {\n        pytime_time_t_overflow();\n        return -1;\n    }\n    return 0;\n}\n\n\nint\n_PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)\n{\n    return pytime_as_timeval_struct(t, tv, round, 1);\n}\n\n\nvoid\n_PyTime_AsTimeval_clamp(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)\n{\n    (void)pytime_as_timeval_struct(t, tv, round, 0);\n}\n\n\nint\n_PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us,\n                        _PyTime_round_t round)\n{\n    _PyTime_t secs;\n    if (pytime_as_timeval(t, &secs, us, round) < 0) {\n        pytime_time_t_overflow();\n        return -1;\n    }\n\n    if (_PyTime_AsTime_t(secs, p_secs) < 0) {\n        pytime_time_t_overflow();\n        return -1;\n    }\n    return 0;\n}\n\n\n#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)\nstatic int\npytime_as_timespec(_PyTime_t t, struct timespec *ts, int raise_exc)\n{\n    _PyTime_t ns = pytime_as_nanoseconds(t);\n    _PyTime_t tv_sec, tv_nsec;\n    int res = pytime_divmod(ns, SEC_TO_NS, &tv_sec, &tv_nsec);\n\n    int res2 = _PyTime_AsTime_t(tv_sec, &ts->tv_sec);\n    if (res2 < 0) {\n        tv_nsec = 0;\n    }\n    ts->tv_nsec = tv_nsec;\n\n    if (raise_exc && (res < 0 || res2 < 0)) {\n        pytime_time_t_overflow();\n        return -1;\n    }\n    return 0;\n}\n\nvoid\n_PyTime_AsTimespec_clamp(_PyTime_t t, struct timespec *ts)\n{\n    (void)pytime_as_timespec(t, ts, 0);\n}\n\nint\n_PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)\n{\n    return pytime_as_timespec(t, ts, 1);\n}\n#endif\n\n\nstatic int\npy_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)\n{\n    assert(info == NULL || raise_exc);\n\n#ifdef MS_WINDOWS\n    FILETIME system_time;\n    ULARGE_INTEGER large;\n\n    GetSystemTimeAsFileTime(&system_time);\n    large.u.LowPart = system_time.dwLowDateTime;\n    large.u.HighPart = system_time.dwHighDateTime;\n    /* 11,644,473,600,000,000,000: number of nanoseconds between\n       the 1st january 1601 and the 1st january 1970 (369 years + 89 leap\n       days). */\n    _PyTime_t ns = large.QuadPart * 100 - 11644473600000000000;\n    *tp = pytime_from_nanoseconds(ns);\n    if (info) {\n        DWORD timeAdjustment, timeIncrement;\n        BOOL isTimeAdjustmentDisabled, ok;\n\n        info->implementation = \"GetSystemTimeAsFileTime()\";\n        info->monotonic = 0;\n        ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,\n                                     &isTimeAdjustmentDisabled);\n        if (!ok) {\n            PyErr_SetFromWindowsErr(0);\n            return -1;\n        }\n        info->resolution = timeIncrement * 1e-7;\n        info->adjustable = 1;\n    }\n\n#else   /* MS_WINDOWS */\n    int err;\n#if defined(HAVE_CLOCK_GETTIME)\n    struct timespec ts;\n#endif\n\n#if !defined(HAVE_CLOCK_GETTIME) || defined(__APPLE__)\n    struct timeval tv;\n#endif\n\n#ifdef HAVE_CLOCK_GETTIME\n\n#ifdef HAVE_CLOCK_GETTIME_RUNTIME\n    if (HAVE_CLOCK_GETTIME_RUNTIME) {\n#endif\n\n    err = clock_gettime(CLOCK_REALTIME, &ts);\n    if (err) {\n        if (raise_exc) {\n            PyErr_SetFromErrno(PyExc_OSError);\n        }\n        return -1;\n    }\n    if (pytime_fromtimespec(tp, &ts, raise_exc) < 0) {\n        return -1;\n    }\n\n    if (info) {\n        struct timespec res;\n        info->implementation = \"clock_gettime(CLOCK_REALTIME)\";\n        info->monotonic = 0;\n        info->adjustable = 1;\n        if (clock_getres(CLOCK_REALTIME, &res) == 0) {\n            info->resolution = (double)res.tv_sec + (double)res.tv_nsec * 1e-9;\n        }\n        else {\n            info->resolution = 1e-9;\n        }\n    }\n\n#ifdef HAVE_CLOCK_GETTIME_RUNTIME\n    }\n    else {\n#endif\n\n#endif\n\n#if !defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_GETTIME_RUNTIME)\n\n     /* test gettimeofday() */\n    err = gettimeofday(&tv, (struct timezone *)NULL);\n    if (err) {\n        if (raise_exc) {\n            PyErr_SetFromErrno(PyExc_OSError);\n        }\n        return -1;\n    }\n    if (pytime_fromtimeval(tp, &tv, raise_exc) < 0) {\n        return -1;\n    }\n\n    if (info) {\n        info->implementation = \"gettimeofday()\";\n        info->resolution = 1e-6;\n        info->monotonic = 0;\n        info->adjustable = 1;\n    }\n\n#if defined(HAVE_CLOCK_GETTIME_RUNTIME) && defined(HAVE_CLOCK_GETTIME)\n    } /* end of availibity block */\n#endif\n\n#endif   /* !HAVE_CLOCK_GETTIME */\n#endif   /* !MS_WINDOWS */\n    return 0;\n}\n\n\n_PyTime_t\n_PyTime_GetSystemClock(void)\n{\n    _PyTime_t t;\n    if (py_get_system_clock(&t, NULL, 0) < 0) {\n        // If clock_gettime(CLOCK_REALTIME) or gettimeofday() fails:\n        // silently ignore the failure and return 0.\n        t = 0;\n    }\n    return t;\n}\n\n\nint\n_PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info)\n{\n    return py_get_system_clock(t, info, 1);\n}\n\n\n#ifdef __APPLE__\nstatic int\npy_mach_timebase_info(_PyTime_t *pnumer, _PyTime_t *pdenom, int raise)\n{\n    static mach_timebase_info_data_t timebase;\n    /* According to the Technical Q&A QA1398, mach_timebase_info() cannot\n       fail: https://developer.apple.com/library/mac/#qa/qa1398/ */\n    (void)mach_timebase_info(&timebase);\n\n    /* Sanity check: should never occur in practice */\n    if (timebase.numer < 1 || timebase.denom < 1) {\n        if (raise) {\n            PyErr_SetString(PyExc_RuntimeError,\n                            \"invalid mach_timebase_info\");\n        }\n        return -1;\n    }\n\n    /* Check that timebase.numer and timebase.denom can be casted to\n       _PyTime_t. In practice, timebase uses uint32_t, so casting cannot\n       overflow. At the end, only make sure that the type is uint32_t\n       (_PyTime_t is 64-bit long). */\n    static_assert(sizeof(timebase.numer) <= sizeof(_PyTime_t),\n                  \"timebase.numer is larger than _PyTime_t\");\n    static_assert(sizeof(timebase.denom) <= sizeof(_PyTime_t),\n                  \"timebase.denom is larger than _PyTime_t\");\n\n    /* Make sure that _PyTime_MulDiv(ticks, timebase_numer, timebase_denom)\n       cannot overflow.\n\n       Known time bases:\n\n       * (1, 1) on Intel\n       * (1000000000, 33333335) or (1000000000, 25000000) on PowerPC\n\n       None of these time bases can overflow with 64-bit _PyTime_t, but\n       check for overflow, just in case. */\n    if ((_PyTime_t)timebase.numer > _PyTime_MAX / (_PyTime_t)timebase.denom) {\n        if (raise) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"mach_timebase_info is too large\");\n        }\n        return -1;\n    }\n\n    *pnumer = (_PyTime_t)timebase.numer;\n    *pdenom = (_PyTime_t)timebase.denom;\n    return 0;\n}\n#endif\n\n\nstatic int\npy_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)\n{\n    assert(info == NULL || raise_exc);\n\n#if defined(MS_WINDOWS)\n    ULONGLONG ticks = GetTickCount64();\n    static_assert(sizeof(ticks) <= sizeof(_PyTime_t),\n                  \"ULONGLONG is larger than _PyTime_t\");\n    _PyTime_t t;\n    if (ticks <= (ULONGLONG)_PyTime_MAX) {\n        t = (_PyTime_t)ticks;\n    }\n    else {\n        // GetTickCount64() maximum is larger than _PyTime_t maximum:\n        // ULONGLONG is unsigned, whereas _PyTime_t is signed.\n        t = _PyTime_MAX;\n    }\n\n    int res = pytime_mul(&t, MS_TO_NS);\n    *tp = t;\n\n    if (raise_exc && res < 0) {\n        pytime_overflow();\n        return -1;\n    }\n\n    if (info) {\n        DWORD timeAdjustment, timeIncrement;\n        BOOL isTimeAdjustmentDisabled, ok;\n        info->implementation = \"GetTickCount64()\";\n        info->monotonic = 1;\n        ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,\n                                     &isTimeAdjustmentDisabled);\n        if (!ok) {\n            PyErr_SetFromWindowsErr(0);\n            return -1;\n        }\n        info->resolution = timeIncrement * 1e-7;\n        info->adjustable = 0;\n    }\n\n#elif defined(__APPLE__)\n    static _PyTime_t timebase_numer = 0;\n    static _PyTime_t timebase_denom = 0;\n    if (timebase_denom == 0) {\n        if (py_mach_timebase_info(&timebase_numer, &timebase_denom, raise_exc) < 0) {\n            return -1;\n        }\n    }\n\n    if (info) {\n        info->implementation = \"mach_absolute_time()\";\n        info->resolution = (double)timebase_numer / (double)timebase_denom * 1e-9;\n        info->monotonic = 1;\n        info->adjustable = 0;\n    }\n\n    uint64_t uticks = mach_absolute_time();\n    // unsigned => signed\n    assert(uticks <= (uint64_t)_PyTime_MAX);\n    _PyTime_t ticks = (_PyTime_t)uticks;\n\n    _PyTime_t ns = _PyTime_MulDiv(ticks, timebase_numer, timebase_denom);\n    *tp = pytime_from_nanoseconds(ns);\n\n#elif defined(__hpux)\n    hrtime_t time;\n\n    time = gethrtime();\n    if (time == -1) {\n        if (raise_exc) {\n            PyErr_SetFromErrno(PyExc_OSError);\n        }\n        return -1;\n    }\n\n    *tp = pytime_from_nanoseconds(time);\n\n    if (info) {\n        info->implementation = \"gethrtime()\";\n        info->resolution = 1e-9;\n        info->monotonic = 1;\n        info->adjustable = 0;\n    }\n\n#else\n\n#ifdef CLOCK_HIGHRES\n    const clockid_t clk_id = CLOCK_HIGHRES;\n    const char *implementation = \"clock_gettime(CLOCK_HIGHRES)\";\n#else\n    const clockid_t clk_id = CLOCK_MONOTONIC;\n    const char *implementation = \"clock_gettime(CLOCK_MONOTONIC)\";\n#endif\n\n    struct timespec ts;\n    if (clock_gettime(clk_id, &ts) != 0) {\n        if (raise_exc) {\n            PyErr_SetFromErrno(PyExc_OSError);\n            return -1;\n        }\n        return -1;\n    }\n\n    if (pytime_fromtimespec(tp, &ts, raise_exc) < 0) {\n        return -1;\n    }\n\n    if (info) {\n        info->monotonic = 1;\n        info->implementation = implementation;\n        info->adjustable = 0;\n        struct timespec res;\n        if (clock_getres(clk_id, &res) != 0) {\n            PyErr_SetFromErrno(PyExc_OSError);\n            return -1;\n        }\n        info->resolution = res.tv_sec + res.tv_nsec * 1e-9;\n    }\n#endif\n    return 0;\n}\n\n\n_PyTime_t\n_PyTime_GetMonotonicClock(void)\n{\n    _PyTime_t t;\n    if (py_get_monotonic_clock(&t, NULL, 0) < 0) {\n        // If mach_timebase_info(), clock_gettime() or gethrtime() fails:\n        // silently ignore the failure and return 0.\n        t = 0;\n    }\n    return t;\n}\n\n\nint\n_PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)\n{\n    return py_get_monotonic_clock(tp, info, 1);\n}\n\n\n#ifdef MS_WINDOWS\nstatic int\npy_win_perf_counter_frequency(LONGLONG *pfrequency, int raise)\n{\n    LONGLONG frequency;\n\n    LARGE_INTEGER freq;\n    // Since Windows XP, the function cannot fail.\n    (void)QueryPerformanceFrequency(&freq);\n    frequency = freq.QuadPart;\n\n    // Since Windows XP, frequency cannot be zero.\n    assert(frequency >= 1);\n\n    /* Make also sure that (ticks * SEC_TO_NS) cannot overflow in\n       _PyTime_MulDiv(), with ticks < frequency.\n\n       Known QueryPerformanceFrequency() values:\n\n       * 10,000,000 (10 MHz): 100 ns resolution\n       * 3,579,545 Hz (3.6 MHz): 279 ns resolution\n\n       None of these frequencies can overflow with 64-bit _PyTime_t, but\n       check for integer overflow just in case. */\n    if (frequency > _PyTime_MAX / SEC_TO_NS) {\n        if (raise) {\n            PyErr_SetString(PyExc_OverflowError,\n                            \"QueryPerformanceFrequency is too large\");\n        }\n        return -1;\n    }\n\n    *pfrequency = frequency;\n    return 0;\n}\n\n\nstatic int\npy_get_win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)\n{\n    assert(info == NULL || raise_exc);\n\n    static LONGLONG frequency = 0;\n    if (frequency == 0) {\n        if (py_win_perf_counter_frequency(&frequency, raise_exc) < 0) {\n            return -1;\n        }\n    }\n\n    if (info) {\n        info->implementation = \"QueryPerformanceCounter()\";\n        info->resolution = 1.0 / (double)frequency;\n        info->monotonic = 1;\n        info->adjustable = 0;\n    }\n\n    LARGE_INTEGER now;\n    QueryPerformanceCounter(&now);\n    LONGLONG ticksll = now.QuadPart;\n\n    /* Make sure that casting LONGLONG to _PyTime_t cannot overflow,\n       both types are signed */\n    _PyTime_t ticks;\n    static_assert(sizeof(ticksll) <= sizeof(ticks),\n                  \"LONGLONG is larger than _PyTime_t\");\n    ticks = (_PyTime_t)ticksll;\n\n    _PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)frequency);\n    *tp = pytime_from_nanoseconds(ns);\n    return 0;\n}\n#endif  // MS_WINDOWS\n\n\nint\n_PyTime_GetPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info)\n{\n#ifdef MS_WINDOWS\n    return py_get_win_perf_counter(t, info, 1);\n#else\n    return _PyTime_GetMonotonicClockWithInfo(t, info);\n#endif\n}\n\n\n_PyTime_t\n_PyTime_GetPerfCounter(void)\n{\n    _PyTime_t t;\n    int res;\n#ifdef MS_WINDOWS\n    res = py_get_win_perf_counter(&t, NULL, 0);\n#else\n    res = py_get_monotonic_clock(&t, NULL, 0);\n#endif\n    if (res  < 0) {\n        // If py_win_perf_counter_frequency() or py_get_monotonic_clock()\n        // fails: silently ignore the failure and return 0.\n        t = 0;\n    }\n    return t;\n}\n\n\nint\n_PyTime_localtime(time_t t, struct tm *tm)\n{\n#ifdef MS_WINDOWS\n    int error;\n\n    error = localtime_s(tm, &t);\n    if (error != 0) {\n        errno = error;\n        PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n    return 0;\n#else /* !MS_WINDOWS */\n\n#if defined(_AIX) && (SIZEOF_TIME_T < 8)\n    /* bpo-34373: AIX does not return NULL if t is too small or too large */\n    if (t < -2145916800 /* 1902-01-01 */\n       || t > 2145916800 /* 2038-01-01 */) {\n        errno = EINVAL;\n        PyErr_SetString(PyExc_OverflowError,\n                        \"localtime argument out of range\");\n        return -1;\n    }\n#endif\n\n    errno = 0;\n    if (localtime_r(&t, tm) == NULL) {\n        if (errno == 0) {\n            errno = EINVAL;\n        }\n        PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n    return 0;\n#endif /* MS_WINDOWS */\n}\n\n\nint\n_PyTime_gmtime(time_t t, struct tm *tm)\n{\n#ifdef MS_WINDOWS\n    int error;\n\n    error = gmtime_s(tm, &t);\n    if (error != 0) {\n        errno = error;\n        PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n    return 0;\n#else /* !MS_WINDOWS */\n    if (gmtime_r(&t, tm) == NULL) {\n#ifdef EINVAL\n        if (errno == 0) {\n            errno = EINVAL;\n        }\n#endif\n        PyErr_SetFromErrno(PyExc_OSError);\n        return -1;\n    }\n    return 0;\n#endif /* MS_WINDOWS */\n}\n\n\n_PyTime_t\n_PyDeadline_Init(_PyTime_t timeout)\n{\n    _PyTime_t now = _PyTime_GetMonotonicClock();\n    return _PyTime_Add(now, timeout);\n}\n\n\n_PyTime_t\n_PyDeadline_Get(_PyTime_t deadline)\n{\n    _PyTime_t now = _PyTime_GetMonotonicClock();\n    return deadline - now;\n}\n"
  },
  {
    "path": "Python-AST.c",
    "content": "// File automatically generated by Parser/asdl_c.py.\n\n#include \"Python.h\"\n#include \"pycore_ast.h\"\n#include \"pycore_ast_state.h\"     // struct ast_state\n#include \"pycore_ceval.h\"         // _Py_EnterRecursiveCall\n#include \"pycore_interp.h\"        // _PyInterpreterState.ast\n#include \"pycore_pystate.h\"       // _PyInterpreterState_GET()\n#include \"structmember.h\"\n#include <stddef.h>\n\n// Forward declaration\nstatic int init_types(struct ast_state *state);\n\nstatic struct ast_state*\nget_ast_state(void)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    struct ast_state *state = &interp->ast;\n    if (!init_types(state)) {\n        return NULL;\n    }\n    return state;\n}\n\nvoid _PyAST_Fini(PyInterpreterState *interp)\n{\n    struct ast_state *state = &interp->ast;\n\n    Py_CLEAR(state->AST_type);\n    Py_CLEAR(state->Add_singleton);\n    Py_CLEAR(state->Add_type);\n    Py_CLEAR(state->And_singleton);\n    Py_CLEAR(state->And_type);\n    Py_CLEAR(state->AnnAssign_type);\n    Py_CLEAR(state->Assert_type);\n    Py_CLEAR(state->Assign_type);\n    Py_CLEAR(state->AsyncFor_type);\n    Py_CLEAR(state->AsyncFunctionDef_type);\n    Py_CLEAR(state->AsyncWith_type);\n    Py_CLEAR(state->Attribute_type);\n    Py_CLEAR(state->AugAssign_type);\n    Py_CLEAR(state->Await_type);\n    Py_CLEAR(state->BinOp_type);\n    Py_CLEAR(state->BitAnd_singleton);\n    Py_CLEAR(state->BitAnd_type);\n    Py_CLEAR(state->BitOr_singleton);\n    Py_CLEAR(state->BitOr_type);\n    Py_CLEAR(state->BitXor_singleton);\n    Py_CLEAR(state->BitXor_type);\n    Py_CLEAR(state->BoolOp_type);\n    Py_CLEAR(state->Break_type);\n    Py_CLEAR(state->Call_type);\n    Py_CLEAR(state->ClassDef_type);\n    Py_CLEAR(state->Compare_type);\n    Py_CLEAR(state->Constant_type);\n    Py_CLEAR(state->Continue_type);\n    Py_CLEAR(state->Del_singleton);\n    Py_CLEAR(state->Del_type);\n    Py_CLEAR(state->Delete_type);\n    Py_CLEAR(state->DictComp_type);\n    Py_CLEAR(state->Dict_type);\n    Py_CLEAR(state->Div_singleton);\n    Py_CLEAR(state->Div_type);\n    Py_CLEAR(state->Eq_singleton);\n    Py_CLEAR(state->Eq_type);\n    Py_CLEAR(state->ExceptHandler_type);\n    Py_CLEAR(state->Expr_type);\n    Py_CLEAR(state->Expression_type);\n    Py_CLEAR(state->FloorDiv_singleton);\n    Py_CLEAR(state->FloorDiv_type);\n    Py_CLEAR(state->For_type);\n    Py_CLEAR(state->FormattedValue_type);\n    Py_CLEAR(state->FunctionDef_type);\n    Py_CLEAR(state->FunctionType_type);\n    Py_CLEAR(state->GeneratorExp_type);\n    Py_CLEAR(state->Global_type);\n    Py_CLEAR(state->GtE_singleton);\n    Py_CLEAR(state->GtE_type);\n    Py_CLEAR(state->Gt_singleton);\n    Py_CLEAR(state->Gt_type);\n    Py_CLEAR(state->IfExp_type);\n    Py_CLEAR(state->If_type);\n    Py_CLEAR(state->ImportFrom_type);\n    Py_CLEAR(state->Import_type);\n    Py_CLEAR(state->In_singleton);\n    Py_CLEAR(state->In_type);\n    Py_CLEAR(state->Interactive_type);\n    Py_CLEAR(state->Invert_singleton);\n    Py_CLEAR(state->Invert_type);\n    Py_CLEAR(state->IsNot_singleton);\n    Py_CLEAR(state->IsNot_type);\n    Py_CLEAR(state->Is_singleton);\n    Py_CLEAR(state->Is_type);\n    Py_CLEAR(state->JoinedStr_type);\n    Py_CLEAR(state->LShift_singleton);\n    Py_CLEAR(state->LShift_type);\n    Py_CLEAR(state->Lambda_type);\n    Py_CLEAR(state->ListComp_type);\n    Py_CLEAR(state->List_type);\n    Py_CLEAR(state->Load_singleton);\n    Py_CLEAR(state->Load_type);\n    Py_CLEAR(state->LtE_singleton);\n    Py_CLEAR(state->LtE_type);\n    Py_CLEAR(state->Lt_singleton);\n    Py_CLEAR(state->Lt_type);\n    Py_CLEAR(state->MatMult_singleton);\n    Py_CLEAR(state->MatMult_type);\n    Py_CLEAR(state->MatchAs_type);\n    Py_CLEAR(state->MatchClass_type);\n    Py_CLEAR(state->MatchMapping_type);\n    Py_CLEAR(state->MatchOr_type);\n    Py_CLEAR(state->MatchSequence_type);\n    Py_CLEAR(state->MatchSingleton_type);\n    Py_CLEAR(state->MatchStar_type);\n    Py_CLEAR(state->MatchValue_type);\n    Py_CLEAR(state->Match_type);\n    Py_CLEAR(state->Mod_singleton);\n    Py_CLEAR(state->Mod_type);\n    Py_CLEAR(state->Module_type);\n    Py_CLEAR(state->Mult_singleton);\n    Py_CLEAR(state->Mult_type);\n    Py_CLEAR(state->Name_type);\n    Py_CLEAR(state->NamedExpr_type);\n    Py_CLEAR(state->Nonlocal_type);\n    Py_CLEAR(state->NotEq_singleton);\n    Py_CLEAR(state->NotEq_type);\n    Py_CLEAR(state->NotIn_singleton);\n    Py_CLEAR(state->NotIn_type);\n    Py_CLEAR(state->Not_singleton);\n    Py_CLEAR(state->Not_type);\n    Py_CLEAR(state->Or_singleton);\n    Py_CLEAR(state->Or_type);\n    Py_CLEAR(state->ParamSpec_type);\n    Py_CLEAR(state->Pass_type);\n    Py_CLEAR(state->Pow_singleton);\n    Py_CLEAR(state->Pow_type);\n    Py_CLEAR(state->RShift_singleton);\n    Py_CLEAR(state->RShift_type);\n    Py_CLEAR(state->Raise_type);\n    Py_CLEAR(state->Return_type);\n    Py_CLEAR(state->SetComp_type);\n    Py_CLEAR(state->Set_type);\n    Py_CLEAR(state->Slice_type);\n    Py_CLEAR(state->Starred_type);\n    Py_CLEAR(state->Store_singleton);\n    Py_CLEAR(state->Store_type);\n    Py_CLEAR(state->Sub_singleton);\n    Py_CLEAR(state->Sub_type);\n    Py_CLEAR(state->Subscript_type);\n    Py_CLEAR(state->TryStar_type);\n    Py_CLEAR(state->Try_type);\n    Py_CLEAR(state->Tuple_type);\n    Py_CLEAR(state->TypeAlias_type);\n    Py_CLEAR(state->TypeIgnore_type);\n    Py_CLEAR(state->TypeVarTuple_type);\n    Py_CLEAR(state->TypeVar_type);\n    Py_CLEAR(state->UAdd_singleton);\n    Py_CLEAR(state->UAdd_type);\n    Py_CLEAR(state->USub_singleton);\n    Py_CLEAR(state->USub_type);\n    Py_CLEAR(state->UnaryOp_type);\n    Py_CLEAR(state->While_type);\n    Py_CLEAR(state->With_type);\n    Py_CLEAR(state->YieldFrom_type);\n    Py_CLEAR(state->Yield_type);\n    Py_CLEAR(state->__dict__);\n    Py_CLEAR(state->__doc__);\n    Py_CLEAR(state->__match_args__);\n    Py_CLEAR(state->__module__);\n    Py_CLEAR(state->_attributes);\n    Py_CLEAR(state->_fields);\n    Py_CLEAR(state->alias_type);\n    Py_CLEAR(state->annotation);\n    Py_CLEAR(state->arg);\n    Py_CLEAR(state->arg_type);\n    Py_CLEAR(state->args);\n    Py_CLEAR(state->argtypes);\n    Py_CLEAR(state->arguments_type);\n    Py_CLEAR(state->asname);\n    Py_CLEAR(state->ast);\n    Py_CLEAR(state->attr);\n    Py_CLEAR(state->bases);\n    Py_CLEAR(state->body);\n    Py_CLEAR(state->boolop_type);\n    Py_CLEAR(state->bound);\n    Py_CLEAR(state->cases);\n    Py_CLEAR(state->cause);\n    Py_CLEAR(state->cls);\n    Py_CLEAR(state->cmpop_type);\n    Py_CLEAR(state->col_offset);\n    Py_CLEAR(state->comparators);\n    Py_CLEAR(state->comprehension_type);\n    Py_CLEAR(state->context_expr);\n    Py_CLEAR(state->conversion);\n    Py_CLEAR(state->ctx);\n    Py_CLEAR(state->decorator_list);\n    Py_CLEAR(state->defaults);\n    Py_CLEAR(state->elt);\n    Py_CLEAR(state->elts);\n    Py_CLEAR(state->end_col_offset);\n    Py_CLEAR(state->end_lineno);\n    Py_CLEAR(state->exc);\n    Py_CLEAR(state->excepthandler_type);\n    Py_CLEAR(state->expr_context_type);\n    Py_CLEAR(state->expr_type);\n    Py_CLEAR(state->finalbody);\n    Py_CLEAR(state->format_spec);\n    Py_CLEAR(state->func);\n    Py_CLEAR(state->generators);\n    Py_CLEAR(state->guard);\n    Py_CLEAR(state->handlers);\n    Py_CLEAR(state->id);\n    Py_CLEAR(state->ifs);\n    Py_CLEAR(state->is_async);\n    Py_CLEAR(state->items);\n    Py_CLEAR(state->iter);\n    Py_CLEAR(state->key);\n    Py_CLEAR(state->keys);\n    Py_CLEAR(state->keyword_type);\n    Py_CLEAR(state->keywords);\n    Py_CLEAR(state->kind);\n    Py_CLEAR(state->kw_defaults);\n    Py_CLEAR(state->kwarg);\n    Py_CLEAR(state->kwd_attrs);\n    Py_CLEAR(state->kwd_patterns);\n    Py_CLEAR(state->kwonlyargs);\n    Py_CLEAR(state->left);\n    Py_CLEAR(state->level);\n    Py_CLEAR(state->lineno);\n    Py_CLEAR(state->lower);\n    Py_CLEAR(state->match_case_type);\n    Py_CLEAR(state->mod_type);\n    Py_CLEAR(state->module);\n    Py_CLEAR(state->msg);\n    Py_CLEAR(state->name);\n    Py_CLEAR(state->names);\n    Py_CLEAR(state->op);\n    Py_CLEAR(state->operand);\n    Py_CLEAR(state->operator_type);\n    Py_CLEAR(state->ops);\n    Py_CLEAR(state->optional_vars);\n    Py_CLEAR(state->orelse);\n    Py_CLEAR(state->pattern);\n    Py_CLEAR(state->pattern_type);\n    Py_CLEAR(state->patterns);\n    Py_CLEAR(state->posonlyargs);\n    Py_CLEAR(state->rest);\n    Py_CLEAR(state->returns);\n    Py_CLEAR(state->right);\n    Py_CLEAR(state->simple);\n    Py_CLEAR(state->slice);\n    Py_CLEAR(state->step);\n    Py_CLEAR(state->stmt_type);\n    Py_CLEAR(state->subject);\n    Py_CLEAR(state->tag);\n    Py_CLEAR(state->target);\n    Py_CLEAR(state->targets);\n    Py_CLEAR(state->test);\n    Py_CLEAR(state->type);\n    Py_CLEAR(state->type_comment);\n    Py_CLEAR(state->type_ignore_type);\n    Py_CLEAR(state->type_ignores);\n    Py_CLEAR(state->type_param_type);\n    Py_CLEAR(state->type_params);\n    Py_CLEAR(state->unaryop_type);\n    Py_CLEAR(state->upper);\n    Py_CLEAR(state->value);\n    Py_CLEAR(state->values);\n    Py_CLEAR(state->vararg);\n    Py_CLEAR(state->withitem_type);\n\n    Py_CLEAR(_Py_INTERP_CACHED_OBJECT(interp, str_replace_inf));\n\n#if !defined(NDEBUG)\n    state->initialized = -1;\n#else\n    state->initialized = 0;\n#endif\n}\n\nstatic int init_identifiers(struct ast_state *state)\n{\n    if ((state->__dict__ = PyUnicode_InternFromString(\"__dict__\")) == NULL) return 0;\n    if ((state->__doc__ = PyUnicode_InternFromString(\"__doc__\")) == NULL) return 0;\n    if ((state->__match_args__ = PyUnicode_InternFromString(\"__match_args__\")) == NULL) return 0;\n    if ((state->__module__ = PyUnicode_InternFromString(\"__module__\")) == NULL) return 0;\n    if ((state->_attributes = PyUnicode_InternFromString(\"_attributes\")) == NULL) return 0;\n    if ((state->_fields = PyUnicode_InternFromString(\"_fields\")) == NULL) return 0;\n    if ((state->annotation = PyUnicode_InternFromString(\"annotation\")) == NULL) return 0;\n    if ((state->arg = PyUnicode_InternFromString(\"arg\")) == NULL) return 0;\n    if ((state->args = PyUnicode_InternFromString(\"args\")) == NULL) return 0;\n    if ((state->argtypes = PyUnicode_InternFromString(\"argtypes\")) == NULL) return 0;\n    if ((state->asname = PyUnicode_InternFromString(\"asname\")) == NULL) return 0;\n    if ((state->ast = PyUnicode_InternFromString(\"ast\")) == NULL) return 0;\n    if ((state->attr = PyUnicode_InternFromString(\"attr\")) == NULL) return 0;\n    if ((state->bases = PyUnicode_InternFromString(\"bases\")) == NULL) return 0;\n    if ((state->body = PyUnicode_InternFromString(\"body\")) == NULL) return 0;\n    if ((state->bound = PyUnicode_InternFromString(\"bound\")) == NULL) return 0;\n    if ((state->cases = PyUnicode_InternFromString(\"cases\")) == NULL) return 0;\n    if ((state->cause = PyUnicode_InternFromString(\"cause\")) == NULL) return 0;\n    if ((state->cls = PyUnicode_InternFromString(\"cls\")) == NULL) return 0;\n    if ((state->col_offset = PyUnicode_InternFromString(\"col_offset\")) == NULL) return 0;\n    if ((state->comparators = PyUnicode_InternFromString(\"comparators\")) == NULL) return 0;\n    if ((state->context_expr = PyUnicode_InternFromString(\"context_expr\")) == NULL) return 0;\n    if ((state->conversion = PyUnicode_InternFromString(\"conversion\")) == NULL) return 0;\n    if ((state->ctx = PyUnicode_InternFromString(\"ctx\")) == NULL) return 0;\n    if ((state->decorator_list = PyUnicode_InternFromString(\"decorator_list\")) == NULL) return 0;\n    if ((state->defaults = PyUnicode_InternFromString(\"defaults\")) == NULL) return 0;\n    if ((state->elt = PyUnicode_InternFromString(\"elt\")) == NULL) return 0;\n    if ((state->elts = PyUnicode_InternFromString(\"elts\")) == NULL) return 0;\n    if ((state->end_col_offset = PyUnicode_InternFromString(\"end_col_offset\")) == NULL) return 0;\n    if ((state->end_lineno = PyUnicode_InternFromString(\"end_lineno\")) == NULL) return 0;\n    if ((state->exc = PyUnicode_InternFromString(\"exc\")) == NULL) return 0;\n    if ((state->finalbody = PyUnicode_InternFromString(\"finalbody\")) == NULL) return 0;\n    if ((state->format_spec = PyUnicode_InternFromString(\"format_spec\")) == NULL) return 0;\n    if ((state->func = PyUnicode_InternFromString(\"func\")) == NULL) return 0;\n    if ((state->generators = PyUnicode_InternFromString(\"generators\")) == NULL) return 0;\n    if ((state->guard = PyUnicode_InternFromString(\"guard\")) == NULL) return 0;\n    if ((state->handlers = PyUnicode_InternFromString(\"handlers\")) == NULL) return 0;\n    if ((state->id = PyUnicode_InternFromString(\"id\")) == NULL) return 0;\n    if ((state->ifs = PyUnicode_InternFromString(\"ifs\")) == NULL) return 0;\n    if ((state->is_async = PyUnicode_InternFromString(\"is_async\")) == NULL) return 0;\n    if ((state->items = PyUnicode_InternFromString(\"items\")) == NULL) return 0;\n    if ((state->iter = PyUnicode_InternFromString(\"iter\")) == NULL) return 0;\n    if ((state->key = PyUnicode_InternFromString(\"key\")) == NULL) return 0;\n    if ((state->keys = PyUnicode_InternFromString(\"keys\")) == NULL) return 0;\n    if ((state->keywords = PyUnicode_InternFromString(\"keywords\")) == NULL) return 0;\n    if ((state->kind = PyUnicode_InternFromString(\"kind\")) == NULL) return 0;\n    if ((state->kw_defaults = PyUnicode_InternFromString(\"kw_defaults\")) == NULL) return 0;\n    if ((state->kwarg = PyUnicode_InternFromString(\"kwarg\")) == NULL) return 0;\n    if ((state->kwd_attrs = PyUnicode_InternFromString(\"kwd_attrs\")) == NULL) return 0;\n    if ((state->kwd_patterns = PyUnicode_InternFromString(\"kwd_patterns\")) == NULL) return 0;\n    if ((state->kwonlyargs = PyUnicode_InternFromString(\"kwonlyargs\")) == NULL) return 0;\n    if ((state->left = PyUnicode_InternFromString(\"left\")) == NULL) return 0;\n    if ((state->level = PyUnicode_InternFromString(\"level\")) == NULL) return 0;\n    if ((state->lineno = PyUnicode_InternFromString(\"lineno\")) == NULL) return 0;\n    if ((state->lower = PyUnicode_InternFromString(\"lower\")) == NULL) return 0;\n    if ((state->module = PyUnicode_InternFromString(\"module\")) == NULL) return 0;\n    if ((state->msg = PyUnicode_InternFromString(\"msg\")) == NULL) return 0;\n    if ((state->name = PyUnicode_InternFromString(\"name\")) == NULL) return 0;\n    if ((state->names = PyUnicode_InternFromString(\"names\")) == NULL) return 0;\n    if ((state->op = PyUnicode_InternFromString(\"op\")) == NULL) return 0;\n    if ((state->operand = PyUnicode_InternFromString(\"operand\")) == NULL) return 0;\n    if ((state->ops = PyUnicode_InternFromString(\"ops\")) == NULL) return 0;\n    if ((state->optional_vars = PyUnicode_InternFromString(\"optional_vars\")) == NULL) return 0;\n    if ((state->orelse = PyUnicode_InternFromString(\"orelse\")) == NULL) return 0;\n    if ((state->pattern = PyUnicode_InternFromString(\"pattern\")) == NULL) return 0;\n    if ((state->patterns = PyUnicode_InternFromString(\"patterns\")) == NULL) return 0;\n    if ((state->posonlyargs = PyUnicode_InternFromString(\"posonlyargs\")) == NULL) return 0;\n    if ((state->rest = PyUnicode_InternFromString(\"rest\")) == NULL) return 0;\n    if ((state->returns = PyUnicode_InternFromString(\"returns\")) == NULL) return 0;\n    if ((state->right = PyUnicode_InternFromString(\"right\")) == NULL) return 0;\n    if ((state->simple = PyUnicode_InternFromString(\"simple\")) == NULL) return 0;\n    if ((state->slice = PyUnicode_InternFromString(\"slice\")) == NULL) return 0;\n    if ((state->step = PyUnicode_InternFromString(\"step\")) == NULL) return 0;\n    if ((state->subject = PyUnicode_InternFromString(\"subject\")) == NULL) return 0;\n    if ((state->tag = PyUnicode_InternFromString(\"tag\")) == NULL) return 0;\n    if ((state->target = PyUnicode_InternFromString(\"target\")) == NULL) return 0;\n    if ((state->targets = PyUnicode_InternFromString(\"targets\")) == NULL) return 0;\n    if ((state->test = PyUnicode_InternFromString(\"test\")) == NULL) return 0;\n    if ((state->type = PyUnicode_InternFromString(\"type\")) == NULL) return 0;\n    if ((state->type_comment = PyUnicode_InternFromString(\"type_comment\")) == NULL) return 0;\n    if ((state->type_ignores = PyUnicode_InternFromString(\"type_ignores\")) == NULL) return 0;\n    if ((state->type_params = PyUnicode_InternFromString(\"type_params\")) == NULL) return 0;\n    if ((state->upper = PyUnicode_InternFromString(\"upper\")) == NULL) return 0;\n    if ((state->value = PyUnicode_InternFromString(\"value\")) == NULL) return 0;\n    if ((state->values = PyUnicode_InternFromString(\"values\")) == NULL) return 0;\n    if ((state->vararg = PyUnicode_InternFromString(\"vararg\")) == NULL) return 0;\n    return 1;\n};\n\nGENERATE_ASDL_SEQ_CONSTRUCTOR(mod, mod_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(stmt, stmt_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(expr, expr_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(comprehension, comprehension_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(excepthandler, excepthandler_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(arguments, arguments_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(arg, arg_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(keyword, keyword_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(alias, alias_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(withitem, withitem_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(match_case, match_case_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(pattern, pattern_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(type_ignore, type_ignore_ty)\nGENERATE_ASDL_SEQ_CONSTRUCTOR(type_param, type_param_ty)\n\nstatic PyObject* ast2obj_mod(struct ast_state *state, void*);\nstatic const char * const Module_fields[]={\n    \"body\",\n    \"type_ignores\",\n};\nstatic const char * const Interactive_fields[]={\n    \"body\",\n};\nstatic const char * const Expression_fields[]={\n    \"body\",\n};\nstatic const char * const FunctionType_fields[]={\n    \"argtypes\",\n    \"returns\",\n};\nstatic const char * const stmt_attributes[] = {\n    \"lineno\",\n    \"col_offset\",\n    \"end_lineno\",\n    \"end_col_offset\",\n};\nstatic PyObject* ast2obj_stmt(struct ast_state *state, void*);\nstatic const char * const FunctionDef_fields[]={\n    \"name\",\n    \"args\",\n    \"body\",\n    \"decorator_list\",\n    \"returns\",\n    \"type_comment\",\n    \"type_params\",\n};\nstatic const char * const AsyncFunctionDef_fields[]={\n    \"name\",\n    \"args\",\n    \"body\",\n    \"decorator_list\",\n    \"returns\",\n    \"type_comment\",\n    \"type_params\",\n};\nstatic const char * const ClassDef_fields[]={\n    \"name\",\n    \"bases\",\n    \"keywords\",\n    \"body\",\n    \"decorator_list\",\n    \"type_params\",\n};\nstatic const char * const Return_fields[]={\n    \"value\",\n};\nstatic const char * const Delete_fields[]={\n    \"targets\",\n};\nstatic const char * const Assign_fields[]={\n    \"targets\",\n    \"value\",\n    \"type_comment\",\n};\nstatic const char * const TypeAlias_fields[]={\n    \"name\",\n    \"type_params\",\n    \"value\",\n};\nstatic const char * const AugAssign_fields[]={\n    \"target\",\n    \"op\",\n    \"value\",\n};\nstatic const char * const AnnAssign_fields[]={\n    \"target\",\n    \"annotation\",\n    \"value\",\n    \"simple\",\n};\nstatic const char * const For_fields[]={\n    \"target\",\n    \"iter\",\n    \"body\",\n    \"orelse\",\n    \"type_comment\",\n};\nstatic const char * const AsyncFor_fields[]={\n    \"target\",\n    \"iter\",\n    \"body\",\n    \"orelse\",\n    \"type_comment\",\n};\nstatic const char * const While_fields[]={\n    \"test\",\n    \"body\",\n    \"orelse\",\n};\nstatic const char * const If_fields[]={\n    \"test\",\n    \"body\",\n    \"orelse\",\n};\nstatic const char * const With_fields[]={\n    \"items\",\n    \"body\",\n    \"type_comment\",\n};\nstatic const char * const AsyncWith_fields[]={\n    \"items\",\n    \"body\",\n    \"type_comment\",\n};\nstatic const char * const Match_fields[]={\n    \"subject\",\n    \"cases\",\n};\nstatic const char * const Raise_fields[]={\n    \"exc\",\n    \"cause\",\n};\nstatic const char * const Try_fields[]={\n    \"body\",\n    \"handlers\",\n    \"orelse\",\n    \"finalbody\",\n};\nstatic const char * const TryStar_fields[]={\n    \"body\",\n    \"handlers\",\n    \"orelse\",\n    \"finalbody\",\n};\nstatic const char * const Assert_fields[]={\n    \"test\",\n    \"msg\",\n};\nstatic const char * const Import_fields[]={\n    \"names\",\n};\nstatic const char * const ImportFrom_fields[]={\n    \"module\",\n    \"names\",\n    \"level\",\n};\nstatic const char * const Global_fields[]={\n    \"names\",\n};\nstatic const char * const Nonlocal_fields[]={\n    \"names\",\n};\nstatic const char * const Expr_fields[]={\n    \"value\",\n};\nstatic const char * const expr_attributes[] = {\n    \"lineno\",\n    \"col_offset\",\n    \"end_lineno\",\n    \"end_col_offset\",\n};\nstatic PyObject* ast2obj_expr(struct ast_state *state, void*);\nstatic const char * const BoolOp_fields[]={\n    \"op\",\n    \"values\",\n};\nstatic const char * const NamedExpr_fields[]={\n    \"target\",\n    \"value\",\n};\nstatic const char * const BinOp_fields[]={\n    \"left\",\n    \"op\",\n    \"right\",\n};\nstatic const char * const UnaryOp_fields[]={\n    \"op\",\n    \"operand\",\n};\nstatic const char * const Lambda_fields[]={\n    \"args\",\n    \"body\",\n};\nstatic const char * const IfExp_fields[]={\n    \"test\",\n    \"body\",\n    \"orelse\",\n};\nstatic const char * const Dict_fields[]={\n    \"keys\",\n    \"values\",\n};\nstatic const char * const Set_fields[]={\n    \"elts\",\n};\nstatic const char * const ListComp_fields[]={\n    \"elt\",\n    \"generators\",\n};\nstatic const char * const SetComp_fields[]={\n    \"elt\",\n    \"generators\",\n};\nstatic const char * const DictComp_fields[]={\n    \"key\",\n    \"value\",\n    \"generators\",\n};\nstatic const char * const GeneratorExp_fields[]={\n    \"elt\",\n    \"generators\",\n};\nstatic const char * const Await_fields[]={\n    \"value\",\n};\nstatic const char * const Yield_fields[]={\n    \"value\",\n};\nstatic const char * const YieldFrom_fields[]={\n    \"value\",\n};\nstatic const char * const Compare_fields[]={\n    \"left\",\n    \"ops\",\n    \"comparators\",\n};\nstatic const char * const Call_fields[]={\n    \"func\",\n    \"args\",\n    \"keywords\",\n};\nstatic const char * const FormattedValue_fields[]={\n    \"value\",\n    \"conversion\",\n    \"format_spec\",\n};\nstatic const char * const JoinedStr_fields[]={\n    \"values\",\n};\nstatic const char * const Constant_fields[]={\n    \"value\",\n    \"kind\",\n};\nstatic const char * const Attribute_fields[]={\n    \"value\",\n    \"attr\",\n    \"ctx\",\n};\nstatic const char * const Subscript_fields[]={\n    \"value\",\n    \"slice\",\n    \"ctx\",\n};\nstatic const char * const Starred_fields[]={\n    \"value\",\n    \"ctx\",\n};\nstatic const char * const Name_fields[]={\n    \"id\",\n    \"ctx\",\n};\nstatic const char * const List_fields[]={\n    \"elts\",\n    \"ctx\",\n};\nstatic const char * const Tuple_fields[]={\n    \"elts\",\n    \"ctx\",\n};\nstatic const char * const Slice_fields[]={\n    \"lower\",\n    \"upper\",\n    \"step\",\n};\nstatic PyObject* ast2obj_expr_context(struct ast_state *state, expr_context_ty);\nstatic PyObject* ast2obj_boolop(struct ast_state *state, boolop_ty);\nstatic PyObject* ast2obj_operator(struct ast_state *state, operator_ty);\nstatic PyObject* ast2obj_unaryop(struct ast_state *state, unaryop_ty);\nstatic PyObject* ast2obj_cmpop(struct ast_state *state, cmpop_ty);\nstatic PyObject* ast2obj_comprehension(struct ast_state *state, void*);\nstatic const char * const comprehension_fields[]={\n    \"target\",\n    \"iter\",\n    \"ifs\",\n    \"is_async\",\n};\nstatic const char * const excepthandler_attributes[] = {\n    \"lineno\",\n    \"col_offset\",\n    \"end_lineno\",\n    \"end_col_offset\",\n};\nstatic PyObject* ast2obj_excepthandler(struct ast_state *state, void*);\nstatic const char * const ExceptHandler_fields[]={\n    \"type\",\n    \"name\",\n    \"body\",\n};\nstatic PyObject* ast2obj_arguments(struct ast_state *state, void*);\nstatic const char * const arguments_fields[]={\n    \"posonlyargs\",\n    \"args\",\n    \"vararg\",\n    \"kwonlyargs\",\n    \"kw_defaults\",\n    \"kwarg\",\n    \"defaults\",\n};\nstatic PyObject* ast2obj_arg(struct ast_state *state, void*);\nstatic const char * const arg_attributes[] = {\n    \"lineno\",\n    \"col_offset\",\n    \"end_lineno\",\n    \"end_col_offset\",\n};\nstatic const char * const arg_fields[]={\n    \"arg\",\n    \"annotation\",\n    \"type_comment\",\n};\nstatic PyObject* ast2obj_keyword(struct ast_state *state, void*);\nstatic const char * const keyword_attributes[] = {\n    \"lineno\",\n    \"col_offset\",\n    \"end_lineno\",\n    \"end_col_offset\",\n};\nstatic const char * const keyword_fields[]={\n    \"arg\",\n    \"value\",\n};\nstatic PyObject* ast2obj_alias(struct ast_state *state, void*);\nstatic const char * const alias_attributes[] = {\n    \"lineno\",\n    \"col_offset\",\n    \"end_lineno\",\n    \"end_col_offset\",\n};\nstatic const char * const alias_fields[]={\n    \"name\",\n    \"asname\",\n};\nstatic PyObject* ast2obj_withitem(struct ast_state *state, void*);\nstatic const char * const withitem_fields[]={\n    \"context_expr\",\n    \"optional_vars\",\n};\nstatic PyObject* ast2obj_match_case(struct ast_state *state, void*);\nstatic const char * const match_case_fields[]={\n    \"pattern\",\n    \"guard\",\n    \"body\",\n};\nstatic const char * const pattern_attributes[] = {\n    \"lineno\",\n    \"col_offset\",\n    \"end_lineno\",\n    \"end_col_offset\",\n};\nstatic PyObject* ast2obj_pattern(struct ast_state *state, void*);\nstatic const char * const MatchValue_fields[]={\n    \"value\",\n};\nstatic const char * const MatchSingleton_fields[]={\n    \"value\",\n};\nstatic const char * const MatchSequence_fields[]={\n    \"patterns\",\n};\nstatic const char * const MatchMapping_fields[]={\n    \"keys\",\n    \"patterns\",\n    \"rest\",\n};\nstatic const char * const MatchClass_fields[]={\n    \"cls\",\n    \"patterns\",\n    \"kwd_attrs\",\n    \"kwd_patterns\",\n};\nstatic const char * const MatchStar_fields[]={\n    \"name\",\n};\nstatic const char * const MatchAs_fields[]={\n    \"pattern\",\n    \"name\",\n};\nstatic const char * const MatchOr_fields[]={\n    \"patterns\",\n};\nstatic PyObject* ast2obj_type_ignore(struct ast_state *state, void*);\nstatic const char * const TypeIgnore_fields[]={\n    \"lineno\",\n    \"tag\",\n};\nstatic const char * const type_param_attributes[] = {\n    \"lineno\",\n    \"col_offset\",\n    \"end_lineno\",\n    \"end_col_offset\",\n};\nstatic PyObject* ast2obj_type_param(struct ast_state *state, void*);\nstatic const char * const TypeVar_fields[]={\n    \"name\",\n    \"bound\",\n};\nstatic const char * const ParamSpec_fields[]={\n    \"name\",\n};\nstatic const char * const TypeVarTuple_fields[]={\n    \"name\",\n};\n\n\n\ntypedef struct {\n    PyObject_HEAD\n    PyObject *dict;\n} AST_object;\n\nstatic void\nast_dealloc(AST_object *self)\n{\n    /* bpo-31095: UnTrack is needed before calling any callbacks */\n    PyTypeObject *tp = Py_TYPE(self);\n    PyObject_GC_UnTrack(self);\n    Py_CLEAR(self->dict);\n    freefunc free_func = PyType_GetSlot(tp, Py_tp_free);\n    assert(free_func != NULL);\n    free_func(self);\n    Py_DECREF(tp);\n}\n\nstatic int\nast_traverse(AST_object *self, visitproc visit, void *arg)\n{\n    Py_VISIT(Py_TYPE(self));\n    Py_VISIT(self->dict);\n    return 0;\n}\n\nstatic int\nast_clear(AST_object *self)\n{\n    Py_CLEAR(self->dict);\n    return 0;\n}\n\nstatic int\nast_type_init(PyObject *self, PyObject *args, PyObject *kw)\n{\n    struct ast_state *state = get_ast_state();\n    if (state == NULL) {\n        return -1;\n    }\n\n    Py_ssize_t i, numfields = 0;\n    int res = -1;\n    PyObject *key, *value, *fields;\n    if (_PyObject_LookupAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) {\n        goto cleanup;\n    }\n    if (fields) {\n        numfields = PySequence_Size(fields);\n        if (numfields == -1) {\n            goto cleanup;\n        }\n    }\n\n    res = 0; /* if no error occurs, this stays 0 to the end */\n    if (numfields < PyTuple_GET_SIZE(args)) {\n        PyErr_Format(PyExc_TypeError, \"%.400s constructor takes at most \"\n                     \"%zd positional argument%s\",\n                     _PyType_Name(Py_TYPE(self)),\n                     numfields, numfields == 1 ? \"\" : \"s\");\n        res = -1;\n        goto cleanup;\n    }\n    for (i = 0; i < PyTuple_GET_SIZE(args); i++) {\n        /* cannot be reached when fields is NULL */\n        PyObject *name = PySequence_GetItem(fields, i);\n        if (!name) {\n            res = -1;\n            goto cleanup;\n        }\n        res = PyObject_SetAttr(self, name, PyTuple_GET_ITEM(args, i));\n        Py_DECREF(name);\n        if (res < 0) {\n            goto cleanup;\n        }\n    }\n    if (kw) {\n        i = 0;  /* needed by PyDict_Next */\n        while (PyDict_Next(kw, &i, &key, &value)) {\n            int contains = PySequence_Contains(fields, key);\n            if (contains == -1) {\n                res = -1;\n                goto cleanup;\n            } else if (contains == 1) {\n                Py_ssize_t p = PySequence_Index(fields, key);\n                if (p == -1) {\n                    res = -1;\n                    goto cleanup;\n                }\n                if (p < PyTuple_GET_SIZE(args)) {\n                    PyErr_Format(PyExc_TypeError,\n                        \"%.400s got multiple values for argument '%U'\",\n                        Py_TYPE(self)->tp_name, key);\n                    res = -1;\n                    goto cleanup;\n                }\n            }\n            res = PyObject_SetAttr(self, key, value);\n            if (res < 0) {\n                goto cleanup;\n            }\n        }\n    }\n  cleanup:\n    Py_XDECREF(fields);\n    return res;\n}\n\n/* Pickling support */\nstatic PyObject *\nast_type_reduce(PyObject *self, PyObject *unused)\n{\n    struct ast_state *state = get_ast_state();\n    if (state == NULL) {\n        return NULL;\n    }\n\n    PyObject *dict;\n    if (_PyObject_LookupAttr(self, state->__dict__, &dict) < 0) {\n        return NULL;\n    }\n    if (dict) {\n        return Py_BuildValue(\"O()N\", Py_TYPE(self), dict);\n    }\n    return Py_BuildValue(\"O()\", Py_TYPE(self));\n}\n\nstatic PyMemberDef ast_type_members[] = {\n    {\"__dictoffset__\", T_PYSSIZET, offsetof(AST_object, dict), READONLY},\n    {NULL}  /* Sentinel */\n};\n\nstatic PyMethodDef ast_type_methods[] = {\n    {\"__reduce__\", ast_type_reduce, METH_NOARGS, NULL},\n    {NULL}\n};\n\nstatic PyGetSetDef ast_type_getsets[] = {\n    {\"__dict__\", PyObject_GenericGetDict, PyObject_GenericSetDict},\n    {NULL}\n};\n\nstatic PyType_Slot AST_type_slots[] = {\n    {Py_tp_dealloc, ast_dealloc},\n    {Py_tp_getattro, PyObject_GenericGetAttr},\n    {Py_tp_setattro, PyObject_GenericSetAttr},\n    {Py_tp_traverse, ast_traverse},\n    {Py_tp_clear, ast_clear},\n    {Py_tp_members, ast_type_members},\n    {Py_tp_methods, ast_type_methods},\n    {Py_tp_getset, ast_type_getsets},\n    {Py_tp_init, ast_type_init},\n    {Py_tp_alloc, PyType_GenericAlloc},\n    {Py_tp_new, PyType_GenericNew},\n    {Py_tp_free, PyObject_GC_Del},\n    {0, 0},\n};\n\nstatic PyType_Spec AST_type_spec = {\n    \"ast.AST\",\n    sizeof(AST_object),\n    0,\n    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,\n    AST_type_slots\n};\n\nstatic PyObject *\nmake_type(struct ast_state *state, const char *type, PyObject* base,\n          const char* const* fields, int num_fields, const char *doc)\n{\n    PyObject *fnames, *result;\n    int i;\n    fnames = PyTuple_New(num_fields);\n    if (!fnames) return NULL;\n    for (i = 0; i < num_fields; i++) {\n        PyObject *field = PyUnicode_InternFromString(fields[i]);\n        if (!field) {\n            Py_DECREF(fnames);\n            return NULL;\n        }\n        PyTuple_SET_ITEM(fnames, i, field);\n    }\n    result = PyObject_CallFunction((PyObject*)&PyType_Type, \"s(O){OOOOOOOs}\",\n                    type, base,\n                    state->_fields, fnames,\n                    state->__match_args__, fnames,\n                    state->__module__,\n                    state->ast,\n                    state->__doc__, doc);\n    Py_DECREF(fnames);\n    return result;\n}\n\nstatic int\nadd_attributes(struct ast_state *state, PyObject *type, const char * const *attrs, int num_fields)\n{\n    int i, result;\n    PyObject *s, *l = PyTuple_New(num_fields);\n    if (!l)\n        return 0;\n    for (i = 0; i < num_fields; i++) {\n        s = PyUnicode_InternFromString(attrs[i]);\n        if (!s) {\n            Py_DECREF(l);\n            return 0;\n        }\n        PyTuple_SET_ITEM(l, i, s);\n    }\n    result = PyObject_SetAttr(type, state->_attributes, l) >= 0;\n    Py_DECREF(l);\n    return result;\n}\n\n/* Conversion AST -> Python */\n\nstatic PyObject* ast2obj_list(struct ast_state *state, asdl_seq *seq, PyObject* (*func)(struct ast_state *state, void*))\n{\n    Py_ssize_t i, n = asdl_seq_LEN(seq);\n    PyObject *result = PyList_New(n);\n    PyObject *value;\n    if (!result)\n        return NULL;\n    for (i = 0; i < n; i++) {\n        value = func(state, asdl_seq_GET_UNTYPED(seq, i));\n        if (!value) {\n            Py_DECREF(result);\n            return NULL;\n        }\n        PyList_SET_ITEM(result, i, value);\n    }\n    return result;\n}\n\nstatic PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), void *o)\n{\n    PyObject *op = (PyObject*)o;\n    if (!op) {\n        op = Py_None;\n    }\n    return Py_NewRef(op);\n}\n#define ast2obj_constant ast2obj_object\n#define ast2obj_identifier ast2obj_object\n#define ast2obj_string ast2obj_object\n\nstatic PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), long b)\n{\n    return PyLong_FromLong(b);\n}\n\n/* Conversion Python -> AST */\n\nstatic int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena)\n{\n    if (obj == Py_None)\n        obj = NULL;\n    if (obj) {\n        if (_PyArena_AddPyObject(arena, obj) < 0) {\n            *out = NULL;\n            return -1;\n        }\n        *out = Py_NewRef(obj);\n    }\n    else {\n        *out = NULL;\n    }\n    return 0;\n}\n\nstatic int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena)\n{\n    if (_PyArena_AddPyObject(arena, obj) < 0) {\n        *out = NULL;\n        return -1;\n    }\n    *out = Py_NewRef(obj);\n    return 0;\n}\n\nstatic int obj2ast_identifier(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena)\n{\n    if (!PyUnicode_CheckExact(obj) && obj != Py_None) {\n        PyErr_SetString(PyExc_TypeError, \"AST identifier must be of type str\");\n        return 1;\n    }\n    return obj2ast_object(state, obj, out, arena);\n}\n\nstatic int obj2ast_string(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena)\n{\n    if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) {\n        PyErr_SetString(PyExc_TypeError, \"AST string must be of type str\");\n        return 1;\n    }\n    return obj2ast_object(state, obj, out, arena);\n}\n\nstatic int obj2ast_int(struct ast_state* Py_UNUSED(state), PyObject* obj, int* out, PyArena* arena)\n{\n    int i;\n    if (!PyLong_Check(obj)) {\n        PyErr_Format(PyExc_ValueError, \"invalid integer value: %R\", obj);\n        return 1;\n    }\n\n    i = _PyLong_AsInt(obj);\n    if (i == -1 && PyErr_Occurred())\n        return 1;\n    *out = i;\n    return 0;\n}\n\nstatic int add_ast_fields(struct ast_state *state)\n{\n    PyObject *empty_tuple;\n    empty_tuple = PyTuple_New(0);\n    if (!empty_tuple ||\n        PyObject_SetAttrString(state->AST_type, \"_fields\", empty_tuple) < 0 ||\n        PyObject_SetAttrString(state->AST_type, \"__match_args__\", empty_tuple) < 0 ||\n        PyObject_SetAttrString(state->AST_type, \"_attributes\", empty_tuple) < 0) {\n        Py_XDECREF(empty_tuple);\n        return -1;\n    }\n    Py_DECREF(empty_tuple);\n    return 0;\n}\n\n\n\nstatic int\ninit_types(struct ast_state *state)\n{\n    // init_types() must not be called after _PyAST_Fini()\n    // has been called\n    assert(state->initialized >= 0);\n\n    if (state->initialized) {\n        return 1;\n    }\n    if (init_identifiers(state) < 0) {\n        return 0;\n    }\n    state->AST_type = PyType_FromSpec(&AST_type_spec);\n    if (!state->AST_type) {\n        return 0;\n    }\n    if (add_ast_fields(state) < 0) {\n        return 0;\n    }\n    state->mod_type = make_type(state, \"mod\", state->AST_type, NULL, 0,\n        \"mod = Module(stmt* body, type_ignore* type_ignores)\\n\"\n        \"    | Interactive(stmt* body)\\n\"\n        \"    | Expression(expr body)\\n\"\n        \"    | FunctionType(expr* argtypes, expr returns)\");\n    if (!state->mod_type) return 0;\n    if (!add_attributes(state, state->mod_type, NULL, 0)) return 0;\n    state->Module_type = make_type(state, \"Module\", state->mod_type,\n                                   Module_fields, 2,\n        \"Module(stmt* body, type_ignore* type_ignores)\");\n    if (!state->Module_type) return 0;\n    state->Interactive_type = make_type(state, \"Interactive\", state->mod_type,\n                                        Interactive_fields, 1,\n        \"Interactive(stmt* body)\");\n    if (!state->Interactive_type) return 0;\n    state->Expression_type = make_type(state, \"Expression\", state->mod_type,\n                                       Expression_fields, 1,\n        \"Expression(expr body)\");\n    if (!state->Expression_type) return 0;\n    state->FunctionType_type = make_type(state, \"FunctionType\",\n                                         state->mod_type, FunctionType_fields,\n                                         2,\n        \"FunctionType(expr* argtypes, expr returns)\");\n    if (!state->FunctionType_type) return 0;\n    state->stmt_type = make_type(state, \"stmt\", state->AST_type, NULL, 0,\n        \"stmt = FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment, type_param* type_params)\\n\"\n        \"     | AsyncFunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment, type_param* type_params)\\n\"\n        \"     | ClassDef(identifier name, expr* bases, keyword* keywords, stmt* body, expr* decorator_list, type_param* type_params)\\n\"\n        \"     | Return(expr? value)\\n\"\n        \"     | Delete(expr* targets)\\n\"\n        \"     | Assign(expr* targets, expr value, string? type_comment)\\n\"\n        \"     | TypeAlias(expr name, type_param* type_params, expr value)\\n\"\n        \"     | AugAssign(expr target, operator op, expr value)\\n\"\n        \"     | AnnAssign(expr target, expr annotation, expr? value, int simple)\\n\"\n        \"     | For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)\\n\"\n        \"     | AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)\\n\"\n        \"     | While(expr test, stmt* body, stmt* orelse)\\n\"\n        \"     | If(expr test, stmt* body, stmt* orelse)\\n\"\n        \"     | With(withitem* items, stmt* body, string? type_comment)\\n\"\n        \"     | AsyncWith(withitem* items, stmt* body, string? type_comment)\\n\"\n        \"     | Match(expr subject, match_case* cases)\\n\"\n        \"     | Raise(expr? exc, expr? cause)\\n\"\n        \"     | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\\n\"\n        \"     | TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\\n\"\n        \"     | Assert(expr test, expr? msg)\\n\"\n        \"     | Import(alias* names)\\n\"\n        \"     | ImportFrom(identifier? module, alias* names, int? level)\\n\"\n        \"     | Global(identifier* names)\\n\"\n        \"     | Nonlocal(identifier* names)\\n\"\n        \"     | Expr(expr value)\\n\"\n        \"     | Pass\\n\"\n        \"     | Break\\n\"\n        \"     | Continue\");\n    if (!state->stmt_type) return 0;\n    if (!add_attributes(state, state->stmt_type, stmt_attributes, 4)) return 0;\n    if (PyObject_SetAttr(state->stmt_type, state->end_lineno, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->stmt_type, state->end_col_offset, Py_None) ==\n        -1)\n        return 0;\n    state->FunctionDef_type = make_type(state, \"FunctionDef\", state->stmt_type,\n                                        FunctionDef_fields, 7,\n        \"FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment, type_param* type_params)\");\n    if (!state->FunctionDef_type) return 0;\n    if (PyObject_SetAttr(state->FunctionDef_type, state->returns, Py_None) ==\n        -1)\n        return 0;\n    if (PyObject_SetAttr(state->FunctionDef_type, state->type_comment, Py_None)\n        == -1)\n        return 0;\n    state->AsyncFunctionDef_type = make_type(state, \"AsyncFunctionDef\",\n                                             state->stmt_type,\n                                             AsyncFunctionDef_fields, 7,\n        \"AsyncFunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns, string? type_comment, type_param* type_params)\");\n    if (!state->AsyncFunctionDef_type) return 0;\n    if (PyObject_SetAttr(state->AsyncFunctionDef_type, state->returns, Py_None)\n        == -1)\n        return 0;\n    if (PyObject_SetAttr(state->AsyncFunctionDef_type, state->type_comment,\n        Py_None) == -1)\n        return 0;\n    state->ClassDef_type = make_type(state, \"ClassDef\", state->stmt_type,\n                                     ClassDef_fields, 6,\n        \"ClassDef(identifier name, expr* bases, keyword* keywords, stmt* body, expr* decorator_list, type_param* type_params)\");\n    if (!state->ClassDef_type) return 0;\n    state->Return_type = make_type(state, \"Return\", state->stmt_type,\n                                   Return_fields, 1,\n        \"Return(expr? value)\");\n    if (!state->Return_type) return 0;\n    if (PyObject_SetAttr(state->Return_type, state->value, Py_None) == -1)\n        return 0;\n    state->Delete_type = make_type(state, \"Delete\", state->stmt_type,\n                                   Delete_fields, 1,\n        \"Delete(expr* targets)\");\n    if (!state->Delete_type) return 0;\n    state->Assign_type = make_type(state, \"Assign\", state->stmt_type,\n                                   Assign_fields, 3,\n        \"Assign(expr* targets, expr value, string? type_comment)\");\n    if (!state->Assign_type) return 0;\n    if (PyObject_SetAttr(state->Assign_type, state->type_comment, Py_None) ==\n        -1)\n        return 0;\n    state->TypeAlias_type = make_type(state, \"TypeAlias\", state->stmt_type,\n                                      TypeAlias_fields, 3,\n        \"TypeAlias(expr name, type_param* type_params, expr value)\");\n    if (!state->TypeAlias_type) return 0;\n    state->AugAssign_type = make_type(state, \"AugAssign\", state->stmt_type,\n                                      AugAssign_fields, 3,\n        \"AugAssign(expr target, operator op, expr value)\");\n    if (!state->AugAssign_type) return 0;\n    state->AnnAssign_type = make_type(state, \"AnnAssign\", state->stmt_type,\n                                      AnnAssign_fields, 4,\n        \"AnnAssign(expr target, expr annotation, expr? value, int simple)\");\n    if (!state->AnnAssign_type) return 0;\n    if (PyObject_SetAttr(state->AnnAssign_type, state->value, Py_None) == -1)\n        return 0;\n    state->For_type = make_type(state, \"For\", state->stmt_type, For_fields, 5,\n        \"For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)\");\n    if (!state->For_type) return 0;\n    if (PyObject_SetAttr(state->For_type, state->type_comment, Py_None) == -1)\n        return 0;\n    state->AsyncFor_type = make_type(state, \"AsyncFor\", state->stmt_type,\n                                     AsyncFor_fields, 5,\n        \"AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)\");\n    if (!state->AsyncFor_type) return 0;\n    if (PyObject_SetAttr(state->AsyncFor_type, state->type_comment, Py_None) ==\n        -1)\n        return 0;\n    state->While_type = make_type(state, \"While\", state->stmt_type,\n                                  While_fields, 3,\n        \"While(expr test, stmt* body, stmt* orelse)\");\n    if (!state->While_type) return 0;\n    state->If_type = make_type(state, \"If\", state->stmt_type, If_fields, 3,\n        \"If(expr test, stmt* body, stmt* orelse)\");\n    if (!state->If_type) return 0;\n    state->With_type = make_type(state, \"With\", state->stmt_type, With_fields,\n                                 3,\n        \"With(withitem* items, stmt* body, string? type_comment)\");\n    if (!state->With_type) return 0;\n    if (PyObject_SetAttr(state->With_type, state->type_comment, Py_None) == -1)\n        return 0;\n    state->AsyncWith_type = make_type(state, \"AsyncWith\", state->stmt_type,\n                                      AsyncWith_fields, 3,\n        \"AsyncWith(withitem* items, stmt* body, string? type_comment)\");\n    if (!state->AsyncWith_type) return 0;\n    if (PyObject_SetAttr(state->AsyncWith_type, state->type_comment, Py_None)\n        == -1)\n        return 0;\n    state->Match_type = make_type(state, \"Match\", state->stmt_type,\n                                  Match_fields, 2,\n        \"Match(expr subject, match_case* cases)\");\n    if (!state->Match_type) return 0;\n    state->Raise_type = make_type(state, \"Raise\", state->stmt_type,\n                                  Raise_fields, 2,\n        \"Raise(expr? exc, expr? cause)\");\n    if (!state->Raise_type) return 0;\n    if (PyObject_SetAttr(state->Raise_type, state->exc, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->Raise_type, state->cause, Py_None) == -1)\n        return 0;\n    state->Try_type = make_type(state, \"Try\", state->stmt_type, Try_fields, 4,\n        \"Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\");\n    if (!state->Try_type) return 0;\n    state->TryStar_type = make_type(state, \"TryStar\", state->stmt_type,\n                                    TryStar_fields, 4,\n        \"TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\");\n    if (!state->TryStar_type) return 0;\n    state->Assert_type = make_type(state, \"Assert\", state->stmt_type,\n                                   Assert_fields, 2,\n        \"Assert(expr test, expr? msg)\");\n    if (!state->Assert_type) return 0;\n    if (PyObject_SetAttr(state->Assert_type, state->msg, Py_None) == -1)\n        return 0;\n    state->Import_type = make_type(state, \"Import\", state->stmt_type,\n                                   Import_fields, 1,\n        \"Import(alias* names)\");\n    if (!state->Import_type) return 0;\n    state->ImportFrom_type = make_type(state, \"ImportFrom\", state->stmt_type,\n                                       ImportFrom_fields, 3,\n        \"ImportFrom(identifier? module, alias* names, int? level)\");\n    if (!state->ImportFrom_type) return 0;\n    if (PyObject_SetAttr(state->ImportFrom_type, state->module, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->ImportFrom_type, state->level, Py_None) == -1)\n        return 0;\n    state->Global_type = make_type(state, \"Global\", state->stmt_type,\n                                   Global_fields, 1,\n        \"Global(identifier* names)\");\n    if (!state->Global_type) return 0;\n    state->Nonlocal_type = make_type(state, \"Nonlocal\", state->stmt_type,\n                                     Nonlocal_fields, 1,\n        \"Nonlocal(identifier* names)\");\n    if (!state->Nonlocal_type) return 0;\n    state->Expr_type = make_type(state, \"Expr\", state->stmt_type, Expr_fields,\n                                 1,\n        \"Expr(expr value)\");\n    if (!state->Expr_type) return 0;\n    state->Pass_type = make_type(state, \"Pass\", state->stmt_type, NULL, 0,\n        \"Pass\");\n    if (!state->Pass_type) return 0;\n    state->Break_type = make_type(state, \"Break\", state->stmt_type, NULL, 0,\n        \"Break\");\n    if (!state->Break_type) return 0;\n    state->Continue_type = make_type(state, \"Continue\", state->stmt_type, NULL,\n                                     0,\n        \"Continue\");\n    if (!state->Continue_type) return 0;\n    state->expr_type = make_type(state, \"expr\", state->AST_type, NULL, 0,\n        \"expr = BoolOp(boolop op, expr* values)\\n\"\n        \"     | NamedExpr(expr target, expr value)\\n\"\n        \"     | BinOp(expr left, operator op, expr right)\\n\"\n        \"     | UnaryOp(unaryop op, expr operand)\\n\"\n        \"     | Lambda(arguments args, expr body)\\n\"\n        \"     | IfExp(expr test, expr body, expr orelse)\\n\"\n        \"     | Dict(expr* keys, expr* values)\\n\"\n        \"     | Set(expr* elts)\\n\"\n        \"     | ListComp(expr elt, comprehension* generators)\\n\"\n        \"     | SetComp(expr elt, comprehension* generators)\\n\"\n        \"     | DictComp(expr key, expr value, comprehension* generators)\\n\"\n        \"     | GeneratorExp(expr elt, comprehension* generators)\\n\"\n        \"     | Await(expr value)\\n\"\n        \"     | Yield(expr? value)\\n\"\n        \"     | YieldFrom(expr value)\\n\"\n        \"     | Compare(expr left, cmpop* ops, expr* comparators)\\n\"\n        \"     | Call(expr func, expr* args, keyword* keywords)\\n\"\n        \"     | FormattedValue(expr value, int conversion, expr? format_spec)\\n\"\n        \"     | JoinedStr(expr* values)\\n\"\n        \"     | Constant(constant value, string? kind)\\n\"\n        \"     | Attribute(expr value, identifier attr, expr_context ctx)\\n\"\n        \"     | Subscript(expr value, expr slice, expr_context ctx)\\n\"\n        \"     | Starred(expr value, expr_context ctx)\\n\"\n        \"     | Name(identifier id, expr_context ctx)\\n\"\n        \"     | List(expr* elts, expr_context ctx)\\n\"\n        \"     | Tuple(expr* elts, expr_context ctx)\\n\"\n        \"     | Slice(expr? lower, expr? upper, expr? step)\");\n    if (!state->expr_type) return 0;\n    if (!add_attributes(state, state->expr_type, expr_attributes, 4)) return 0;\n    if (PyObject_SetAttr(state->expr_type, state->end_lineno, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->expr_type, state->end_col_offset, Py_None) ==\n        -1)\n        return 0;\n    state->BoolOp_type = make_type(state, \"BoolOp\", state->expr_type,\n                                   BoolOp_fields, 2,\n        \"BoolOp(boolop op, expr* values)\");\n    if (!state->BoolOp_type) return 0;\n    state->NamedExpr_type = make_type(state, \"NamedExpr\", state->expr_type,\n                                      NamedExpr_fields, 2,\n        \"NamedExpr(expr target, expr value)\");\n    if (!state->NamedExpr_type) return 0;\n    state->BinOp_type = make_type(state, \"BinOp\", state->expr_type,\n                                  BinOp_fields, 3,\n        \"BinOp(expr left, operator op, expr right)\");\n    if (!state->BinOp_type) return 0;\n    state->UnaryOp_type = make_type(state, \"UnaryOp\", state->expr_type,\n                                    UnaryOp_fields, 2,\n        \"UnaryOp(unaryop op, expr operand)\");\n    if (!state->UnaryOp_type) return 0;\n    state->Lambda_type = make_type(state, \"Lambda\", state->expr_type,\n                                   Lambda_fields, 2,\n        \"Lambda(arguments args, expr body)\");\n    if (!state->Lambda_type) return 0;\n    state->IfExp_type = make_type(state, \"IfExp\", state->expr_type,\n                                  IfExp_fields, 3,\n        \"IfExp(expr test, expr body, expr orelse)\");\n    if (!state->IfExp_type) return 0;\n    state->Dict_type = make_type(state, \"Dict\", state->expr_type, Dict_fields,\n                                 2,\n        \"Dict(expr* keys, expr* values)\");\n    if (!state->Dict_type) return 0;\n    state->Set_type = make_type(state, \"Set\", state->expr_type, Set_fields, 1,\n        \"Set(expr* elts)\");\n    if (!state->Set_type) return 0;\n    state->ListComp_type = make_type(state, \"ListComp\", state->expr_type,\n                                     ListComp_fields, 2,\n        \"ListComp(expr elt, comprehension* generators)\");\n    if (!state->ListComp_type) return 0;\n    state->SetComp_type = make_type(state, \"SetComp\", state->expr_type,\n                                    SetComp_fields, 2,\n        \"SetComp(expr elt, comprehension* generators)\");\n    if (!state->SetComp_type) return 0;\n    state->DictComp_type = make_type(state, \"DictComp\", state->expr_type,\n                                     DictComp_fields, 3,\n        \"DictComp(expr key, expr value, comprehension* generators)\");\n    if (!state->DictComp_type) return 0;\n    state->GeneratorExp_type = make_type(state, \"GeneratorExp\",\n                                         state->expr_type, GeneratorExp_fields,\n                                         2,\n        \"GeneratorExp(expr elt, comprehension* generators)\");\n    if (!state->GeneratorExp_type) return 0;\n    state->Await_type = make_type(state, \"Await\", state->expr_type,\n                                  Await_fields, 1,\n        \"Await(expr value)\");\n    if (!state->Await_type) return 0;\n    state->Yield_type = make_type(state, \"Yield\", state->expr_type,\n                                  Yield_fields, 1,\n        \"Yield(expr? value)\");\n    if (!state->Yield_type) return 0;\n    if (PyObject_SetAttr(state->Yield_type, state->value, Py_None) == -1)\n        return 0;\n    state->YieldFrom_type = make_type(state, \"YieldFrom\", state->expr_type,\n                                      YieldFrom_fields, 1,\n        \"YieldFrom(expr value)\");\n    if (!state->YieldFrom_type) return 0;\n    state->Compare_type = make_type(state, \"Compare\", state->expr_type,\n                                    Compare_fields, 3,\n        \"Compare(expr left, cmpop* ops, expr* comparators)\");\n    if (!state->Compare_type) return 0;\n    state->Call_type = make_type(state, \"Call\", state->expr_type, Call_fields,\n                                 3,\n        \"Call(expr func, expr* args, keyword* keywords)\");\n    if (!state->Call_type) return 0;\n    state->FormattedValue_type = make_type(state, \"FormattedValue\",\n                                           state->expr_type,\n                                           FormattedValue_fields, 3,\n        \"FormattedValue(expr value, int conversion, expr? format_spec)\");\n    if (!state->FormattedValue_type) return 0;\n    if (PyObject_SetAttr(state->FormattedValue_type, state->format_spec,\n        Py_None) == -1)\n        return 0;\n    state->JoinedStr_type = make_type(state, \"JoinedStr\", state->expr_type,\n                                      JoinedStr_fields, 1,\n        \"JoinedStr(expr* values)\");\n    if (!state->JoinedStr_type) return 0;\n    state->Constant_type = make_type(state, \"Constant\", state->expr_type,\n                                     Constant_fields, 2,\n        \"Constant(constant value, string? kind)\");\n    if (!state->Constant_type) return 0;\n    if (PyObject_SetAttr(state->Constant_type, state->kind, Py_None) == -1)\n        return 0;\n    state->Attribute_type = make_type(state, \"Attribute\", state->expr_type,\n                                      Attribute_fields, 3,\n        \"Attribute(expr value, identifier attr, expr_context ctx)\");\n    if (!state->Attribute_type) return 0;\n    state->Subscript_type = make_type(state, \"Subscript\", state->expr_type,\n                                      Subscript_fields, 3,\n        \"Subscript(expr value, expr slice, expr_context ctx)\");\n    if (!state->Subscript_type) return 0;\n    state->Starred_type = make_type(state, \"Starred\", state->expr_type,\n                                    Starred_fields, 2,\n        \"Starred(expr value, expr_context ctx)\");\n    if (!state->Starred_type) return 0;\n    state->Name_type = make_type(state, \"Name\", state->expr_type, Name_fields,\n                                 2,\n        \"Name(identifier id, expr_context ctx)\");\n    if (!state->Name_type) return 0;\n    state->List_type = make_type(state, \"List\", state->expr_type, List_fields,\n                                 2,\n        \"List(expr* elts, expr_context ctx)\");\n    if (!state->List_type) return 0;\n    state->Tuple_type = make_type(state, \"Tuple\", state->expr_type,\n                                  Tuple_fields, 2,\n        \"Tuple(expr* elts, expr_context ctx)\");\n    if (!state->Tuple_type) return 0;\n    state->Slice_type = make_type(state, \"Slice\", state->expr_type,\n                                  Slice_fields, 3,\n        \"Slice(expr? lower, expr? upper, expr? step)\");\n    if (!state->Slice_type) return 0;\n    if (PyObject_SetAttr(state->Slice_type, state->lower, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->Slice_type, state->upper, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->Slice_type, state->step, Py_None) == -1)\n        return 0;\n    state->expr_context_type = make_type(state, \"expr_context\",\n                                         state->AST_type, NULL, 0,\n        \"expr_context = Load | Store | Del\");\n    if (!state->expr_context_type) return 0;\n    if (!add_attributes(state, state->expr_context_type, NULL, 0)) return 0;\n    state->Load_type = make_type(state, \"Load\", state->expr_context_type, NULL,\n                                 0,\n        \"Load\");\n    if (!state->Load_type) return 0;\n    state->Load_singleton = PyType_GenericNew((PyTypeObject *)state->Load_type,\n                                              NULL, NULL);\n    if (!state->Load_singleton) return 0;\n    state->Store_type = make_type(state, \"Store\", state->expr_context_type,\n                                  NULL, 0,\n        \"Store\");\n    if (!state->Store_type) return 0;\n    state->Store_singleton = PyType_GenericNew((PyTypeObject\n                                               *)state->Store_type, NULL, NULL);\n    if (!state->Store_singleton) return 0;\n    state->Del_type = make_type(state, \"Del\", state->expr_context_type, NULL, 0,\n        \"Del\");\n    if (!state->Del_type) return 0;\n    state->Del_singleton = PyType_GenericNew((PyTypeObject *)state->Del_type,\n                                             NULL, NULL);\n    if (!state->Del_singleton) return 0;\n    state->boolop_type = make_type(state, \"boolop\", state->AST_type, NULL, 0,\n        \"boolop = And | Or\");\n    if (!state->boolop_type) return 0;\n    if (!add_attributes(state, state->boolop_type, NULL, 0)) return 0;\n    state->And_type = make_type(state, \"And\", state->boolop_type, NULL, 0,\n        \"And\");\n    if (!state->And_type) return 0;\n    state->And_singleton = PyType_GenericNew((PyTypeObject *)state->And_type,\n                                             NULL, NULL);\n    if (!state->And_singleton) return 0;\n    state->Or_type = make_type(state, \"Or\", state->boolop_type, NULL, 0,\n        \"Or\");\n    if (!state->Or_type) return 0;\n    state->Or_singleton = PyType_GenericNew((PyTypeObject *)state->Or_type,\n                                            NULL, NULL);\n    if (!state->Or_singleton) return 0;\n    state->operator_type = make_type(state, \"operator\", state->AST_type, NULL,\n                                     0,\n        \"operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift | RShift | BitOr | BitXor | BitAnd | FloorDiv\");\n    if (!state->operator_type) return 0;\n    if (!add_attributes(state, state->operator_type, NULL, 0)) return 0;\n    state->Add_type = make_type(state, \"Add\", state->operator_type, NULL, 0,\n        \"Add\");\n    if (!state->Add_type) return 0;\n    state->Add_singleton = PyType_GenericNew((PyTypeObject *)state->Add_type,\n                                             NULL, NULL);\n    if (!state->Add_singleton) return 0;\n    state->Sub_type = make_type(state, \"Sub\", state->operator_type, NULL, 0,\n        \"Sub\");\n    if (!state->Sub_type) return 0;\n    state->Sub_singleton = PyType_GenericNew((PyTypeObject *)state->Sub_type,\n                                             NULL, NULL);\n    if (!state->Sub_singleton) return 0;\n    state->Mult_type = make_type(state, \"Mult\", state->operator_type, NULL, 0,\n        \"Mult\");\n    if (!state->Mult_type) return 0;\n    state->Mult_singleton = PyType_GenericNew((PyTypeObject *)state->Mult_type,\n                                              NULL, NULL);\n    if (!state->Mult_singleton) return 0;\n    state->MatMult_type = make_type(state, \"MatMult\", state->operator_type,\n                                    NULL, 0,\n        \"MatMult\");\n    if (!state->MatMult_type) return 0;\n    state->MatMult_singleton = PyType_GenericNew((PyTypeObject\n                                                 *)state->MatMult_type, NULL,\n                                                 NULL);\n    if (!state->MatMult_singleton) return 0;\n    state->Div_type = make_type(state, \"Div\", state->operator_type, NULL, 0,\n        \"Div\");\n    if (!state->Div_type) return 0;\n    state->Div_singleton = PyType_GenericNew((PyTypeObject *)state->Div_type,\n                                             NULL, NULL);\n    if (!state->Div_singleton) return 0;\n    state->Mod_type = make_type(state, \"Mod\", state->operator_type, NULL, 0,\n        \"Mod\");\n    if (!state->Mod_type) return 0;\n    state->Mod_singleton = PyType_GenericNew((PyTypeObject *)state->Mod_type,\n                                             NULL, NULL);\n    if (!state->Mod_singleton) return 0;\n    state->Pow_type = make_type(state, \"Pow\", state->operator_type, NULL, 0,\n        \"Pow\");\n    if (!state->Pow_type) return 0;\n    state->Pow_singleton = PyType_GenericNew((PyTypeObject *)state->Pow_type,\n                                             NULL, NULL);\n    if (!state->Pow_singleton) return 0;\n    state->LShift_type = make_type(state, \"LShift\", state->operator_type, NULL,\n                                   0,\n        \"LShift\");\n    if (!state->LShift_type) return 0;\n    state->LShift_singleton = PyType_GenericNew((PyTypeObject\n                                                *)state->LShift_type, NULL,\n                                                NULL);\n    if (!state->LShift_singleton) return 0;\n    state->RShift_type = make_type(state, \"RShift\", state->operator_type, NULL,\n                                   0,\n        \"RShift\");\n    if (!state->RShift_type) return 0;\n    state->RShift_singleton = PyType_GenericNew((PyTypeObject\n                                                *)state->RShift_type, NULL,\n                                                NULL);\n    if (!state->RShift_singleton) return 0;\n    state->BitOr_type = make_type(state, \"BitOr\", state->operator_type, NULL, 0,\n        \"BitOr\");\n    if (!state->BitOr_type) return 0;\n    state->BitOr_singleton = PyType_GenericNew((PyTypeObject\n                                               *)state->BitOr_type, NULL, NULL);\n    if (!state->BitOr_singleton) return 0;\n    state->BitXor_type = make_type(state, \"BitXor\", state->operator_type, NULL,\n                                   0,\n        \"BitXor\");\n    if (!state->BitXor_type) return 0;\n    state->BitXor_singleton = PyType_GenericNew((PyTypeObject\n                                                *)state->BitXor_type, NULL,\n                                                NULL);\n    if (!state->BitXor_singleton) return 0;\n    state->BitAnd_type = make_type(state, \"BitAnd\", state->operator_type, NULL,\n                                   0,\n        \"BitAnd\");\n    if (!state->BitAnd_type) return 0;\n    state->BitAnd_singleton = PyType_GenericNew((PyTypeObject\n                                                *)state->BitAnd_type, NULL,\n                                                NULL);\n    if (!state->BitAnd_singleton) return 0;\n    state->FloorDiv_type = make_type(state, \"FloorDiv\", state->operator_type,\n                                     NULL, 0,\n        \"FloorDiv\");\n    if (!state->FloorDiv_type) return 0;\n    state->FloorDiv_singleton = PyType_GenericNew((PyTypeObject\n                                                  *)state->FloorDiv_type, NULL,\n                                                  NULL);\n    if (!state->FloorDiv_singleton) return 0;\n    state->unaryop_type = make_type(state, \"unaryop\", state->AST_type, NULL, 0,\n        \"unaryop = Invert | Not | UAdd | USub\");\n    if (!state->unaryop_type) return 0;\n    if (!add_attributes(state, state->unaryop_type, NULL, 0)) return 0;\n    state->Invert_type = make_type(state, \"Invert\", state->unaryop_type, NULL,\n                                   0,\n        \"Invert\");\n    if (!state->Invert_type) return 0;\n    state->Invert_singleton = PyType_GenericNew((PyTypeObject\n                                                *)state->Invert_type, NULL,\n                                                NULL);\n    if (!state->Invert_singleton) return 0;\n    state->Not_type = make_type(state, \"Not\", state->unaryop_type, NULL, 0,\n        \"Not\");\n    if (!state->Not_type) return 0;\n    state->Not_singleton = PyType_GenericNew((PyTypeObject *)state->Not_type,\n                                             NULL, NULL);\n    if (!state->Not_singleton) return 0;\n    state->UAdd_type = make_type(state, \"UAdd\", state->unaryop_type, NULL, 0,\n        \"UAdd\");\n    if (!state->UAdd_type) return 0;\n    state->UAdd_singleton = PyType_GenericNew((PyTypeObject *)state->UAdd_type,\n                                              NULL, NULL);\n    if (!state->UAdd_singleton) return 0;\n    state->USub_type = make_type(state, \"USub\", state->unaryop_type, NULL, 0,\n        \"USub\");\n    if (!state->USub_type) return 0;\n    state->USub_singleton = PyType_GenericNew((PyTypeObject *)state->USub_type,\n                                              NULL, NULL);\n    if (!state->USub_singleton) return 0;\n    state->cmpop_type = make_type(state, \"cmpop\", state->AST_type, NULL, 0,\n        \"cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn\");\n    if (!state->cmpop_type) return 0;\n    if (!add_attributes(state, state->cmpop_type, NULL, 0)) return 0;\n    state->Eq_type = make_type(state, \"Eq\", state->cmpop_type, NULL, 0,\n        \"Eq\");\n    if (!state->Eq_type) return 0;\n    state->Eq_singleton = PyType_GenericNew((PyTypeObject *)state->Eq_type,\n                                            NULL, NULL);\n    if (!state->Eq_singleton) return 0;\n    state->NotEq_type = make_type(state, \"NotEq\", state->cmpop_type, NULL, 0,\n        \"NotEq\");\n    if (!state->NotEq_type) return 0;\n    state->NotEq_singleton = PyType_GenericNew((PyTypeObject\n                                               *)state->NotEq_type, NULL, NULL);\n    if (!state->NotEq_singleton) return 0;\n    state->Lt_type = make_type(state, \"Lt\", state->cmpop_type, NULL, 0,\n        \"Lt\");\n    if (!state->Lt_type) return 0;\n    state->Lt_singleton = PyType_GenericNew((PyTypeObject *)state->Lt_type,\n                                            NULL, NULL);\n    if (!state->Lt_singleton) return 0;\n    state->LtE_type = make_type(state, \"LtE\", state->cmpop_type, NULL, 0,\n        \"LtE\");\n    if (!state->LtE_type) return 0;\n    state->LtE_singleton = PyType_GenericNew((PyTypeObject *)state->LtE_type,\n                                             NULL, NULL);\n    if (!state->LtE_singleton) return 0;\n    state->Gt_type = make_type(state, \"Gt\", state->cmpop_type, NULL, 0,\n        \"Gt\");\n    if (!state->Gt_type) return 0;\n    state->Gt_singleton = PyType_GenericNew((PyTypeObject *)state->Gt_type,\n                                            NULL, NULL);\n    if (!state->Gt_singleton) return 0;\n    state->GtE_type = make_type(state, \"GtE\", state->cmpop_type, NULL, 0,\n        \"GtE\");\n    if (!state->GtE_type) return 0;\n    state->GtE_singleton = PyType_GenericNew((PyTypeObject *)state->GtE_type,\n                                             NULL, NULL);\n    if (!state->GtE_singleton) return 0;\n    state->Is_type = make_type(state, \"Is\", state->cmpop_type, NULL, 0,\n        \"Is\");\n    if (!state->Is_type) return 0;\n    state->Is_singleton = PyType_GenericNew((PyTypeObject *)state->Is_type,\n                                            NULL, NULL);\n    if (!state->Is_singleton) return 0;\n    state->IsNot_type = make_type(state, \"IsNot\", state->cmpop_type, NULL, 0,\n        \"IsNot\");\n    if (!state->IsNot_type) return 0;\n    state->IsNot_singleton = PyType_GenericNew((PyTypeObject\n                                               *)state->IsNot_type, NULL, NULL);\n    if (!state->IsNot_singleton) return 0;\n    state->In_type = make_type(state, \"In\", state->cmpop_type, NULL, 0,\n        \"In\");\n    if (!state->In_type) return 0;\n    state->In_singleton = PyType_GenericNew((PyTypeObject *)state->In_type,\n                                            NULL, NULL);\n    if (!state->In_singleton) return 0;\n    state->NotIn_type = make_type(state, \"NotIn\", state->cmpop_type, NULL, 0,\n        \"NotIn\");\n    if (!state->NotIn_type) return 0;\n    state->NotIn_singleton = PyType_GenericNew((PyTypeObject\n                                               *)state->NotIn_type, NULL, NULL);\n    if (!state->NotIn_singleton) return 0;\n    state->comprehension_type = make_type(state, \"comprehension\",\n                                          state->AST_type,\n                                          comprehension_fields, 4,\n        \"comprehension(expr target, expr iter, expr* ifs, int is_async)\");\n    if (!state->comprehension_type) return 0;\n    if (!add_attributes(state, state->comprehension_type, NULL, 0)) return 0;\n    state->excepthandler_type = make_type(state, \"excepthandler\",\n                                          state->AST_type, NULL, 0,\n        \"excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)\");\n    if (!state->excepthandler_type) return 0;\n    if (!add_attributes(state, state->excepthandler_type,\n        excepthandler_attributes, 4)) return 0;\n    if (PyObject_SetAttr(state->excepthandler_type, state->end_lineno, Py_None)\n        == -1)\n        return 0;\n    if (PyObject_SetAttr(state->excepthandler_type, state->end_col_offset,\n        Py_None) == -1)\n        return 0;\n    state->ExceptHandler_type = make_type(state, \"ExceptHandler\",\n                                          state->excepthandler_type,\n                                          ExceptHandler_fields, 3,\n        \"ExceptHandler(expr? type, identifier? name, stmt* body)\");\n    if (!state->ExceptHandler_type) return 0;\n    if (PyObject_SetAttr(state->ExceptHandler_type, state->type, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->ExceptHandler_type, state->name, Py_None) == -1)\n        return 0;\n    state->arguments_type = make_type(state, \"arguments\", state->AST_type,\n                                      arguments_fields, 7,\n        \"arguments(arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults, arg? kwarg, expr* defaults)\");\n    if (!state->arguments_type) return 0;\n    if (!add_attributes(state, state->arguments_type, NULL, 0)) return 0;\n    if (PyObject_SetAttr(state->arguments_type, state->vararg, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->arguments_type, state->kwarg, Py_None) == -1)\n        return 0;\n    state->arg_type = make_type(state, \"arg\", state->AST_type, arg_fields, 3,\n        \"arg(identifier arg, expr? annotation, string? type_comment)\");\n    if (!state->arg_type) return 0;\n    if (!add_attributes(state, state->arg_type, arg_attributes, 4)) return 0;\n    if (PyObject_SetAttr(state->arg_type, state->annotation, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->arg_type, state->type_comment, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->arg_type, state->end_lineno, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->arg_type, state->end_col_offset, Py_None) == -1)\n        return 0;\n    state->keyword_type = make_type(state, \"keyword\", state->AST_type,\n                                    keyword_fields, 2,\n        \"keyword(identifier? arg, expr value)\");\n    if (!state->keyword_type) return 0;\n    if (!add_attributes(state, state->keyword_type, keyword_attributes, 4))\n        return 0;\n    if (PyObject_SetAttr(state->keyword_type, state->arg, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->keyword_type, state->end_lineno, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->keyword_type, state->end_col_offset, Py_None)\n        == -1)\n        return 0;\n    state->alias_type = make_type(state, \"alias\", state->AST_type,\n                                  alias_fields, 2,\n        \"alias(identifier name, identifier? asname)\");\n    if (!state->alias_type) return 0;\n    if (!add_attributes(state, state->alias_type, alias_attributes, 4)) return\n        0;\n    if (PyObject_SetAttr(state->alias_type, state->asname, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->alias_type, state->end_lineno, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->alias_type, state->end_col_offset, Py_None) ==\n        -1)\n        return 0;\n    state->withitem_type = make_type(state, \"withitem\", state->AST_type,\n                                     withitem_fields, 2,\n        \"withitem(expr context_expr, expr? optional_vars)\");\n    if (!state->withitem_type) return 0;\n    if (!add_attributes(state, state->withitem_type, NULL, 0)) return 0;\n    if (PyObject_SetAttr(state->withitem_type, state->optional_vars, Py_None)\n        == -1)\n        return 0;\n    state->match_case_type = make_type(state, \"match_case\", state->AST_type,\n                                       match_case_fields, 3,\n        \"match_case(pattern pattern, expr? guard, stmt* body)\");\n    if (!state->match_case_type) return 0;\n    if (!add_attributes(state, state->match_case_type, NULL, 0)) return 0;\n    if (PyObject_SetAttr(state->match_case_type, state->guard, Py_None) == -1)\n        return 0;\n    state->pattern_type = make_type(state, \"pattern\", state->AST_type, NULL, 0,\n        \"pattern = MatchValue(expr value)\\n\"\n        \"        | MatchSingleton(constant value)\\n\"\n        \"        | MatchSequence(pattern* patterns)\\n\"\n        \"        | MatchMapping(expr* keys, pattern* patterns, identifier? rest)\\n\"\n        \"        | MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns)\\n\"\n        \"        | MatchStar(identifier? name)\\n\"\n        \"        | MatchAs(pattern? pattern, identifier? name)\\n\"\n        \"        | MatchOr(pattern* patterns)\");\n    if (!state->pattern_type) return 0;\n    if (!add_attributes(state, state->pattern_type, pattern_attributes, 4))\n        return 0;\n    state->MatchValue_type = make_type(state, \"MatchValue\",\n                                       state->pattern_type, MatchValue_fields,\n                                       1,\n        \"MatchValue(expr value)\");\n    if (!state->MatchValue_type) return 0;\n    state->MatchSingleton_type = make_type(state, \"MatchSingleton\",\n                                           state->pattern_type,\n                                           MatchSingleton_fields, 1,\n        \"MatchSingleton(constant value)\");\n    if (!state->MatchSingleton_type) return 0;\n    state->MatchSequence_type = make_type(state, \"MatchSequence\",\n                                          state->pattern_type,\n                                          MatchSequence_fields, 1,\n        \"MatchSequence(pattern* patterns)\");\n    if (!state->MatchSequence_type) return 0;\n    state->MatchMapping_type = make_type(state, \"MatchMapping\",\n                                         state->pattern_type,\n                                         MatchMapping_fields, 3,\n        \"MatchMapping(expr* keys, pattern* patterns, identifier? rest)\");\n    if (!state->MatchMapping_type) return 0;\n    if (PyObject_SetAttr(state->MatchMapping_type, state->rest, Py_None) == -1)\n        return 0;\n    state->MatchClass_type = make_type(state, \"MatchClass\",\n                                       state->pattern_type, MatchClass_fields,\n                                       4,\n        \"MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns)\");\n    if (!state->MatchClass_type) return 0;\n    state->MatchStar_type = make_type(state, \"MatchStar\", state->pattern_type,\n                                      MatchStar_fields, 1,\n        \"MatchStar(identifier? name)\");\n    if (!state->MatchStar_type) return 0;\n    if (PyObject_SetAttr(state->MatchStar_type, state->name, Py_None) == -1)\n        return 0;\n    state->MatchAs_type = make_type(state, \"MatchAs\", state->pattern_type,\n                                    MatchAs_fields, 2,\n        \"MatchAs(pattern? pattern, identifier? name)\");\n    if (!state->MatchAs_type) return 0;\n    if (PyObject_SetAttr(state->MatchAs_type, state->pattern, Py_None) == -1)\n        return 0;\n    if (PyObject_SetAttr(state->MatchAs_type, state->name, Py_None) == -1)\n        return 0;\n    state->MatchOr_type = make_type(state, \"MatchOr\", state->pattern_type,\n                                    MatchOr_fields, 1,\n        \"MatchOr(pattern* patterns)\");\n    if (!state->MatchOr_type) return 0;\n    state->type_ignore_type = make_type(state, \"type_ignore\", state->AST_type,\n                                        NULL, 0,\n        \"type_ignore = TypeIgnore(int lineno, string tag)\");\n    if (!state->type_ignore_type) return 0;\n    if (!add_attributes(state, state->type_ignore_type, NULL, 0)) return 0;\n    state->TypeIgnore_type = make_type(state, \"TypeIgnore\",\n                                       state->type_ignore_type,\n                                       TypeIgnore_fields, 2,\n        \"TypeIgnore(int lineno, string tag)\");\n    if (!state->TypeIgnore_type) return 0;\n    state->type_param_type = make_type(state, \"type_param\", state->AST_type,\n                                       NULL, 0,\n        \"type_param = TypeVar(identifier name, expr? bound)\\n\"\n        \"           | ParamSpec(identifier name)\\n\"\n        \"           | TypeVarTuple(identifier name)\");\n    if (!state->type_param_type) return 0;\n    if (!add_attributes(state, state->type_param_type, type_param_attributes,\n        4)) return 0;\n    if (PyObject_SetAttr(state->type_param_type, state->end_lineno, Py_None) ==\n        -1)\n        return 0;\n    if (PyObject_SetAttr(state->type_param_type, state->end_col_offset,\n        Py_None) == -1)\n        return 0;\n    state->TypeVar_type = make_type(state, \"TypeVar\", state->type_param_type,\n                                    TypeVar_fields, 2,\n        \"TypeVar(identifier name, expr? bound)\");\n    if (!state->TypeVar_type) return 0;\n    if (PyObject_SetAttr(state->TypeVar_type, state->bound, Py_None) == -1)\n        return 0;\n    state->ParamSpec_type = make_type(state, \"ParamSpec\",\n                                      state->type_param_type, ParamSpec_fields,\n                                      1,\n        \"ParamSpec(identifier name)\");\n    if (!state->ParamSpec_type) return 0;\n    state->TypeVarTuple_type = make_type(state, \"TypeVarTuple\",\n                                         state->type_param_type,\n                                         TypeVarTuple_fields, 1,\n        \"TypeVarTuple(identifier name)\");\n    if (!state->TypeVarTuple_type) return 0;\n\n    state->recursion_depth = 0;\n    state->recursion_limit = 0;\n    state->initialized = 1;\n    return 1;\n}\n\nstatic int obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out,\n                       PyArena* arena);\nstatic int obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out,\n                        PyArena* arena);\nstatic int obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out,\n                        PyArena* arena);\nstatic int obj2ast_expr_context(struct ast_state *state, PyObject* obj,\n                                expr_context_ty* out, PyArena* arena);\nstatic int obj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty*\n                          out, PyArena* arena);\nstatic int obj2ast_operator(struct ast_state *state, PyObject* obj,\n                            operator_ty* out, PyArena* arena);\nstatic int obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty*\n                           out, PyArena* arena);\nstatic int obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out,\n                         PyArena* arena);\nstatic int obj2ast_comprehension(struct ast_state *state, PyObject* obj,\n                                 comprehension_ty* out, PyArena* arena);\nstatic int obj2ast_excepthandler(struct ast_state *state, PyObject* obj,\n                                 excepthandler_ty* out, PyArena* arena);\nstatic int obj2ast_arguments(struct ast_state *state, PyObject* obj,\n                             arguments_ty* out, PyArena* arena);\nstatic int obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out,\n                       PyArena* arena);\nstatic int obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty*\n                           out, PyArena* arena);\nstatic int obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out,\n                         PyArena* arena);\nstatic int obj2ast_withitem(struct ast_state *state, PyObject* obj,\n                            withitem_ty* out, PyArena* arena);\nstatic int obj2ast_match_case(struct ast_state *state, PyObject* obj,\n                              match_case_ty* out, PyArena* arena);\nstatic int obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty*\n                           out, PyArena* arena);\nstatic int obj2ast_type_ignore(struct ast_state *state, PyObject* obj,\n                               type_ignore_ty* out, PyArena* arena);\nstatic int obj2ast_type_param(struct ast_state *state, PyObject* obj,\n                              type_param_ty* out, PyArena* arena);\n\nmod_ty\n_PyAST_Module(asdl_stmt_seq * body, asdl_type_ignore_seq * type_ignores,\n              PyArena *arena)\n{\n    mod_ty p;\n    p = (mod_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Module_kind;\n    p->v.Module.body = body;\n    p->v.Module.type_ignores = type_ignores;\n    return p;\n}\n\nmod_ty\n_PyAST_Interactive(asdl_stmt_seq * body, PyArena *arena)\n{\n    mod_ty p;\n    p = (mod_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Interactive_kind;\n    p->v.Interactive.body = body;\n    return p;\n}\n\nmod_ty\n_PyAST_Expression(expr_ty body, PyArena *arena)\n{\n    mod_ty p;\n    if (!body) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'body' is required for Expression\");\n        return NULL;\n    }\n    p = (mod_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Expression_kind;\n    p->v.Expression.body = body;\n    return p;\n}\n\nmod_ty\n_PyAST_FunctionType(asdl_expr_seq * argtypes, expr_ty returns, PyArena *arena)\n{\n    mod_ty p;\n    if (!returns) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'returns' is required for FunctionType\");\n        return NULL;\n    }\n    p = (mod_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = FunctionType_kind;\n    p->v.FunctionType.argtypes = argtypes;\n    p->v.FunctionType.returns = returns;\n    return p;\n}\n\nstmt_ty\n_PyAST_FunctionDef(identifier name, arguments_ty args, asdl_stmt_seq * body,\n                   asdl_expr_seq * decorator_list, expr_ty returns, string\n                   type_comment, asdl_type_param_seq * type_params, int lineno,\n                   int col_offset, int end_lineno, int end_col_offset, PyArena\n                   *arena)\n{\n    stmt_ty p;\n    if (!name) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'name' is required for FunctionDef\");\n        return NULL;\n    }\n    if (!args) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'args' is required for FunctionDef\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = FunctionDef_kind;\n    p->v.FunctionDef.name = name;\n    p->v.FunctionDef.args = args;\n    p->v.FunctionDef.body = body;\n    p->v.FunctionDef.decorator_list = decorator_list;\n    p->v.FunctionDef.returns = returns;\n    p->v.FunctionDef.type_comment = type_comment;\n    p->v.FunctionDef.type_params = type_params;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_AsyncFunctionDef(identifier name, arguments_ty args, asdl_stmt_seq *\n                        body, asdl_expr_seq * decorator_list, expr_ty returns,\n                        string type_comment, asdl_type_param_seq * type_params,\n                        int lineno, int col_offset, int end_lineno, int\n                        end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    if (!name) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'name' is required for AsyncFunctionDef\");\n        return NULL;\n    }\n    if (!args) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'args' is required for AsyncFunctionDef\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = AsyncFunctionDef_kind;\n    p->v.AsyncFunctionDef.name = name;\n    p->v.AsyncFunctionDef.args = args;\n    p->v.AsyncFunctionDef.body = body;\n    p->v.AsyncFunctionDef.decorator_list = decorator_list;\n    p->v.AsyncFunctionDef.returns = returns;\n    p->v.AsyncFunctionDef.type_comment = type_comment;\n    p->v.AsyncFunctionDef.type_params = type_params;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_ClassDef(identifier name, asdl_expr_seq * bases, asdl_keyword_seq *\n                keywords, asdl_stmt_seq * body, asdl_expr_seq * decorator_list,\n                asdl_type_param_seq * type_params, int lineno, int col_offset,\n                int end_lineno, int end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    if (!name) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'name' is required for ClassDef\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = ClassDef_kind;\n    p->v.ClassDef.name = name;\n    p->v.ClassDef.bases = bases;\n    p->v.ClassDef.keywords = keywords;\n    p->v.ClassDef.body = body;\n    p->v.ClassDef.decorator_list = decorator_list;\n    p->v.ClassDef.type_params = type_params;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Return(expr_ty value, int lineno, int col_offset, int end_lineno, int\n              end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Return_kind;\n    p->v.Return.value = value;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Delete(asdl_expr_seq * targets, int lineno, int col_offset, int\n              end_lineno, int end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Delete_kind;\n    p->v.Delete.targets = targets;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Assign(asdl_expr_seq * targets, expr_ty value, string type_comment, int\n              lineno, int col_offset, int end_lineno, int end_col_offset,\n              PyArena *arena)\n{\n    stmt_ty p;\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for Assign\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Assign_kind;\n    p->v.Assign.targets = targets;\n    p->v.Assign.value = value;\n    p->v.Assign.type_comment = type_comment;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_TypeAlias(expr_ty name, asdl_type_param_seq * type_params, expr_ty\n                 value, int lineno, int col_offset, int end_lineno, int\n                 end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    if (!name) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'name' is required for TypeAlias\");\n        return NULL;\n    }\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for TypeAlias\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = TypeAlias_kind;\n    p->v.TypeAlias.name = name;\n    p->v.TypeAlias.type_params = type_params;\n    p->v.TypeAlias.value = value;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno, int\n                 col_offset, int end_lineno, int end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    if (!target) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'target' is required for AugAssign\");\n        return NULL;\n    }\n    if (!op) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'op' is required for AugAssign\");\n        return NULL;\n    }\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for AugAssign\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = AugAssign_kind;\n    p->v.AugAssign.target = target;\n    p->v.AugAssign.op = op;\n    p->v.AugAssign.value = value;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_AnnAssign(expr_ty target, expr_ty annotation, expr_ty value, int simple,\n                 int lineno, int col_offset, int end_lineno, int\n                 end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    if (!target) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'target' is required for AnnAssign\");\n        return NULL;\n    }\n    if (!annotation) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'annotation' is required for AnnAssign\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = AnnAssign_kind;\n    p->v.AnnAssign.target = target;\n    p->v.AnnAssign.annotation = annotation;\n    p->v.AnnAssign.value = value;\n    p->v.AnnAssign.simple = simple;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_For(expr_ty target, expr_ty iter, asdl_stmt_seq * body, asdl_stmt_seq *\n           orelse, string type_comment, int lineno, int col_offset, int\n           end_lineno, int end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    if (!target) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'target' is required for For\");\n        return NULL;\n    }\n    if (!iter) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'iter' is required for For\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = For_kind;\n    p->v.For.target = target;\n    p->v.For.iter = iter;\n    p->v.For.body = body;\n    p->v.For.orelse = orelse;\n    p->v.For.type_comment = type_comment;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_AsyncFor(expr_ty target, expr_ty iter, asdl_stmt_seq * body,\n                asdl_stmt_seq * orelse, string type_comment, int lineno, int\n                col_offset, int end_lineno, int end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    if (!target) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'target' is required for AsyncFor\");\n        return NULL;\n    }\n    if (!iter) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'iter' is required for AsyncFor\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = AsyncFor_kind;\n    p->v.AsyncFor.target = target;\n    p->v.AsyncFor.iter = iter;\n    p->v.AsyncFor.body = body;\n    p->v.AsyncFor.orelse = orelse;\n    p->v.AsyncFor.type_comment = type_comment;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_While(expr_ty test, asdl_stmt_seq * body, asdl_stmt_seq * orelse, int\n             lineno, int col_offset, int end_lineno, int end_col_offset,\n             PyArena *arena)\n{\n    stmt_ty p;\n    if (!test) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'test' is required for While\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = While_kind;\n    p->v.While.test = test;\n    p->v.While.body = body;\n    p->v.While.orelse = orelse;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_If(expr_ty test, asdl_stmt_seq * body, asdl_stmt_seq * orelse, int\n          lineno, int col_offset, int end_lineno, int end_col_offset, PyArena\n          *arena)\n{\n    stmt_ty p;\n    if (!test) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'test' is required for If\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = If_kind;\n    p->v.If.test = test;\n    p->v.If.body = body;\n    p->v.If.orelse = orelse;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_With(asdl_withitem_seq * items, asdl_stmt_seq * body, string\n            type_comment, int lineno, int col_offset, int end_lineno, int\n            end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = With_kind;\n    p->v.With.items = items;\n    p->v.With.body = body;\n    p->v.With.type_comment = type_comment;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_AsyncWith(asdl_withitem_seq * items, asdl_stmt_seq * body, string\n                 type_comment, int lineno, int col_offset, int end_lineno, int\n                 end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = AsyncWith_kind;\n    p->v.AsyncWith.items = items;\n    p->v.AsyncWith.body = body;\n    p->v.AsyncWith.type_comment = type_comment;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Match(expr_ty subject, asdl_match_case_seq * cases, int lineno, int\n             col_offset, int end_lineno, int end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    if (!subject) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'subject' is required for Match\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Match_kind;\n    p->v.Match.subject = subject;\n    p->v.Match.cases = cases;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, int\n             end_lineno, int end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Raise_kind;\n    p->v.Raise.exc = exc;\n    p->v.Raise.cause = cause;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Try(asdl_stmt_seq * body, asdl_excepthandler_seq * handlers,\n           asdl_stmt_seq * orelse, asdl_stmt_seq * finalbody, int lineno, int\n           col_offset, int end_lineno, int end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Try_kind;\n    p->v.Try.body = body;\n    p->v.Try.handlers = handlers;\n    p->v.Try.orelse = orelse;\n    p->v.Try.finalbody = finalbody;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_TryStar(asdl_stmt_seq * body, asdl_excepthandler_seq * handlers,\n               asdl_stmt_seq * orelse, asdl_stmt_seq * finalbody, int lineno,\n               int col_offset, int end_lineno, int end_col_offset, PyArena\n               *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = TryStar_kind;\n    p->v.TryStar.body = body;\n    p->v.TryStar.handlers = handlers;\n    p->v.TryStar.orelse = orelse;\n    p->v.TryStar.finalbody = finalbody;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, int\n              end_lineno, int end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    if (!test) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'test' is required for Assert\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Assert_kind;\n    p->v.Assert.test = test;\n    p->v.Assert.msg = msg;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int\n              end_lineno, int end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Import_kind;\n    p->v.Import.names = names;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_ImportFrom(identifier module, asdl_alias_seq * names, int level, int\n                  lineno, int col_offset, int end_lineno, int end_col_offset,\n                  PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = ImportFrom_kind;\n    p->v.ImportFrom.module = module;\n    p->v.ImportFrom.names = names;\n    p->v.ImportFrom.level = level;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Global(asdl_identifier_seq * names, int lineno, int col_offset, int\n              end_lineno, int end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Global_kind;\n    p->v.Global.names = names;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Nonlocal(asdl_identifier_seq * names, int lineno, int col_offset, int\n                end_lineno, int end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Nonlocal_kind;\n    p->v.Nonlocal.names = names;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Expr(expr_ty value, int lineno, int col_offset, int end_lineno, int\n            end_col_offset, PyArena *arena)\n{\n    stmt_ty p;\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for Expr\");\n        return NULL;\n    }\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Expr_kind;\n    p->v.Expr.value = value;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Pass(int lineno, int col_offset, int end_lineno, int end_col_offset,\n            PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Pass_kind;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Break(int lineno, int col_offset, int end_lineno, int end_col_offset,\n             PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Break_kind;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nstmt_ty\n_PyAST_Continue(int lineno, int col_offset, int end_lineno, int end_col_offset,\n                PyArena *arena)\n{\n    stmt_ty p;\n    p = (stmt_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Continue_kind;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_BoolOp(boolop_ty op, asdl_expr_seq * values, int lineno, int col_offset,\n              int end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!op) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'op' is required for BoolOp\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = BoolOp_kind;\n    p->v.BoolOp.op = op;\n    p->v.BoolOp.values = values;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_NamedExpr(expr_ty target, expr_ty value, int lineno, int col_offset, int\n                 end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!target) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'target' is required for NamedExpr\");\n        return NULL;\n    }\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for NamedExpr\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = NamedExpr_kind;\n    p->v.NamedExpr.target = target;\n    p->v.NamedExpr.value = value;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno, int\n             col_offset, int end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!left) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'left' is required for BinOp\");\n        return NULL;\n    }\n    if (!op) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'op' is required for BinOp\");\n        return NULL;\n    }\n    if (!right) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'right' is required for BinOp\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = BinOp_kind;\n    p->v.BinOp.left = left;\n    p->v.BinOp.op = op;\n    p->v.BinOp.right = right;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_UnaryOp(unaryop_ty op, expr_ty operand, int lineno, int col_offset, int\n               end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!op) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'op' is required for UnaryOp\");\n        return NULL;\n    }\n    if (!operand) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'operand' is required for UnaryOp\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = UnaryOp_kind;\n    p->v.UnaryOp.op = op;\n    p->v.UnaryOp.operand = operand;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Lambda(arguments_ty args, expr_ty body, int lineno, int col_offset, int\n              end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!args) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'args' is required for Lambda\");\n        return NULL;\n    }\n    if (!body) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'body' is required for Lambda\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Lambda_kind;\n    p->v.Lambda.args = args;\n    p->v.Lambda.body = body;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_IfExp(expr_ty test, expr_ty body, expr_ty orelse, int lineno, int\n             col_offset, int end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!test) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'test' is required for IfExp\");\n        return NULL;\n    }\n    if (!body) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'body' is required for IfExp\");\n        return NULL;\n    }\n    if (!orelse) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'orelse' is required for IfExp\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = IfExp_kind;\n    p->v.IfExp.test = test;\n    p->v.IfExp.body = body;\n    p->v.IfExp.orelse = orelse;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Dict(asdl_expr_seq * keys, asdl_expr_seq * values, int lineno, int\n            col_offset, int end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Dict_kind;\n    p->v.Dict.keys = keys;\n    p->v.Dict.values = values;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Set(asdl_expr_seq * elts, int lineno, int col_offset, int end_lineno,\n           int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Set_kind;\n    p->v.Set.elts = elts;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_ListComp(expr_ty elt, asdl_comprehension_seq * generators, int lineno,\n                int col_offset, int end_lineno, int end_col_offset, PyArena\n                *arena)\n{\n    expr_ty p;\n    if (!elt) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'elt' is required for ListComp\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = ListComp_kind;\n    p->v.ListComp.elt = elt;\n    p->v.ListComp.generators = generators;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_SetComp(expr_ty elt, asdl_comprehension_seq * generators, int lineno,\n               int col_offset, int end_lineno, int end_col_offset, PyArena\n               *arena)\n{\n    expr_ty p;\n    if (!elt) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'elt' is required for SetComp\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = SetComp_kind;\n    p->v.SetComp.elt = elt;\n    p->v.SetComp.generators = generators;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_DictComp(expr_ty key, expr_ty value, asdl_comprehension_seq *\n                generators, int lineno, int col_offset, int end_lineno, int\n                end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!key) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'key' is required for DictComp\");\n        return NULL;\n    }\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for DictComp\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = DictComp_kind;\n    p->v.DictComp.key = key;\n    p->v.DictComp.value = value;\n    p->v.DictComp.generators = generators;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_GeneratorExp(expr_ty elt, asdl_comprehension_seq * generators, int\n                    lineno, int col_offset, int end_lineno, int end_col_offset,\n                    PyArena *arena)\n{\n    expr_ty p;\n    if (!elt) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'elt' is required for GeneratorExp\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = GeneratorExp_kind;\n    p->v.GeneratorExp.elt = elt;\n    p->v.GeneratorExp.generators = generators;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Await(expr_ty value, int lineno, int col_offset, int end_lineno, int\n             end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for Await\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Await_kind;\n    p->v.Await.value = value;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Yield(expr_ty value, int lineno, int col_offset, int end_lineno, int\n             end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Yield_kind;\n    p->v.Yield.value = value;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_YieldFrom(expr_ty value, int lineno, int col_offset, int end_lineno, int\n                 end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for YieldFrom\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = YieldFrom_kind;\n    p->v.YieldFrom.value = value;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Compare(expr_ty left, asdl_int_seq * ops, asdl_expr_seq * comparators,\n               int lineno, int col_offset, int end_lineno, int end_col_offset,\n               PyArena *arena)\n{\n    expr_ty p;\n    if (!left) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'left' is required for Compare\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Compare_kind;\n    p->v.Compare.left = left;\n    p->v.Compare.ops = ops;\n    p->v.Compare.comparators = comparators;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Call(expr_ty func, asdl_expr_seq * args, asdl_keyword_seq * keywords,\n            int lineno, int col_offset, int end_lineno, int end_col_offset,\n            PyArena *arena)\n{\n    expr_ty p;\n    if (!func) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'func' is required for Call\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Call_kind;\n    p->v.Call.func = func;\n    p->v.Call.args = args;\n    p->v.Call.keywords = keywords;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_FormattedValue(expr_ty value, int conversion, expr_ty format_spec, int\n                      lineno, int col_offset, int end_lineno, int\n                      end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for FormattedValue\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = FormattedValue_kind;\n    p->v.FormattedValue.value = value;\n    p->v.FormattedValue.conversion = conversion;\n    p->v.FormattedValue.format_spec = format_spec;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_JoinedStr(asdl_expr_seq * values, int lineno, int col_offset, int\n                 end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = JoinedStr_kind;\n    p->v.JoinedStr.values = values;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Constant(constant value, string kind, int lineno, int col_offset, int\n                end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for Constant\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Constant_kind;\n    p->v.Constant.value = value;\n    p->v.Constant.kind = kind;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Attribute(expr_ty value, identifier attr, expr_context_ty ctx, int\n                 lineno, int col_offset, int end_lineno, int end_col_offset,\n                 PyArena *arena)\n{\n    expr_ty p;\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for Attribute\");\n        return NULL;\n    }\n    if (!attr) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'attr' is required for Attribute\");\n        return NULL;\n    }\n    if (!ctx) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'ctx' is required for Attribute\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Attribute_kind;\n    p->v.Attribute.value = value;\n    p->v.Attribute.attr = attr;\n    p->v.Attribute.ctx = ctx;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Subscript(expr_ty value, expr_ty slice, expr_context_ty ctx, int lineno,\n                 int col_offset, int end_lineno, int end_col_offset, PyArena\n                 *arena)\n{\n    expr_ty p;\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for Subscript\");\n        return NULL;\n    }\n    if (!slice) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'slice' is required for Subscript\");\n        return NULL;\n    }\n    if (!ctx) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'ctx' is required for Subscript\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Subscript_kind;\n    p->v.Subscript.value = value;\n    p->v.Subscript.slice = slice;\n    p->v.Subscript.ctx = ctx;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Starred(expr_ty value, expr_context_ty ctx, int lineno, int col_offset,\n               int end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for Starred\");\n        return NULL;\n    }\n    if (!ctx) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'ctx' is required for Starred\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Starred_kind;\n    p->v.Starred.value = value;\n    p->v.Starred.ctx = ctx;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Name(identifier id, expr_context_ty ctx, int lineno, int col_offset, int\n            end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!id) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'id' is required for Name\");\n        return NULL;\n    }\n    if (!ctx) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'ctx' is required for Name\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Name_kind;\n    p->v.Name.id = id;\n    p->v.Name.ctx = ctx;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_List(asdl_expr_seq * elts, expr_context_ty ctx, int lineno, int\n            col_offset, int end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!ctx) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'ctx' is required for List\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = List_kind;\n    p->v.List.elts = elts;\n    p->v.List.ctx = ctx;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Tuple(asdl_expr_seq * elts, expr_context_ty ctx, int lineno, int\n             col_offset, int end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    if (!ctx) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'ctx' is required for Tuple\");\n        return NULL;\n    }\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Tuple_kind;\n    p->v.Tuple.elts = elts;\n    p->v.Tuple.ctx = ctx;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nexpr_ty\n_PyAST_Slice(expr_ty lower, expr_ty upper, expr_ty step, int lineno, int\n             col_offset, int end_lineno, int end_col_offset, PyArena *arena)\n{\n    expr_ty p;\n    p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = Slice_kind;\n    p->v.Slice.lower = lower;\n    p->v.Slice.upper = upper;\n    p->v.Slice.step = step;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\ncomprehension_ty\n_PyAST_comprehension(expr_ty target, expr_ty iter, asdl_expr_seq * ifs, int\n                     is_async, PyArena *arena)\n{\n    comprehension_ty p;\n    if (!target) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'target' is required for comprehension\");\n        return NULL;\n    }\n    if (!iter) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'iter' is required for comprehension\");\n        return NULL;\n    }\n    p = (comprehension_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->target = target;\n    p->iter = iter;\n    p->ifs = ifs;\n    p->is_async = is_async;\n    return p;\n}\n\nexcepthandler_ty\n_PyAST_ExceptHandler(expr_ty type, identifier name, asdl_stmt_seq * body, int\n                     lineno, int col_offset, int end_lineno, int\n                     end_col_offset, PyArena *arena)\n{\n    excepthandler_ty p;\n    p = (excepthandler_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = ExceptHandler_kind;\n    p->v.ExceptHandler.type = type;\n    p->v.ExceptHandler.name = name;\n    p->v.ExceptHandler.body = body;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\narguments_ty\n_PyAST_arguments(asdl_arg_seq * posonlyargs, asdl_arg_seq * args, arg_ty\n                 vararg, asdl_arg_seq * kwonlyargs, asdl_expr_seq *\n                 kw_defaults, arg_ty kwarg, asdl_expr_seq * defaults, PyArena\n                 *arena)\n{\n    arguments_ty p;\n    p = (arguments_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->posonlyargs = posonlyargs;\n    p->args = args;\n    p->vararg = vararg;\n    p->kwonlyargs = kwonlyargs;\n    p->kw_defaults = kw_defaults;\n    p->kwarg = kwarg;\n    p->defaults = defaults;\n    return p;\n}\n\narg_ty\n_PyAST_arg(identifier arg, expr_ty annotation, string type_comment, int lineno,\n           int col_offset, int end_lineno, int end_col_offset, PyArena *arena)\n{\n    arg_ty p;\n    if (!arg) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'arg' is required for arg\");\n        return NULL;\n    }\n    p = (arg_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->arg = arg;\n    p->annotation = annotation;\n    p->type_comment = type_comment;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nkeyword_ty\n_PyAST_keyword(identifier arg, expr_ty value, int lineno, int col_offset, int\n               end_lineno, int end_col_offset, PyArena *arena)\n{\n    keyword_ty p;\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for keyword\");\n        return NULL;\n    }\n    p = (keyword_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->arg = arg;\n    p->value = value;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nalias_ty\n_PyAST_alias(identifier name, identifier asname, int lineno, int col_offset,\n             int end_lineno, int end_col_offset, PyArena *arena)\n{\n    alias_ty p;\n    if (!name) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'name' is required for alias\");\n        return NULL;\n    }\n    p = (alias_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->name = name;\n    p->asname = asname;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\nwithitem_ty\n_PyAST_withitem(expr_ty context_expr, expr_ty optional_vars, PyArena *arena)\n{\n    withitem_ty p;\n    if (!context_expr) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'context_expr' is required for withitem\");\n        return NULL;\n    }\n    p = (withitem_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->context_expr = context_expr;\n    p->optional_vars = optional_vars;\n    return p;\n}\n\nmatch_case_ty\n_PyAST_match_case(pattern_ty pattern, expr_ty guard, asdl_stmt_seq * body,\n                  PyArena *arena)\n{\n    match_case_ty p;\n    if (!pattern) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'pattern' is required for match_case\");\n        return NULL;\n    }\n    p = (match_case_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->pattern = pattern;\n    p->guard = guard;\n    p->body = body;\n    return p;\n}\n\npattern_ty\n_PyAST_MatchValue(expr_ty value, int lineno, int col_offset, int end_lineno,\n                  int end_col_offset, PyArena *arena)\n{\n    pattern_ty p;\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for MatchValue\");\n        return NULL;\n    }\n    p = (pattern_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = MatchValue_kind;\n    p->v.MatchValue.value = value;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\npattern_ty\n_PyAST_MatchSingleton(constant value, int lineno, int col_offset, int\n                      end_lineno, int end_col_offset, PyArena *arena)\n{\n    pattern_ty p;\n    if (!value) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'value' is required for MatchSingleton\");\n        return NULL;\n    }\n    p = (pattern_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = MatchSingleton_kind;\n    p->v.MatchSingleton.value = value;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\npattern_ty\n_PyAST_MatchSequence(asdl_pattern_seq * patterns, int lineno, int col_offset,\n                     int end_lineno, int end_col_offset, PyArena *arena)\n{\n    pattern_ty p;\n    p = (pattern_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = MatchSequence_kind;\n    p->v.MatchSequence.patterns = patterns;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\npattern_ty\n_PyAST_MatchMapping(asdl_expr_seq * keys, asdl_pattern_seq * patterns,\n                    identifier rest, int lineno, int col_offset, int\n                    end_lineno, int end_col_offset, PyArena *arena)\n{\n    pattern_ty p;\n    p = (pattern_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = MatchMapping_kind;\n    p->v.MatchMapping.keys = keys;\n    p->v.MatchMapping.patterns = patterns;\n    p->v.MatchMapping.rest = rest;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\npattern_ty\n_PyAST_MatchClass(expr_ty cls, asdl_pattern_seq * patterns, asdl_identifier_seq\n                  * kwd_attrs, asdl_pattern_seq * kwd_patterns, int lineno, int\n                  col_offset, int end_lineno, int end_col_offset, PyArena\n                  *arena)\n{\n    pattern_ty p;\n    if (!cls) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'cls' is required for MatchClass\");\n        return NULL;\n    }\n    p = (pattern_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = MatchClass_kind;\n    p->v.MatchClass.cls = cls;\n    p->v.MatchClass.patterns = patterns;\n    p->v.MatchClass.kwd_attrs = kwd_attrs;\n    p->v.MatchClass.kwd_patterns = kwd_patterns;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\npattern_ty\n_PyAST_MatchStar(identifier name, int lineno, int col_offset, int end_lineno,\n                 int end_col_offset, PyArena *arena)\n{\n    pattern_ty p;\n    p = (pattern_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = MatchStar_kind;\n    p->v.MatchStar.name = name;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\npattern_ty\n_PyAST_MatchAs(pattern_ty pattern, identifier name, int lineno, int col_offset,\n               int end_lineno, int end_col_offset, PyArena *arena)\n{\n    pattern_ty p;\n    p = (pattern_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = MatchAs_kind;\n    p->v.MatchAs.pattern = pattern;\n    p->v.MatchAs.name = name;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\npattern_ty\n_PyAST_MatchOr(asdl_pattern_seq * patterns, int lineno, int col_offset, int\n               end_lineno, int end_col_offset, PyArena *arena)\n{\n    pattern_ty p;\n    p = (pattern_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = MatchOr_kind;\n    p->v.MatchOr.patterns = patterns;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\ntype_ignore_ty\n_PyAST_TypeIgnore(int lineno, string tag, PyArena *arena)\n{\n    type_ignore_ty p;\n    if (!tag) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'tag' is required for TypeIgnore\");\n        return NULL;\n    }\n    p = (type_ignore_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = TypeIgnore_kind;\n    p->v.TypeIgnore.lineno = lineno;\n    p->v.TypeIgnore.tag = tag;\n    return p;\n}\n\ntype_param_ty\n_PyAST_TypeVar(identifier name, expr_ty bound, int lineno, int col_offset, int\n               end_lineno, int end_col_offset, PyArena *arena)\n{\n    type_param_ty p;\n    if (!name) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'name' is required for TypeVar\");\n        return NULL;\n    }\n    p = (type_param_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = TypeVar_kind;\n    p->v.TypeVar.name = name;\n    p->v.TypeVar.bound = bound;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\ntype_param_ty\n_PyAST_ParamSpec(identifier name, int lineno, int col_offset, int end_lineno,\n                 int end_col_offset, PyArena *arena)\n{\n    type_param_ty p;\n    if (!name) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'name' is required for ParamSpec\");\n        return NULL;\n    }\n    p = (type_param_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = ParamSpec_kind;\n    p->v.ParamSpec.name = name;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\ntype_param_ty\n_PyAST_TypeVarTuple(identifier name, int lineno, int col_offset, int\n                    end_lineno, int end_col_offset, PyArena *arena)\n{\n    type_param_ty p;\n    if (!name) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"field 'name' is required for TypeVarTuple\");\n        return NULL;\n    }\n    p = (type_param_ty)_PyArena_Malloc(arena, sizeof(*p));\n    if (!p)\n        return NULL;\n    p->kind = TypeVarTuple_kind;\n    p->v.TypeVarTuple.name = name;\n    p->lineno = lineno;\n    p->col_offset = col_offset;\n    p->end_lineno = end_lineno;\n    p->end_col_offset = end_col_offset;\n    return p;\n}\n\n\nPyObject*\nast2obj_mod(struct ast_state *state, void* _o)\n{\n    mod_ty o = (mod_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    switch (o->kind) {\n    case Module_kind:\n        tp = (PyTypeObject *)state->Module_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.Module.body, ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.Module.type_ignores,\n                             ast2obj_type_ignore);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type_ignores, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Interactive_kind:\n        tp = (PyTypeObject *)state->Interactive_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.Interactive.body,\n                             ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Expression_kind:\n        tp = (PyTypeObject *)state->Expression_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Expression.body);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case FunctionType_kind:\n        tp = (PyTypeObject *)state->FunctionType_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.FunctionType.argtypes,\n                             ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->argtypes, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.FunctionType.returns);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->returns, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    }\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject*\nast2obj_stmt(struct ast_state *state, void* _o)\n{\n    stmt_ty o = (stmt_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    switch (o->kind) {\n    case FunctionDef_kind:\n        tp = (PyTypeObject *)state->FunctionDef_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_identifier(state, o->v.FunctionDef.name);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->name, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_arguments(state, o->v.FunctionDef.args);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->args, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.FunctionDef.body,\n                             ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.FunctionDef.decorator_list,\n                             ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->decorator_list, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.FunctionDef.returns);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->returns, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_string(state, o->v.FunctionDef.type_comment);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type_comment, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.FunctionDef.type_params,\n                             ast2obj_type_param);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type_params, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case AsyncFunctionDef_kind:\n        tp = (PyTypeObject *)state->AsyncFunctionDef_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_identifier(state, o->v.AsyncFunctionDef.name);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->name, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_arguments(state, o->v.AsyncFunctionDef.args);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->args, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.AsyncFunctionDef.body,\n                             ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state,\n                             (asdl_seq*)o->v.AsyncFunctionDef.decorator_list,\n                             ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->decorator_list, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.AsyncFunctionDef.returns);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->returns, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_string(state, o->v.AsyncFunctionDef.type_comment);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type_comment, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state,\n                             (asdl_seq*)o->v.AsyncFunctionDef.type_params,\n                             ast2obj_type_param);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type_params, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case ClassDef_kind:\n        tp = (PyTypeObject *)state->ClassDef_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_identifier(state, o->v.ClassDef.name);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->name, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.bases,\n                             ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->bases, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.keywords,\n                             ast2obj_keyword);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->keywords, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.body,\n                             ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.decorator_list,\n                             ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->decorator_list, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.ClassDef.type_params,\n                             ast2obj_type_param);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type_params, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Return_kind:\n        tp = (PyTypeObject *)state->Return_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Return.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Delete_kind:\n        tp = (PyTypeObject *)state->Delete_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.Delete.targets,\n                             ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->targets, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Assign_kind:\n        tp = (PyTypeObject *)state->Assign_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.Assign.targets,\n                             ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->targets, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.Assign.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_string(state, o->v.Assign.type_comment);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type_comment, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case TypeAlias_kind:\n        tp = (PyTypeObject *)state->TypeAlias_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.TypeAlias.name);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->name, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.TypeAlias.type_params,\n                             ast2obj_type_param);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type_params, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.TypeAlias.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case AugAssign_kind:\n        tp = (PyTypeObject *)state->AugAssign_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.AugAssign.target);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->target, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_operator(state, o->v.AugAssign.op);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->op, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.AugAssign.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case AnnAssign_kind:\n        tp = (PyTypeObject *)state->AnnAssign_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.AnnAssign.target);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->target, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.AnnAssign.annotation);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->annotation, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.AnnAssign.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_int(state, o->v.AnnAssign.simple);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->simple, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case For_kind:\n        tp = (PyTypeObject *)state->For_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.For.target);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->target, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.For.iter);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->iter, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.For.body, ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.For.orelse, ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->orelse, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_string(state, o->v.For.type_comment);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type_comment, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case AsyncFor_kind:\n        tp = (PyTypeObject *)state->AsyncFor_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.AsyncFor.target);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->target, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.AsyncFor.iter);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->iter, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.AsyncFor.body,\n                             ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.AsyncFor.orelse,\n                             ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->orelse, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_string(state, o->v.AsyncFor.type_comment);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type_comment, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case While_kind:\n        tp = (PyTypeObject *)state->While_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.While.test);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->test, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.While.body, ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.While.orelse, ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->orelse, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case If_kind:\n        tp = (PyTypeObject *)state->If_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.If.test);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->test, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.If.body, ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.If.orelse, ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->orelse, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case With_kind:\n        tp = (PyTypeObject *)state->With_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.With.items,\n                             ast2obj_withitem);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->items, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.With.body, ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_string(state, o->v.With.type_comment);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type_comment, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case AsyncWith_kind:\n        tp = (PyTypeObject *)state->AsyncWith_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.AsyncWith.items,\n                             ast2obj_withitem);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->items, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.AsyncWith.body,\n                             ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_string(state, o->v.AsyncWith.type_comment);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type_comment, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Match_kind:\n        tp = (PyTypeObject *)state->Match_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Match.subject);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->subject, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.Match.cases,\n                             ast2obj_match_case);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->cases, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Raise_kind:\n        tp = (PyTypeObject *)state->Raise_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Raise.exc);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->exc, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.Raise.cause);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->cause, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Try_kind:\n        tp = (PyTypeObject *)state->Try_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.Try.body, ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.Try.handlers,\n                             ast2obj_excepthandler);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->handlers, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.Try.orelse, ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->orelse, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.Try.finalbody,\n                             ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->finalbody, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case TryStar_kind:\n        tp = (PyTypeObject *)state->TryStar_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.body, ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.handlers,\n                             ast2obj_excepthandler);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->handlers, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.orelse,\n                             ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->orelse, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.TryStar.finalbody,\n                             ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->finalbody, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Assert_kind:\n        tp = (PyTypeObject *)state->Assert_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Assert.test);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->test, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.Assert.msg);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->msg, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Import_kind:\n        tp = (PyTypeObject *)state->Import_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.Import.names,\n                             ast2obj_alias);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->names, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case ImportFrom_kind:\n        tp = (PyTypeObject *)state->ImportFrom_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_identifier(state, o->v.ImportFrom.module);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->module, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.ImportFrom.names,\n                             ast2obj_alias);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->names, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_int(state, o->v.ImportFrom.level);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->level, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Global_kind:\n        tp = (PyTypeObject *)state->Global_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.Global.names,\n                             ast2obj_identifier);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->names, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Nonlocal_kind:\n        tp = (PyTypeObject *)state->Nonlocal_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.Nonlocal.names,\n                             ast2obj_identifier);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->names, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Expr_kind:\n        tp = (PyTypeObject *)state->Expr_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Expr.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Pass_kind:\n        tp = (PyTypeObject *)state->Pass_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        break;\n    case Break_kind:\n        tp = (PyTypeObject *)state->Break_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        break;\n    case Continue_kind:\n        tp = (PyTypeObject *)state->Continue_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        break;\n    }\n    value = ast2obj_int(state, o->lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject*\nast2obj_expr(struct ast_state *state, void* _o)\n{\n    expr_ty o = (expr_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    switch (o->kind) {\n    case BoolOp_kind:\n        tp = (PyTypeObject *)state->BoolOp_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_boolop(state, o->v.BoolOp.op);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->op, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.BoolOp.values,\n                             ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->values, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case NamedExpr_kind:\n        tp = (PyTypeObject *)state->NamedExpr_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.NamedExpr.target);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->target, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.NamedExpr.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case BinOp_kind:\n        tp = (PyTypeObject *)state->BinOp_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.BinOp.left);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->left, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_operator(state, o->v.BinOp.op);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->op, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.BinOp.right);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->right, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case UnaryOp_kind:\n        tp = (PyTypeObject *)state->UnaryOp_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_unaryop(state, o->v.UnaryOp.op);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->op, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.UnaryOp.operand);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->operand, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Lambda_kind:\n        tp = (PyTypeObject *)state->Lambda_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_arguments(state, o->v.Lambda.args);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->args, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.Lambda.body);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case IfExp_kind:\n        tp = (PyTypeObject *)state->IfExp_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.IfExp.test);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->test, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.IfExp.body);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.IfExp.orelse);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->orelse, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Dict_kind:\n        tp = (PyTypeObject *)state->Dict_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.Dict.keys, ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->keys, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.Dict.values, ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->values, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Set_kind:\n        tp = (PyTypeObject *)state->Set_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.Set.elts, ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->elts, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case ListComp_kind:\n        tp = (PyTypeObject *)state->ListComp_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.ListComp.elt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->elt, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.ListComp.generators,\n                             ast2obj_comprehension);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->generators, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case SetComp_kind:\n        tp = (PyTypeObject *)state->SetComp_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.SetComp.elt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->elt, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.SetComp.generators,\n                             ast2obj_comprehension);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->generators, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case DictComp_kind:\n        tp = (PyTypeObject *)state->DictComp_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.DictComp.key);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->key, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.DictComp.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.DictComp.generators,\n                             ast2obj_comprehension);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->generators, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case GeneratorExp_kind:\n        tp = (PyTypeObject *)state->GeneratorExp_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.GeneratorExp.elt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->elt, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.GeneratorExp.generators,\n                             ast2obj_comprehension);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->generators, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Await_kind:\n        tp = (PyTypeObject *)state->Await_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Await.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Yield_kind:\n        tp = (PyTypeObject *)state->Yield_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Yield.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case YieldFrom_kind:\n        tp = (PyTypeObject *)state->YieldFrom_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.YieldFrom.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Compare_kind:\n        tp = (PyTypeObject *)state->Compare_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Compare.left);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->left, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        {\n            Py_ssize_t i, n = asdl_seq_LEN(o->v.Compare.ops);\n            value = PyList_New(n);\n            if (!value) goto failed;\n            for(i = 0; i < n; i++)\n                PyList_SET_ITEM(value, i, ast2obj_cmpop(state, (cmpop_ty)asdl_seq_GET(o->v.Compare.ops, i)));\n        }\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->ops, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.Compare.comparators,\n                             ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->comparators, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Call_kind:\n        tp = (PyTypeObject *)state->Call_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Call.func);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->func, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.Call.args, ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->args, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.Call.keywords,\n                             ast2obj_keyword);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->keywords, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case FormattedValue_kind:\n        tp = (PyTypeObject *)state->FormattedValue_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.FormattedValue.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_int(state, o->v.FormattedValue.conversion);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->conversion, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.FormattedValue.format_spec);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->format_spec, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case JoinedStr_kind:\n        tp = (PyTypeObject *)state->JoinedStr_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.JoinedStr.values,\n                             ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->values, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Constant_kind:\n        tp = (PyTypeObject *)state->Constant_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_constant(state, o->v.Constant.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_string(state, o->v.Constant.kind);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->kind, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Attribute_kind:\n        tp = (PyTypeObject *)state->Attribute_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Attribute.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_identifier(state, o->v.Attribute.attr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->attr, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr_context(state, o->v.Attribute.ctx);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->ctx, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Subscript_kind:\n        tp = (PyTypeObject *)state->Subscript_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Subscript.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.Subscript.slice);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->slice, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr_context(state, o->v.Subscript.ctx);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->ctx, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Starred_kind:\n        tp = (PyTypeObject *)state->Starred_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Starred.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr_context(state, o->v.Starred.ctx);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->ctx, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Name_kind:\n        tp = (PyTypeObject *)state->Name_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_identifier(state, o->v.Name.id);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->id, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr_context(state, o->v.Name.ctx);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->ctx, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case List_kind:\n        tp = (PyTypeObject *)state->List_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.List.elts, ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->elts, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr_context(state, o->v.List.ctx);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->ctx, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Tuple_kind:\n        tp = (PyTypeObject *)state->Tuple_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.Tuple.elts, ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->elts, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr_context(state, o->v.Tuple.ctx);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->ctx, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case Slice_kind:\n        tp = (PyTypeObject *)state->Slice_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.Slice.lower);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->lower, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.Slice.upper);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->upper, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.Slice.step);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->step, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    }\n    value = ast2obj_int(state, o->lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject* ast2obj_expr_context(struct ast_state *state, expr_context_ty o)\n{\n    switch(o) {\n        case Load:\n            return Py_NewRef(state->Load_singleton);\n        case Store:\n            return Py_NewRef(state->Store_singleton);\n        case Del:\n            return Py_NewRef(state->Del_singleton);\n    }\n    Py_UNREACHABLE();\n}\nPyObject* ast2obj_boolop(struct ast_state *state, boolop_ty o)\n{\n    switch(o) {\n        case And:\n            return Py_NewRef(state->And_singleton);\n        case Or:\n            return Py_NewRef(state->Or_singleton);\n    }\n    Py_UNREACHABLE();\n}\nPyObject* ast2obj_operator(struct ast_state *state, operator_ty o)\n{\n    switch(o) {\n        case Add:\n            return Py_NewRef(state->Add_singleton);\n        case Sub:\n            return Py_NewRef(state->Sub_singleton);\n        case Mult:\n            return Py_NewRef(state->Mult_singleton);\n        case MatMult:\n            return Py_NewRef(state->MatMult_singleton);\n        case Div:\n            return Py_NewRef(state->Div_singleton);\n        case Mod:\n            return Py_NewRef(state->Mod_singleton);\n        case Pow:\n            return Py_NewRef(state->Pow_singleton);\n        case LShift:\n            return Py_NewRef(state->LShift_singleton);\n        case RShift:\n            return Py_NewRef(state->RShift_singleton);\n        case BitOr:\n            return Py_NewRef(state->BitOr_singleton);\n        case BitXor:\n            return Py_NewRef(state->BitXor_singleton);\n        case BitAnd:\n            return Py_NewRef(state->BitAnd_singleton);\n        case FloorDiv:\n            return Py_NewRef(state->FloorDiv_singleton);\n    }\n    Py_UNREACHABLE();\n}\nPyObject* ast2obj_unaryop(struct ast_state *state, unaryop_ty o)\n{\n    switch(o) {\n        case Invert:\n            return Py_NewRef(state->Invert_singleton);\n        case Not:\n            return Py_NewRef(state->Not_singleton);\n        case UAdd:\n            return Py_NewRef(state->UAdd_singleton);\n        case USub:\n            return Py_NewRef(state->USub_singleton);\n    }\n    Py_UNREACHABLE();\n}\nPyObject* ast2obj_cmpop(struct ast_state *state, cmpop_ty o)\n{\n    switch(o) {\n        case Eq:\n            return Py_NewRef(state->Eq_singleton);\n        case NotEq:\n            return Py_NewRef(state->NotEq_singleton);\n        case Lt:\n            return Py_NewRef(state->Lt_singleton);\n        case LtE:\n            return Py_NewRef(state->LtE_singleton);\n        case Gt:\n            return Py_NewRef(state->Gt_singleton);\n        case GtE:\n            return Py_NewRef(state->GtE_singleton);\n        case Is:\n            return Py_NewRef(state->Is_singleton);\n        case IsNot:\n            return Py_NewRef(state->IsNot_singleton);\n        case In:\n            return Py_NewRef(state->In_singleton);\n        case NotIn:\n            return Py_NewRef(state->NotIn_singleton);\n    }\n    Py_UNREACHABLE();\n}\nPyObject*\nast2obj_comprehension(struct ast_state *state, void* _o)\n{\n    comprehension_ty o = (comprehension_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    tp = (PyTypeObject *)state->comprehension_type;\n    result = PyType_GenericNew(tp, NULL, NULL);\n    if (!result) return NULL;\n    value = ast2obj_expr(state, o->target);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->target, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_expr(state, o->iter);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->iter, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_list(state, (asdl_seq*)o->ifs, ast2obj_expr);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->ifs, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->is_async);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->is_async, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject*\nast2obj_excepthandler(struct ast_state *state, void* _o)\n{\n    excepthandler_ty o = (excepthandler_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    switch (o->kind) {\n    case ExceptHandler_kind:\n        tp = (PyTypeObject *)state->ExceptHandler_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.ExceptHandler.type);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->type, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_identifier(state, o->v.ExceptHandler.name);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->name, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.ExceptHandler.body,\n                             ast2obj_stmt);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->body, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    }\n    value = ast2obj_int(state, o->lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject*\nast2obj_arguments(struct ast_state *state, void* _o)\n{\n    arguments_ty o = (arguments_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    tp = (PyTypeObject *)state->arguments_type;\n    result = PyType_GenericNew(tp, NULL, NULL);\n    if (!result) return NULL;\n    value = ast2obj_list(state, (asdl_seq*)o->posonlyargs, ast2obj_arg);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->posonlyargs, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_list(state, (asdl_seq*)o->args, ast2obj_arg);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->args, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_arg(state, o->vararg);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->vararg, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_list(state, (asdl_seq*)o->kwonlyargs, ast2obj_arg);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->kwonlyargs, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_list(state, (asdl_seq*)o->kw_defaults, ast2obj_expr);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->kw_defaults, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_arg(state, o->kwarg);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->kwarg, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_list(state, (asdl_seq*)o->defaults, ast2obj_expr);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->defaults, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject*\nast2obj_arg(struct ast_state *state, void* _o)\n{\n    arg_ty o = (arg_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    tp = (PyTypeObject *)state->arg_type;\n    result = PyType_GenericNew(tp, NULL, NULL);\n    if (!result) return NULL;\n    value = ast2obj_identifier(state, o->arg);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->arg, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_expr(state, o->annotation);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->annotation, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_string(state, o->type_comment);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->type_comment, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject*\nast2obj_keyword(struct ast_state *state, void* _o)\n{\n    keyword_ty o = (keyword_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    tp = (PyTypeObject *)state->keyword_type;\n    result = PyType_GenericNew(tp, NULL, NULL);\n    if (!result) return NULL;\n    value = ast2obj_identifier(state, o->arg);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->arg, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_expr(state, o->value);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->value, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject*\nast2obj_alias(struct ast_state *state, void* _o)\n{\n    alias_ty o = (alias_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    tp = (PyTypeObject *)state->alias_type;\n    result = PyType_GenericNew(tp, NULL, NULL);\n    if (!result) return NULL;\n    value = ast2obj_identifier(state, o->name);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->name, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_identifier(state, o->asname);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->asname, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject*\nast2obj_withitem(struct ast_state *state, void* _o)\n{\n    withitem_ty o = (withitem_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    tp = (PyTypeObject *)state->withitem_type;\n    result = PyType_GenericNew(tp, NULL, NULL);\n    if (!result) return NULL;\n    value = ast2obj_expr(state, o->context_expr);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->context_expr, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_expr(state, o->optional_vars);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->optional_vars, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject*\nast2obj_match_case(struct ast_state *state, void* _o)\n{\n    match_case_ty o = (match_case_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    tp = (PyTypeObject *)state->match_case_type;\n    result = PyType_GenericNew(tp, NULL, NULL);\n    if (!result) return NULL;\n    value = ast2obj_pattern(state, o->pattern);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->pattern, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_expr(state, o->guard);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->guard, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_list(state, (asdl_seq*)o->body, ast2obj_stmt);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->body, value) == -1)\n        goto failed;\n    Py_DECREF(value);\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject*\nast2obj_pattern(struct ast_state *state, void* _o)\n{\n    pattern_ty o = (pattern_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    switch (o->kind) {\n    case MatchValue_kind:\n        tp = (PyTypeObject *)state->MatchValue_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.MatchValue.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case MatchSingleton_kind:\n        tp = (PyTypeObject *)state->MatchSingleton_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_constant(state, o->v.MatchSingleton.value);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->value, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case MatchSequence_kind:\n        tp = (PyTypeObject *)state->MatchSequence_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.MatchSequence.patterns,\n                             ast2obj_pattern);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->patterns, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case MatchMapping_kind:\n        tp = (PyTypeObject *)state->MatchMapping_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.MatchMapping.keys,\n                             ast2obj_expr);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->keys, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.MatchMapping.patterns,\n                             ast2obj_pattern);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->patterns, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_identifier(state, o->v.MatchMapping.rest);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->rest, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case MatchClass_kind:\n        tp = (PyTypeObject *)state->MatchClass_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_expr(state, o->v.MatchClass.cls);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->cls, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.MatchClass.patterns,\n                             ast2obj_pattern);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->patterns, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.MatchClass.kwd_attrs,\n                             ast2obj_identifier);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->kwd_attrs, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_list(state, (asdl_seq*)o->v.MatchClass.kwd_patterns,\n                             ast2obj_pattern);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->kwd_patterns, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case MatchStar_kind:\n        tp = (PyTypeObject *)state->MatchStar_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_identifier(state, o->v.MatchStar.name);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->name, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case MatchAs_kind:\n        tp = (PyTypeObject *)state->MatchAs_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_pattern(state, o->v.MatchAs.pattern);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->pattern, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_identifier(state, o->v.MatchAs.name);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->name, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case MatchOr_kind:\n        tp = (PyTypeObject *)state->MatchOr_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_list(state, (asdl_seq*)o->v.MatchOr.patterns,\n                             ast2obj_pattern);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->patterns, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    }\n    value = ast2obj_int(state, o->lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject*\nast2obj_type_ignore(struct ast_state *state, void* _o)\n{\n    type_ignore_ty o = (type_ignore_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    switch (o->kind) {\n    case TypeIgnore_kind:\n        tp = (PyTypeObject *)state->TypeIgnore_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_int(state, o->v.TypeIgnore.lineno);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->lineno, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_string(state, o->v.TypeIgnore.tag);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->tag, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    }\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\nPyObject*\nast2obj_type_param(struct ast_state *state, void* _o)\n{\n    type_param_ty o = (type_param_ty)_o;\n    PyObject *result = NULL, *value = NULL;\n    PyTypeObject *tp;\n    if (!o) {\n        Py_RETURN_NONE;\n    }\n    if (++state->recursion_depth > state->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n            \"maximum recursion depth exceeded during ast construction\");\n        return 0;\n    }\n    switch (o->kind) {\n    case TypeVar_kind:\n        tp = (PyTypeObject *)state->TypeVar_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_identifier(state, o->v.TypeVar.name);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->name, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        value = ast2obj_expr(state, o->v.TypeVar.bound);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->bound, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case ParamSpec_kind:\n        tp = (PyTypeObject *)state->ParamSpec_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_identifier(state, o->v.ParamSpec.name);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->name, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    case TypeVarTuple_kind:\n        tp = (PyTypeObject *)state->TypeVarTuple_type;\n        result = PyType_GenericNew(tp, NULL, NULL);\n        if (!result) goto failed;\n        value = ast2obj_identifier(state, o->v.TypeVarTuple.name);\n        if (!value) goto failed;\n        if (PyObject_SetAttr(result, state->name, value) == -1)\n            goto failed;\n        Py_DECREF(value);\n        break;\n    }\n    value = ast2obj_int(state, o->lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_lineno);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_lineno, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    value = ast2obj_int(state, o->end_col_offset);\n    if (!value) goto failed;\n    if (PyObject_SetAttr(result, state->end_col_offset, value) < 0)\n        goto failed;\n    Py_DECREF(value);\n    state->recursion_depth--;\n    return result;\nfailed:\n    Py_XDECREF(value);\n    Py_XDECREF(result);\n    return NULL;\n}\n\n\nint\nobj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena)\n{\n    int isinstance;\n\n    PyObject *tmp = NULL;\n    PyObject *tp;\n\n    if (obj == Py_None) {\n        *out = NULL;\n        return 0;\n    }\n    tp = state->Module_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_stmt_seq* body;\n        asdl_type_ignore_seq* type_ignores;\n\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from Module\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Module field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Module' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Module field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->type_ignores, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"type_ignores\\\" missing from Module\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Module field \\\"type_ignores\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            type_ignores = _Py_asdl_type_ignore_seq_new(len, arena);\n            if (type_ignores == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                type_ignore_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Module' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_type_ignore(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Module field \\\"type_ignores\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(type_ignores, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Module(body, type_ignores, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Interactive_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_stmt_seq* body;\n\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from Interactive\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Interactive field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Interactive' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Interactive field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Interactive(body, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Expression_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty body;\n\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from Expression\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Expression' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &body, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Expression(body, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->FunctionType_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_expr_seq* argtypes;\n        expr_ty returns;\n\n        if (_PyObject_LookupAttr(obj, state->argtypes, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"argtypes\\\" missing from FunctionType\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"FunctionType field \\\"argtypes\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            argtypes = _Py_asdl_expr_seq_new(len, arena);\n            if (argtypes == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'FunctionType' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"FunctionType field \\\"argtypes\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(argtypes, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->returns, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"returns\\\" missing from FunctionType\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'FunctionType' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &returns, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_FunctionType(argtypes, returns, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"expected some sort of mod, but got %R\", obj);\n    failed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena*\n             arena)\n{\n    int isinstance;\n\n    PyObject *tmp = NULL;\n    PyObject *tp;\n    int lineno;\n    int col_offset;\n    int end_lineno;\n    int end_col_offset;\n\n    if (obj == Py_None) {\n        *out = NULL;\n        return 0;\n    }\n    if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"lineno\\\" missing from stmt\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'stmt' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"col_offset\\\" missing from stmt\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'stmt' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_lineno = lineno;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'stmt' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_col_offset = col_offset;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'stmt' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    tp = state->FunctionDef_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        identifier name;\n        arguments_ty args;\n        asdl_stmt_seq* body;\n        asdl_expr_seq* decorator_list;\n        expr_ty returns;\n        string type_comment;\n        asdl_type_param_seq* type_params;\n\n        if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"name\\\" missing from FunctionDef\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'FunctionDef' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &name, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"args\\\" missing from FunctionDef\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'FunctionDef' node\")) {\n                goto failed;\n            }\n            res = obj2ast_arguments(state, tmp, &args, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from FunctionDef\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"FunctionDef field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'FunctionDef' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"FunctionDef field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->decorator_list, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"decorator_list\\\" missing from FunctionDef\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"FunctionDef field \\\"decorator_list\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            decorator_list = _Py_asdl_expr_seq_new(len, arena);\n            if (decorator_list == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'FunctionDef' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"FunctionDef field \\\"decorator_list\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(decorator_list, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->returns, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            returns = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'FunctionDef' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &returns, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            type_comment = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'FunctionDef' node\")) {\n                goto failed;\n            }\n            res = obj2ast_string(state, tmp, &type_comment, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"type_params\\\" missing from FunctionDef\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"FunctionDef field \\\"type_params\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            type_params = _Py_asdl_type_param_seq_new(len, arena);\n            if (type_params == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                type_param_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'FunctionDef' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_type_param(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"FunctionDef field \\\"type_params\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(type_params, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_FunctionDef(name, args, body, decorator_list, returns,\n                                  type_comment, type_params, lineno,\n                                  col_offset, end_lineno, end_col_offset,\n                                  arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->AsyncFunctionDef_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        identifier name;\n        arguments_ty args;\n        asdl_stmt_seq* body;\n        asdl_expr_seq* decorator_list;\n        expr_ty returns;\n        string type_comment;\n        asdl_type_param_seq* type_params;\n\n        if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"name\\\" missing from AsyncFunctionDef\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AsyncFunctionDef' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &name, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"args\\\" missing from AsyncFunctionDef\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AsyncFunctionDef' node\")) {\n                goto failed;\n            }\n            res = obj2ast_arguments(state, tmp, &args, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from AsyncFunctionDef\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"AsyncFunctionDef field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'AsyncFunctionDef' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"AsyncFunctionDef field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->decorator_list, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"decorator_list\\\" missing from AsyncFunctionDef\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"AsyncFunctionDef field \\\"decorator_list\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            decorator_list = _Py_asdl_expr_seq_new(len, arena);\n            if (decorator_list == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'AsyncFunctionDef' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"AsyncFunctionDef field \\\"decorator_list\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(decorator_list, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->returns, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            returns = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AsyncFunctionDef' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &returns, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            type_comment = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AsyncFunctionDef' node\")) {\n                goto failed;\n            }\n            res = obj2ast_string(state, tmp, &type_comment, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"type_params\\\" missing from AsyncFunctionDef\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"AsyncFunctionDef field \\\"type_params\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            type_params = _Py_asdl_type_param_seq_new(len, arena);\n            if (type_params == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                type_param_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'AsyncFunctionDef' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_type_param(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"AsyncFunctionDef field \\\"type_params\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(type_params, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_AsyncFunctionDef(name, args, body, decorator_list,\n                                       returns, type_comment, type_params,\n                                       lineno, col_offset, end_lineno,\n                                       end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->ClassDef_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        identifier name;\n        asdl_expr_seq* bases;\n        asdl_keyword_seq* keywords;\n        asdl_stmt_seq* body;\n        asdl_expr_seq* decorator_list;\n        asdl_type_param_seq* type_params;\n\n        if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"name\\\" missing from ClassDef\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'ClassDef' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &name, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->bases, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"bases\\\" missing from ClassDef\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"ClassDef field \\\"bases\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            bases = _Py_asdl_expr_seq_new(len, arena);\n            if (bases == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'ClassDef' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"ClassDef field \\\"bases\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(bases, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->keywords, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"keywords\\\" missing from ClassDef\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"ClassDef field \\\"keywords\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            keywords = _Py_asdl_keyword_seq_new(len, arena);\n            if (keywords == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                keyword_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'ClassDef' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_keyword(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"ClassDef field \\\"keywords\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(keywords, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from ClassDef\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"ClassDef field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'ClassDef' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"ClassDef field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->decorator_list, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"decorator_list\\\" missing from ClassDef\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"ClassDef field \\\"decorator_list\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            decorator_list = _Py_asdl_expr_seq_new(len, arena);\n            if (decorator_list == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'ClassDef' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"ClassDef field \\\"decorator_list\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(decorator_list, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"type_params\\\" missing from ClassDef\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"ClassDef field \\\"type_params\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            type_params = _Py_asdl_type_param_seq_new(len, arena);\n            if (type_params == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                type_param_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'ClassDef' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_type_param(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"ClassDef field \\\"type_params\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(type_params, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_ClassDef(name, bases, keywords, body, decorator_list,\n                               type_params, lineno, col_offset, end_lineno,\n                               end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Return_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty value;\n\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            value = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Return' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Return(value, lineno, col_offset, end_lineno,\n                             end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Delete_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_expr_seq* targets;\n\n        if (_PyObject_LookupAttr(obj, state->targets, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"targets\\\" missing from Delete\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Delete field \\\"targets\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            targets = _Py_asdl_expr_seq_new(len, arena);\n            if (targets == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Delete' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Delete field \\\"targets\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(targets, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Delete(targets, lineno, col_offset, end_lineno,\n                             end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Assign_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_expr_seq* targets;\n        expr_ty value;\n        string type_comment;\n\n        if (_PyObject_LookupAttr(obj, state->targets, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"targets\\\" missing from Assign\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Assign field \\\"targets\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            targets = _Py_asdl_expr_seq_new(len, arena);\n            if (targets == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Assign' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Assign field \\\"targets\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(targets, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from Assign\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Assign' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            type_comment = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Assign' node\")) {\n                goto failed;\n            }\n            res = obj2ast_string(state, tmp, &type_comment, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Assign(targets, value, type_comment, lineno, col_offset,\n                             end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->TypeAlias_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty name;\n        asdl_type_param_seq* type_params;\n        expr_ty value;\n\n        if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"name\\\" missing from TypeAlias\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'TypeAlias' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &name, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->type_params, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"type_params\\\" missing from TypeAlias\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"TypeAlias field \\\"type_params\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            type_params = _Py_asdl_type_param_seq_new(len, arena);\n            if (type_params == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                type_param_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'TypeAlias' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_type_param(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"TypeAlias field \\\"type_params\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(type_params, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from TypeAlias\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'TypeAlias' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_TypeAlias(name, type_params, value, lineno, col_offset,\n                                end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->AugAssign_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty target;\n        operator_ty op;\n        expr_ty value;\n\n        if (_PyObject_LookupAttr(obj, state->target, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"target\\\" missing from AugAssign\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AugAssign' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &target, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->op, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"op\\\" missing from AugAssign\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AugAssign' node\")) {\n                goto failed;\n            }\n            res = obj2ast_operator(state, tmp, &op, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from AugAssign\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AugAssign' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_AugAssign(target, op, value, lineno, col_offset,\n                                end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->AnnAssign_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty target;\n        expr_ty annotation;\n        expr_ty value;\n        int simple;\n\n        if (_PyObject_LookupAttr(obj, state->target, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"target\\\" missing from AnnAssign\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AnnAssign' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &target, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->annotation, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"annotation\\\" missing from AnnAssign\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AnnAssign' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &annotation, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            value = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AnnAssign' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->simple, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"simple\\\" missing from AnnAssign\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AnnAssign' node\")) {\n                goto failed;\n            }\n            res = obj2ast_int(state, tmp, &simple, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_AnnAssign(target, annotation, value, simple, lineno,\n                                col_offset, end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->For_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty target;\n        expr_ty iter;\n        asdl_stmt_seq* body;\n        asdl_stmt_seq* orelse;\n        string type_comment;\n\n        if (_PyObject_LookupAttr(obj, state->target, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"target\\\" missing from For\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'For' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &target, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->iter, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"iter\\\" missing from For\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'For' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &iter, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from For\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"For field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'For' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"For field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"orelse\\\" missing from For\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"For field \\\"orelse\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            orelse = _Py_asdl_stmt_seq_new(len, arena);\n            if (orelse == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'For' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"For field \\\"orelse\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(orelse, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            type_comment = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'For' node\")) {\n                goto failed;\n            }\n            res = obj2ast_string(state, tmp, &type_comment, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_For(target, iter, body, orelse, type_comment, lineno,\n                          col_offset, end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->AsyncFor_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty target;\n        expr_ty iter;\n        asdl_stmt_seq* body;\n        asdl_stmt_seq* orelse;\n        string type_comment;\n\n        if (_PyObject_LookupAttr(obj, state->target, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"target\\\" missing from AsyncFor\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AsyncFor' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &target, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->iter, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"iter\\\" missing from AsyncFor\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AsyncFor' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &iter, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from AsyncFor\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"AsyncFor field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'AsyncFor' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"AsyncFor field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"orelse\\\" missing from AsyncFor\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"AsyncFor field \\\"orelse\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            orelse = _Py_asdl_stmt_seq_new(len, arena);\n            if (orelse == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'AsyncFor' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"AsyncFor field \\\"orelse\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(orelse, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            type_comment = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AsyncFor' node\")) {\n                goto failed;\n            }\n            res = obj2ast_string(state, tmp, &type_comment, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_AsyncFor(target, iter, body, orelse, type_comment,\n                               lineno, col_offset, end_lineno, end_col_offset,\n                               arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->While_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty test;\n        asdl_stmt_seq* body;\n        asdl_stmt_seq* orelse;\n\n        if (_PyObject_LookupAttr(obj, state->test, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"test\\\" missing from While\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'While' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &test, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from While\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"While field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'While' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"While field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"orelse\\\" missing from While\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"While field \\\"orelse\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            orelse = _Py_asdl_stmt_seq_new(len, arena);\n            if (orelse == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'While' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"While field \\\"orelse\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(orelse, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_While(test, body, orelse, lineno, col_offset, end_lineno,\n                            end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->If_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty test;\n        asdl_stmt_seq* body;\n        asdl_stmt_seq* orelse;\n\n        if (_PyObject_LookupAttr(obj, state->test, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"test\\\" missing from If\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'If' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &test, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from If\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"If field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'If' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"If field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"orelse\\\" missing from If\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"If field \\\"orelse\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            orelse = _Py_asdl_stmt_seq_new(len, arena);\n            if (orelse == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'If' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"If field \\\"orelse\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(orelse, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_If(test, body, orelse, lineno, col_offset, end_lineno,\n                         end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->With_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_withitem_seq* items;\n        asdl_stmt_seq* body;\n        string type_comment;\n\n        if (_PyObject_LookupAttr(obj, state->items, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"items\\\" missing from With\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"With field \\\"items\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            items = _Py_asdl_withitem_seq_new(len, arena);\n            if (items == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                withitem_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'With' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_withitem(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"With field \\\"items\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(items, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from With\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"With field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'With' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"With field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            type_comment = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'With' node\")) {\n                goto failed;\n            }\n            res = obj2ast_string(state, tmp, &type_comment, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_With(items, body, type_comment, lineno, col_offset,\n                           end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->AsyncWith_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_withitem_seq* items;\n        asdl_stmt_seq* body;\n        string type_comment;\n\n        if (_PyObject_LookupAttr(obj, state->items, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"items\\\" missing from AsyncWith\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"AsyncWith field \\\"items\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            items = _Py_asdl_withitem_seq_new(len, arena);\n            if (items == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                withitem_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'AsyncWith' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_withitem(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"AsyncWith field \\\"items\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(items, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from AsyncWith\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"AsyncWith field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'AsyncWith' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"AsyncWith field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            type_comment = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'AsyncWith' node\")) {\n                goto failed;\n            }\n            res = obj2ast_string(state, tmp, &type_comment, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_AsyncWith(items, body, type_comment, lineno, col_offset,\n                                end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Match_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty subject;\n        asdl_match_case_seq* cases;\n\n        if (_PyObject_LookupAttr(obj, state->subject, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"subject\\\" missing from Match\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Match' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &subject, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->cases, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"cases\\\" missing from Match\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Match field \\\"cases\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            cases = _Py_asdl_match_case_seq_new(len, arena);\n            if (cases == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                match_case_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Match' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_match_case(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Match field \\\"cases\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(cases, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Match(subject, cases, lineno, col_offset, end_lineno,\n                            end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Raise_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty exc;\n        expr_ty cause;\n\n        if (_PyObject_LookupAttr(obj, state->exc, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            exc = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Raise' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &exc, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->cause, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            cause = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Raise' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &cause, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Raise(exc, cause, lineno, col_offset, end_lineno,\n                            end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Try_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_stmt_seq* body;\n        asdl_excepthandler_seq* handlers;\n        asdl_stmt_seq* orelse;\n        asdl_stmt_seq* finalbody;\n\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from Try\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Try field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Try' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Try field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->handlers, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"handlers\\\" missing from Try\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Try field \\\"handlers\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            handlers = _Py_asdl_excepthandler_seq_new(len, arena);\n            if (handlers == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                excepthandler_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Try' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_excepthandler(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Try field \\\"handlers\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(handlers, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"orelse\\\" missing from Try\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Try field \\\"orelse\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            orelse = _Py_asdl_stmt_seq_new(len, arena);\n            if (orelse == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Try' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Try field \\\"orelse\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(orelse, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->finalbody, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"finalbody\\\" missing from Try\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Try field \\\"finalbody\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            finalbody = _Py_asdl_stmt_seq_new(len, arena);\n            if (finalbody == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Try' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Try field \\\"finalbody\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(finalbody, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Try(body, handlers, orelse, finalbody, lineno,\n                          col_offset, end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->TryStar_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_stmt_seq* body;\n        asdl_excepthandler_seq* handlers;\n        asdl_stmt_seq* orelse;\n        asdl_stmt_seq* finalbody;\n\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from TryStar\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"TryStar field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'TryStar' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"TryStar field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->handlers, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"handlers\\\" missing from TryStar\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"TryStar field \\\"handlers\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            handlers = _Py_asdl_excepthandler_seq_new(len, arena);\n            if (handlers == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                excepthandler_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'TryStar' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_excepthandler(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"TryStar field \\\"handlers\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(handlers, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"orelse\\\" missing from TryStar\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"TryStar field \\\"orelse\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            orelse = _Py_asdl_stmt_seq_new(len, arena);\n            if (orelse == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'TryStar' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"TryStar field \\\"orelse\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(orelse, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->finalbody, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"finalbody\\\" missing from TryStar\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"TryStar field \\\"finalbody\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            finalbody = _Py_asdl_stmt_seq_new(len, arena);\n            if (finalbody == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'TryStar' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"TryStar field \\\"finalbody\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(finalbody, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_TryStar(body, handlers, orelse, finalbody, lineno,\n                              col_offset, end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Assert_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty test;\n        expr_ty msg;\n\n        if (_PyObject_LookupAttr(obj, state->test, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"test\\\" missing from Assert\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Assert' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &test, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->msg, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            msg = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Assert' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &msg, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Assert(test, msg, lineno, col_offset, end_lineno,\n                             end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Import_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_alias_seq* names;\n\n        if (_PyObject_LookupAttr(obj, state->names, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"names\\\" missing from Import\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Import field \\\"names\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            names = _Py_asdl_alias_seq_new(len, arena);\n            if (names == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                alias_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Import' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_alias(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Import field \\\"names\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(names, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Import(names, lineno, col_offset, end_lineno,\n                             end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->ImportFrom_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        identifier module;\n        asdl_alias_seq* names;\n        int level;\n\n        if (_PyObject_LookupAttr(obj, state->module, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            module = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'ImportFrom' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &module, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->names, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"names\\\" missing from ImportFrom\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"ImportFrom field \\\"names\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            names = _Py_asdl_alias_seq_new(len, arena);\n            if (names == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                alias_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'ImportFrom' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_alias(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"ImportFrom field \\\"names\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(names, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->level, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            level = 0;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'ImportFrom' node\")) {\n                goto failed;\n            }\n            res = obj2ast_int(state, tmp, &level, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_ImportFrom(module, names, level, lineno, col_offset,\n                                 end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Global_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_identifier_seq* names;\n\n        if (_PyObject_LookupAttr(obj, state->names, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"names\\\" missing from Global\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Global field \\\"names\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            names = _Py_asdl_identifier_seq_new(len, arena);\n            if (names == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                identifier val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Global' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_identifier(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Global field \\\"names\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(names, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Global(names, lineno, col_offset, end_lineno,\n                             end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Nonlocal_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_identifier_seq* names;\n\n        if (_PyObject_LookupAttr(obj, state->names, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"names\\\" missing from Nonlocal\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Nonlocal field \\\"names\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            names = _Py_asdl_identifier_seq_new(len, arena);\n            if (names == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                identifier val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Nonlocal' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_identifier(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Nonlocal field \\\"names\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(names, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Nonlocal(names, lineno, col_offset, end_lineno,\n                               end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Expr_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty value;\n\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from Expr\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Expr' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Expr(value, lineno, col_offset, end_lineno,\n                           end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Pass_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n\n        *out = _PyAST_Pass(lineno, col_offset, end_lineno, end_col_offset,\n                           arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Break_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n\n        *out = _PyAST_Break(lineno, col_offset, end_lineno, end_col_offset,\n                            arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Continue_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n\n        *out = _PyAST_Continue(lineno, col_offset, end_lineno, end_col_offset,\n                               arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"expected some sort of stmt, but got %R\", obj);\n    failed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena*\n             arena)\n{\n    int isinstance;\n\n    PyObject *tmp = NULL;\n    PyObject *tp;\n    int lineno;\n    int col_offset;\n    int end_lineno;\n    int end_col_offset;\n\n    if (obj == Py_None) {\n        *out = NULL;\n        return 0;\n    }\n    if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"lineno\\\" missing from expr\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'expr' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"col_offset\\\" missing from expr\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'expr' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_lineno = lineno;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'expr' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_col_offset = col_offset;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'expr' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    tp = state->BoolOp_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        boolop_ty op;\n        asdl_expr_seq* values;\n\n        if (_PyObject_LookupAttr(obj, state->op, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"op\\\" missing from BoolOp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'BoolOp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_boolop(state, tmp, &op, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->values, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"values\\\" missing from BoolOp\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"BoolOp field \\\"values\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            values = _Py_asdl_expr_seq_new(len, arena);\n            if (values == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'BoolOp' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"BoolOp field \\\"values\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(values, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_BoolOp(op, values, lineno, col_offset, end_lineno,\n                             end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->NamedExpr_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty target;\n        expr_ty value;\n\n        if (_PyObject_LookupAttr(obj, state->target, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"target\\\" missing from NamedExpr\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'NamedExpr' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &target, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from NamedExpr\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'NamedExpr' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_NamedExpr(target, value, lineno, col_offset, end_lineno,\n                                end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->BinOp_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty left;\n        operator_ty op;\n        expr_ty right;\n\n        if (_PyObject_LookupAttr(obj, state->left, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"left\\\" missing from BinOp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'BinOp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &left, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->op, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"op\\\" missing from BinOp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'BinOp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_operator(state, tmp, &op, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->right, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"right\\\" missing from BinOp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'BinOp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &right, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_BinOp(left, op, right, lineno, col_offset, end_lineno,\n                            end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->UnaryOp_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        unaryop_ty op;\n        expr_ty operand;\n\n        if (_PyObject_LookupAttr(obj, state->op, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"op\\\" missing from UnaryOp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'UnaryOp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_unaryop(state, tmp, &op, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->operand, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"operand\\\" missing from UnaryOp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'UnaryOp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &operand, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_UnaryOp(op, operand, lineno, col_offset, end_lineno,\n                              end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Lambda_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        arguments_ty args;\n        expr_ty body;\n\n        if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"args\\\" missing from Lambda\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Lambda' node\")) {\n                goto failed;\n            }\n            res = obj2ast_arguments(state, tmp, &args, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from Lambda\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Lambda' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &body, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Lambda(args, body, lineno, col_offset, end_lineno,\n                             end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->IfExp_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty test;\n        expr_ty body;\n        expr_ty orelse;\n\n        if (_PyObject_LookupAttr(obj, state->test, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"test\\\" missing from IfExp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'IfExp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &test, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from IfExp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'IfExp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &body, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->orelse, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"orelse\\\" missing from IfExp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'IfExp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &orelse, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_IfExp(test, body, orelse, lineno, col_offset, end_lineno,\n                            end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Dict_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_expr_seq* keys;\n        asdl_expr_seq* values;\n\n        if (_PyObject_LookupAttr(obj, state->keys, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"keys\\\" missing from Dict\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Dict field \\\"keys\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            keys = _Py_asdl_expr_seq_new(len, arena);\n            if (keys == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Dict' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Dict field \\\"keys\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(keys, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->values, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"values\\\" missing from Dict\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Dict field \\\"values\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            values = _Py_asdl_expr_seq_new(len, arena);\n            if (values == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Dict' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Dict field \\\"values\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(values, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Dict(keys, values, lineno, col_offset, end_lineno,\n                           end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Set_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_expr_seq* elts;\n\n        if (_PyObject_LookupAttr(obj, state->elts, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"elts\\\" missing from Set\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Set field \\\"elts\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            elts = _Py_asdl_expr_seq_new(len, arena);\n            if (elts == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Set' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Set field \\\"elts\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(elts, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Set(elts, lineno, col_offset, end_lineno, end_col_offset,\n                          arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->ListComp_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty elt;\n        asdl_comprehension_seq* generators;\n\n        if (_PyObject_LookupAttr(obj, state->elt, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"elt\\\" missing from ListComp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'ListComp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &elt, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->generators, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"generators\\\" missing from ListComp\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"ListComp field \\\"generators\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            generators = _Py_asdl_comprehension_seq_new(len, arena);\n            if (generators == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                comprehension_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'ListComp' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_comprehension(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"ListComp field \\\"generators\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(generators, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_ListComp(elt, generators, lineno, col_offset, end_lineno,\n                               end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->SetComp_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty elt;\n        asdl_comprehension_seq* generators;\n\n        if (_PyObject_LookupAttr(obj, state->elt, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"elt\\\" missing from SetComp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'SetComp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &elt, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->generators, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"generators\\\" missing from SetComp\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"SetComp field \\\"generators\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            generators = _Py_asdl_comprehension_seq_new(len, arena);\n            if (generators == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                comprehension_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'SetComp' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_comprehension(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"SetComp field \\\"generators\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(generators, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_SetComp(elt, generators, lineno, col_offset, end_lineno,\n                              end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->DictComp_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty key;\n        expr_ty value;\n        asdl_comprehension_seq* generators;\n\n        if (_PyObject_LookupAttr(obj, state->key, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"key\\\" missing from DictComp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'DictComp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &key, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from DictComp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'DictComp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->generators, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"generators\\\" missing from DictComp\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"DictComp field \\\"generators\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            generators = _Py_asdl_comprehension_seq_new(len, arena);\n            if (generators == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                comprehension_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'DictComp' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_comprehension(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"DictComp field \\\"generators\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(generators, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_DictComp(key, value, generators, lineno, col_offset,\n                               end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->GeneratorExp_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty elt;\n        asdl_comprehension_seq* generators;\n\n        if (_PyObject_LookupAttr(obj, state->elt, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"elt\\\" missing from GeneratorExp\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'GeneratorExp' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &elt, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->generators, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"generators\\\" missing from GeneratorExp\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"GeneratorExp field \\\"generators\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            generators = _Py_asdl_comprehension_seq_new(len, arena);\n            if (generators == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                comprehension_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'GeneratorExp' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_comprehension(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"GeneratorExp field \\\"generators\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(generators, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_GeneratorExp(elt, generators, lineno, col_offset,\n                                   end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Await_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty value;\n\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from Await\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Await' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Await(value, lineno, col_offset, end_lineno,\n                            end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Yield_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty value;\n\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            value = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Yield' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Yield(value, lineno, col_offset, end_lineno,\n                            end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->YieldFrom_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty value;\n\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from YieldFrom\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'YieldFrom' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_YieldFrom(value, lineno, col_offset, end_lineno,\n                                end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Compare_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty left;\n        asdl_int_seq* ops;\n        asdl_expr_seq* comparators;\n\n        if (_PyObject_LookupAttr(obj, state->left, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"left\\\" missing from Compare\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Compare' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &left, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->ops, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"ops\\\" missing from Compare\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Compare field \\\"ops\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            ops = _Py_asdl_int_seq_new(len, arena);\n            if (ops == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                cmpop_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Compare' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_cmpop(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Compare field \\\"ops\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(ops, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->comparators, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"comparators\\\" missing from Compare\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Compare field \\\"comparators\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            comparators = _Py_asdl_expr_seq_new(len, arena);\n            if (comparators == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Compare' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Compare field \\\"comparators\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(comparators, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Compare(left, ops, comparators, lineno, col_offset,\n                              end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Call_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty func;\n        asdl_expr_seq* args;\n        asdl_keyword_seq* keywords;\n\n        if (_PyObject_LookupAttr(obj, state->func, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"func\\\" missing from Call\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Call' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &func, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"args\\\" missing from Call\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Call field \\\"args\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            args = _Py_asdl_expr_seq_new(len, arena);\n            if (args == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Call' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Call field \\\"args\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(args, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->keywords, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"keywords\\\" missing from Call\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Call field \\\"keywords\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            keywords = _Py_asdl_keyword_seq_new(len, arena);\n            if (keywords == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                keyword_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Call' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_keyword(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Call field \\\"keywords\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(keywords, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Call(func, args, keywords, lineno, col_offset,\n                           end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->FormattedValue_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty value;\n        int conversion;\n        expr_ty format_spec;\n\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from FormattedValue\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'FormattedValue' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->conversion, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"conversion\\\" missing from FormattedValue\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'FormattedValue' node\")) {\n                goto failed;\n            }\n            res = obj2ast_int(state, tmp, &conversion, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->format_spec, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            format_spec = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'FormattedValue' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &format_spec, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_FormattedValue(value, conversion, format_spec, lineno,\n                                     col_offset, end_lineno, end_col_offset,\n                                     arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->JoinedStr_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_expr_seq* values;\n\n        if (_PyObject_LookupAttr(obj, state->values, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"values\\\" missing from JoinedStr\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"JoinedStr field \\\"values\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            values = _Py_asdl_expr_seq_new(len, arena);\n            if (values == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'JoinedStr' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"JoinedStr field \\\"values\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(values, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_JoinedStr(values, lineno, col_offset, end_lineno,\n                                end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Constant_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        constant value;\n        string kind;\n\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from Constant\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Constant' node\")) {\n                goto failed;\n            }\n            res = obj2ast_constant(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->kind, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            kind = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Constant' node\")) {\n                goto failed;\n            }\n            res = obj2ast_string(state, tmp, &kind, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Constant(value, kind, lineno, col_offset, end_lineno,\n                               end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Attribute_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty value;\n        identifier attr;\n        expr_context_ty ctx;\n\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from Attribute\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Attribute' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->attr, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"attr\\\" missing from Attribute\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Attribute' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &attr, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->ctx, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"ctx\\\" missing from Attribute\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Attribute' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr_context(state, tmp, &ctx, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Attribute(value, attr, ctx, lineno, col_offset,\n                                end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Subscript_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty value;\n        expr_ty slice;\n        expr_context_ty ctx;\n\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from Subscript\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Subscript' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->slice, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"slice\\\" missing from Subscript\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Subscript' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &slice, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->ctx, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"ctx\\\" missing from Subscript\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Subscript' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr_context(state, tmp, &ctx, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Subscript(value, slice, ctx, lineno, col_offset,\n                                end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Starred_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty value;\n        expr_context_ty ctx;\n\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from Starred\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Starred' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->ctx, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"ctx\\\" missing from Starred\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Starred' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr_context(state, tmp, &ctx, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Starred(value, ctx, lineno, col_offset, end_lineno,\n                              end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Name_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        identifier id;\n        expr_context_ty ctx;\n\n        if (_PyObject_LookupAttr(obj, state->id, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"id\\\" missing from Name\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Name' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &id, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->ctx, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"ctx\\\" missing from Name\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Name' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr_context(state, tmp, &ctx, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Name(id, ctx, lineno, col_offset, end_lineno,\n                           end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->List_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_expr_seq* elts;\n        expr_context_ty ctx;\n\n        if (_PyObject_LookupAttr(obj, state->elts, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"elts\\\" missing from List\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"List field \\\"elts\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            elts = _Py_asdl_expr_seq_new(len, arena);\n            if (elts == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'List' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"List field \\\"elts\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(elts, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->ctx, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"ctx\\\" missing from List\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'List' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr_context(state, tmp, &ctx, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_List(elts, ctx, lineno, col_offset, end_lineno,\n                           end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Tuple_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_expr_seq* elts;\n        expr_context_ty ctx;\n\n        if (_PyObject_LookupAttr(obj, state->elts, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"elts\\\" missing from Tuple\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"Tuple field \\\"elts\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            elts = _Py_asdl_expr_seq_new(len, arena);\n            if (elts == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'Tuple' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"Tuple field \\\"elts\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(elts, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->ctx, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"ctx\\\" missing from Tuple\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Tuple' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr_context(state, tmp, &ctx, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Tuple(elts, ctx, lineno, col_offset, end_lineno,\n                            end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->Slice_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty lower;\n        expr_ty upper;\n        expr_ty step;\n\n        if (_PyObject_LookupAttr(obj, state->lower, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            lower = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Slice' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &lower, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->upper, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            upper = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Slice' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &upper, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->step, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            step = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'Slice' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &step, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_Slice(lower, upper, step, lineno, col_offset, end_lineno,\n                            end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"expected some sort of expr, but got %R\", obj);\n    failed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_expr_context(struct ast_state *state, PyObject* obj, expr_context_ty*\n                     out, PyArena* arena)\n{\n    int isinstance;\n\n    isinstance = PyObject_IsInstance(obj, state->Load_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Load;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->Store_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Store;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->Del_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Del;\n        return 0;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"expected some sort of expr_context, but got %R\", obj);\n    return 1;\n}\n\nint\nobj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty* out, PyArena*\n               arena)\n{\n    int isinstance;\n\n    isinstance = PyObject_IsInstance(obj, state->And_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = And;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->Or_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Or;\n        return 0;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"expected some sort of boolop, but got %R\", obj);\n    return 1;\n}\n\nint\nobj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out,\n                 PyArena* arena)\n{\n    int isinstance;\n\n    isinstance = PyObject_IsInstance(obj, state->Add_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Add;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->Sub_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Sub;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->Mult_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Mult;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->MatMult_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = MatMult;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->Div_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Div;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->Mod_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Mod;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->Pow_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Pow;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->LShift_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = LShift;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->RShift_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = RShift;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->BitOr_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = BitOr;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->BitXor_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = BitXor;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->BitAnd_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = BitAnd;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->FloorDiv_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = FloorDiv;\n        return 0;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"expected some sort of operator, but got %R\", obj);\n    return 1;\n}\n\nint\nobj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* out,\n                PyArena* arena)\n{\n    int isinstance;\n\n    isinstance = PyObject_IsInstance(obj, state->Invert_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Invert;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->Not_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Not;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->UAdd_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = UAdd;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->USub_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = USub;\n        return 0;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"expected some sort of unaryop, but got %R\", obj);\n    return 1;\n}\n\nint\nobj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena*\n              arena)\n{\n    int isinstance;\n\n    isinstance = PyObject_IsInstance(obj, state->Eq_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Eq;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->NotEq_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = NotEq;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->Lt_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Lt;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->LtE_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = LtE;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->Gt_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Gt;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->GtE_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = GtE;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->Is_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = Is;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->IsNot_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = IsNot;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->In_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = In;\n        return 0;\n    }\n    isinstance = PyObject_IsInstance(obj, state->NotIn_type);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        *out = NotIn;\n        return 0;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"expected some sort of cmpop, but got %R\", obj);\n    return 1;\n}\n\nint\nobj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty*\n                      out, PyArena* arena)\n{\n    PyObject* tmp = NULL;\n    expr_ty target;\n    expr_ty iter;\n    asdl_expr_seq* ifs;\n    int is_async;\n\n    if (_PyObject_LookupAttr(obj, state->target, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"target\\\" missing from comprehension\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'comprehension' node\")) {\n            goto failed;\n        }\n        res = obj2ast_expr(state, tmp, &target, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->iter, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"iter\\\" missing from comprehension\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'comprehension' node\")) {\n            goto failed;\n        }\n        res = obj2ast_expr(state, tmp, &iter, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->ifs, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"ifs\\\" missing from comprehension\");\n        return 1;\n    }\n    else {\n        int res;\n        Py_ssize_t len;\n        Py_ssize_t i;\n        if (!PyList_Check(tmp)) {\n            PyErr_Format(PyExc_TypeError, \"comprehension field \\\"ifs\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n            goto failed;\n        }\n        len = PyList_GET_SIZE(tmp);\n        ifs = _Py_asdl_expr_seq_new(len, arena);\n        if (ifs == NULL) goto failed;\n        for (i = 0; i < len; i++) {\n            expr_ty val;\n            PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n            if (_Py_EnterRecursiveCall(\" while traversing 'comprehension' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp2, &val, arena);\n            _Py_LeaveRecursiveCall();\n            Py_DECREF(tmp2);\n            if (res != 0) goto failed;\n            if (len != PyList_GET_SIZE(tmp)) {\n                PyErr_SetString(PyExc_RuntimeError, \"comprehension field \\\"ifs\\\" changed size during iteration\");\n                goto failed;\n            }\n            asdl_seq_SET(ifs, i, val);\n        }\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->is_async, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"is_async\\\" missing from comprehension\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'comprehension' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &is_async, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    *out = _PyAST_comprehension(target, iter, ifs, is_async, arena);\n    return 0;\nfailed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty*\n                      out, PyArena* arena)\n{\n    int isinstance;\n\n    PyObject *tmp = NULL;\n    PyObject *tp;\n    int lineno;\n    int col_offset;\n    int end_lineno;\n    int end_col_offset;\n\n    if (obj == Py_None) {\n        *out = NULL;\n        return 0;\n    }\n    if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"lineno\\\" missing from excepthandler\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'excepthandler' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"col_offset\\\" missing from excepthandler\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'excepthandler' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_lineno = lineno;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'excepthandler' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_col_offset = col_offset;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'excepthandler' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    tp = state->ExceptHandler_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty type;\n        identifier name;\n        asdl_stmt_seq* body;\n\n        if (_PyObject_LookupAttr(obj, state->type, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            type = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'ExceptHandler' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &type, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            name = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'ExceptHandler' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &name, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from ExceptHandler\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"ExceptHandler field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            body = _Py_asdl_stmt_seq_new(len, arena);\n            if (body == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                stmt_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'ExceptHandler' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_stmt(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"ExceptHandler field \\\"body\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(body, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_ExceptHandler(type, name, body, lineno, col_offset,\n                                    end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"expected some sort of excepthandler, but got %R\", obj);\n    failed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out,\n                  PyArena* arena)\n{\n    PyObject* tmp = NULL;\n    asdl_arg_seq* posonlyargs;\n    asdl_arg_seq* args;\n    arg_ty vararg;\n    asdl_arg_seq* kwonlyargs;\n    asdl_expr_seq* kw_defaults;\n    arg_ty kwarg;\n    asdl_expr_seq* defaults;\n\n    if (_PyObject_LookupAttr(obj, state->posonlyargs, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"posonlyargs\\\" missing from arguments\");\n        return 1;\n    }\n    else {\n        int res;\n        Py_ssize_t len;\n        Py_ssize_t i;\n        if (!PyList_Check(tmp)) {\n            PyErr_Format(PyExc_TypeError, \"arguments field \\\"posonlyargs\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n            goto failed;\n        }\n        len = PyList_GET_SIZE(tmp);\n        posonlyargs = _Py_asdl_arg_seq_new(len, arena);\n        if (posonlyargs == NULL) goto failed;\n        for (i = 0; i < len; i++) {\n            arg_ty val;\n            PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n            if (_Py_EnterRecursiveCall(\" while traversing 'arguments' node\")) {\n                goto failed;\n            }\n            res = obj2ast_arg(state, tmp2, &val, arena);\n            _Py_LeaveRecursiveCall();\n            Py_DECREF(tmp2);\n            if (res != 0) goto failed;\n            if (len != PyList_GET_SIZE(tmp)) {\n                PyErr_SetString(PyExc_RuntimeError, \"arguments field \\\"posonlyargs\\\" changed size during iteration\");\n                goto failed;\n            }\n            asdl_seq_SET(posonlyargs, i, val);\n        }\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->args, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"args\\\" missing from arguments\");\n        return 1;\n    }\n    else {\n        int res;\n        Py_ssize_t len;\n        Py_ssize_t i;\n        if (!PyList_Check(tmp)) {\n            PyErr_Format(PyExc_TypeError, \"arguments field \\\"args\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n            goto failed;\n        }\n        len = PyList_GET_SIZE(tmp);\n        args = _Py_asdl_arg_seq_new(len, arena);\n        if (args == NULL) goto failed;\n        for (i = 0; i < len; i++) {\n            arg_ty val;\n            PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n            if (_Py_EnterRecursiveCall(\" while traversing 'arguments' node\")) {\n                goto failed;\n            }\n            res = obj2ast_arg(state, tmp2, &val, arena);\n            _Py_LeaveRecursiveCall();\n            Py_DECREF(tmp2);\n            if (res != 0) goto failed;\n            if (len != PyList_GET_SIZE(tmp)) {\n                PyErr_SetString(PyExc_RuntimeError, \"arguments field \\\"args\\\" changed size during iteration\");\n                goto failed;\n            }\n            asdl_seq_SET(args, i, val);\n        }\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->vararg, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        vararg = NULL;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'arguments' node\")) {\n            goto failed;\n        }\n        res = obj2ast_arg(state, tmp, &vararg, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->kwonlyargs, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"kwonlyargs\\\" missing from arguments\");\n        return 1;\n    }\n    else {\n        int res;\n        Py_ssize_t len;\n        Py_ssize_t i;\n        if (!PyList_Check(tmp)) {\n            PyErr_Format(PyExc_TypeError, \"arguments field \\\"kwonlyargs\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n            goto failed;\n        }\n        len = PyList_GET_SIZE(tmp);\n        kwonlyargs = _Py_asdl_arg_seq_new(len, arena);\n        if (kwonlyargs == NULL) goto failed;\n        for (i = 0; i < len; i++) {\n            arg_ty val;\n            PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n            if (_Py_EnterRecursiveCall(\" while traversing 'arguments' node\")) {\n                goto failed;\n            }\n            res = obj2ast_arg(state, tmp2, &val, arena);\n            _Py_LeaveRecursiveCall();\n            Py_DECREF(tmp2);\n            if (res != 0) goto failed;\n            if (len != PyList_GET_SIZE(tmp)) {\n                PyErr_SetString(PyExc_RuntimeError, \"arguments field \\\"kwonlyargs\\\" changed size during iteration\");\n                goto failed;\n            }\n            asdl_seq_SET(kwonlyargs, i, val);\n        }\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->kw_defaults, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"kw_defaults\\\" missing from arguments\");\n        return 1;\n    }\n    else {\n        int res;\n        Py_ssize_t len;\n        Py_ssize_t i;\n        if (!PyList_Check(tmp)) {\n            PyErr_Format(PyExc_TypeError, \"arguments field \\\"kw_defaults\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n            goto failed;\n        }\n        len = PyList_GET_SIZE(tmp);\n        kw_defaults = _Py_asdl_expr_seq_new(len, arena);\n        if (kw_defaults == NULL) goto failed;\n        for (i = 0; i < len; i++) {\n            expr_ty val;\n            PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n            if (_Py_EnterRecursiveCall(\" while traversing 'arguments' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp2, &val, arena);\n            _Py_LeaveRecursiveCall();\n            Py_DECREF(tmp2);\n            if (res != 0) goto failed;\n            if (len != PyList_GET_SIZE(tmp)) {\n                PyErr_SetString(PyExc_RuntimeError, \"arguments field \\\"kw_defaults\\\" changed size during iteration\");\n                goto failed;\n            }\n            asdl_seq_SET(kw_defaults, i, val);\n        }\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->kwarg, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        kwarg = NULL;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'arguments' node\")) {\n            goto failed;\n        }\n        res = obj2ast_arg(state, tmp, &kwarg, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->defaults, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"defaults\\\" missing from arguments\");\n        return 1;\n    }\n    else {\n        int res;\n        Py_ssize_t len;\n        Py_ssize_t i;\n        if (!PyList_Check(tmp)) {\n            PyErr_Format(PyExc_TypeError, \"arguments field \\\"defaults\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n            goto failed;\n        }\n        len = PyList_GET_SIZE(tmp);\n        defaults = _Py_asdl_expr_seq_new(len, arena);\n        if (defaults == NULL) goto failed;\n        for (i = 0; i < len; i++) {\n            expr_ty val;\n            PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n            if (_Py_EnterRecursiveCall(\" while traversing 'arguments' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp2, &val, arena);\n            _Py_LeaveRecursiveCall();\n            Py_DECREF(tmp2);\n            if (res != 0) goto failed;\n            if (len != PyList_GET_SIZE(tmp)) {\n                PyErr_SetString(PyExc_RuntimeError, \"arguments field \\\"defaults\\\" changed size during iteration\");\n                goto failed;\n            }\n            asdl_seq_SET(defaults, i, val);\n        }\n        Py_CLEAR(tmp);\n    }\n    *out = _PyAST_arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults,\n                            kwarg, defaults, arena);\n    return 0;\nfailed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena)\n{\n    PyObject* tmp = NULL;\n    identifier arg;\n    expr_ty annotation;\n    string type_comment;\n    int lineno;\n    int col_offset;\n    int end_lineno;\n    int end_col_offset;\n\n    if (_PyObject_LookupAttr(obj, state->arg, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"arg\\\" missing from arg\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'arg' node\")) {\n            goto failed;\n        }\n        res = obj2ast_identifier(state, tmp, &arg, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->annotation, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        annotation = NULL;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'arg' node\")) {\n            goto failed;\n        }\n        res = obj2ast_expr(state, tmp, &annotation, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->type_comment, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        type_comment = NULL;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'arg' node\")) {\n            goto failed;\n        }\n        res = obj2ast_string(state, tmp, &type_comment, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"lineno\\\" missing from arg\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'arg' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"col_offset\\\" missing from arg\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'arg' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_lineno = lineno;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'arg' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_col_offset = col_offset;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'arg' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    *out = _PyAST_arg(arg, annotation, type_comment, lineno, col_offset,\n                      end_lineno, end_col_offset, arena);\n    return 0;\nfailed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out,\n                PyArena* arena)\n{\n    PyObject* tmp = NULL;\n    identifier arg;\n    expr_ty value;\n    int lineno;\n    int col_offset;\n    int end_lineno;\n    int end_col_offset;\n\n    if (_PyObject_LookupAttr(obj, state->arg, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        arg = NULL;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'keyword' node\")) {\n            goto failed;\n        }\n        res = obj2ast_identifier(state, tmp, &arg, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from keyword\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'keyword' node\")) {\n            goto failed;\n        }\n        res = obj2ast_expr(state, tmp, &value, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"lineno\\\" missing from keyword\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'keyword' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"col_offset\\\" missing from keyword\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'keyword' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_lineno = lineno;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'keyword' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_col_offset = col_offset;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'keyword' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    *out = _PyAST_keyword(arg, value, lineno, col_offset, end_lineno,\n                          end_col_offset, arena);\n    return 0;\nfailed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena*\n              arena)\n{\n    PyObject* tmp = NULL;\n    identifier name;\n    identifier asname;\n    int lineno;\n    int col_offset;\n    int end_lineno;\n    int end_col_offset;\n\n    if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"name\\\" missing from alias\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'alias' node\")) {\n            goto failed;\n        }\n        res = obj2ast_identifier(state, tmp, &name, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->asname, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        asname = NULL;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'alias' node\")) {\n            goto failed;\n        }\n        res = obj2ast_identifier(state, tmp, &asname, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"lineno\\\" missing from alias\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'alias' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"col_offset\\\" missing from alias\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'alias' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_lineno = lineno;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'alias' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_col_offset = col_offset;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'alias' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    *out = _PyAST_alias(name, asname, lineno, col_offset, end_lineno,\n                        end_col_offset, arena);\n    return 0;\nfailed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out,\n                 PyArena* arena)\n{\n    PyObject* tmp = NULL;\n    expr_ty context_expr;\n    expr_ty optional_vars;\n\n    if (_PyObject_LookupAttr(obj, state->context_expr, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"context_expr\\\" missing from withitem\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'withitem' node\")) {\n            goto failed;\n        }\n        res = obj2ast_expr(state, tmp, &context_expr, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->optional_vars, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        optional_vars = NULL;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'withitem' node\")) {\n            goto failed;\n        }\n        res = obj2ast_expr(state, tmp, &optional_vars, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    *out = _PyAST_withitem(context_expr, optional_vars, arena);\n    return 0;\nfailed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out,\n                   PyArena* arena)\n{\n    PyObject* tmp = NULL;\n    pattern_ty pattern;\n    expr_ty guard;\n    asdl_stmt_seq* body;\n\n    if (_PyObject_LookupAttr(obj, state->pattern, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"pattern\\\" missing from match_case\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'match_case' node\")) {\n            goto failed;\n        }\n        res = obj2ast_pattern(state, tmp, &pattern, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->guard, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        guard = NULL;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'match_case' node\")) {\n            goto failed;\n        }\n        res = obj2ast_expr(state, tmp, &guard, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"body\\\" missing from match_case\");\n        return 1;\n    }\n    else {\n        int res;\n        Py_ssize_t len;\n        Py_ssize_t i;\n        if (!PyList_Check(tmp)) {\n            PyErr_Format(PyExc_TypeError, \"match_case field \\\"body\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n            goto failed;\n        }\n        len = PyList_GET_SIZE(tmp);\n        body = _Py_asdl_stmt_seq_new(len, arena);\n        if (body == NULL) goto failed;\n        for (i = 0; i < len; i++) {\n            stmt_ty val;\n            PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n            if (_Py_EnterRecursiveCall(\" while traversing 'match_case' node\")) {\n                goto failed;\n            }\n            res = obj2ast_stmt(state, tmp2, &val, arena);\n            _Py_LeaveRecursiveCall();\n            Py_DECREF(tmp2);\n            if (res != 0) goto failed;\n            if (len != PyList_GET_SIZE(tmp)) {\n                PyErr_SetString(PyExc_RuntimeError, \"match_case field \\\"body\\\" changed size during iteration\");\n                goto failed;\n            }\n            asdl_seq_SET(body, i, val);\n        }\n        Py_CLEAR(tmp);\n    }\n    *out = _PyAST_match_case(pattern, guard, body, arena);\n    return 0;\nfailed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out,\n                PyArena* arena)\n{\n    int isinstance;\n\n    PyObject *tmp = NULL;\n    PyObject *tp;\n    int lineno;\n    int col_offset;\n    int end_lineno;\n    int end_col_offset;\n\n    if (obj == Py_None) {\n        *out = NULL;\n        return 0;\n    }\n    if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"lineno\\\" missing from pattern\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'pattern' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"col_offset\\\" missing from pattern\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'pattern' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"end_lineno\\\" missing from pattern\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'pattern' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"end_col_offset\\\" missing from pattern\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'pattern' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    tp = state->MatchValue_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty value;\n\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from MatchValue\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'MatchValue' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_MatchValue(value, lineno, col_offset, end_lineno,\n                                 end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->MatchSingleton_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        constant value;\n\n        if (_PyObject_LookupAttr(obj, state->value, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"value\\\" missing from MatchSingleton\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'MatchSingleton' node\")) {\n                goto failed;\n            }\n            res = obj2ast_constant(state, tmp, &value, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_MatchSingleton(value, lineno, col_offset, end_lineno,\n                                     end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->MatchSequence_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_pattern_seq* patterns;\n\n        if (_PyObject_LookupAttr(obj, state->patterns, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"patterns\\\" missing from MatchSequence\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"MatchSequence field \\\"patterns\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            patterns = _Py_asdl_pattern_seq_new(len, arena);\n            if (patterns == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                pattern_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'MatchSequence' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_pattern(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"MatchSequence field \\\"patterns\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(patterns, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_MatchSequence(patterns, lineno, col_offset, end_lineno,\n                                    end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->MatchMapping_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_expr_seq* keys;\n        asdl_pattern_seq* patterns;\n        identifier rest;\n\n        if (_PyObject_LookupAttr(obj, state->keys, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"keys\\\" missing from MatchMapping\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"MatchMapping field \\\"keys\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            keys = _Py_asdl_expr_seq_new(len, arena);\n            if (keys == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                expr_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'MatchMapping' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_expr(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"MatchMapping field \\\"keys\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(keys, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->patterns, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"patterns\\\" missing from MatchMapping\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"MatchMapping field \\\"patterns\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            patterns = _Py_asdl_pattern_seq_new(len, arena);\n            if (patterns == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                pattern_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'MatchMapping' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_pattern(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"MatchMapping field \\\"patterns\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(patterns, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->rest, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            rest = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'MatchMapping' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &rest, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_MatchMapping(keys, patterns, rest, lineno, col_offset,\n                                   end_lineno, end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->MatchClass_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        expr_ty cls;\n        asdl_pattern_seq* patterns;\n        asdl_identifier_seq* kwd_attrs;\n        asdl_pattern_seq* kwd_patterns;\n\n        if (_PyObject_LookupAttr(obj, state->cls, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"cls\\\" missing from MatchClass\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'MatchClass' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &cls, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->patterns, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"patterns\\\" missing from MatchClass\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"MatchClass field \\\"patterns\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            patterns = _Py_asdl_pattern_seq_new(len, arena);\n            if (patterns == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                pattern_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'MatchClass' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_pattern(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"MatchClass field \\\"patterns\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(patterns, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->kwd_attrs, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"kwd_attrs\\\" missing from MatchClass\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"MatchClass field \\\"kwd_attrs\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            kwd_attrs = _Py_asdl_identifier_seq_new(len, arena);\n            if (kwd_attrs == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                identifier val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'MatchClass' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_identifier(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"MatchClass field \\\"kwd_attrs\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(kwd_attrs, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->kwd_patterns, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"kwd_patterns\\\" missing from MatchClass\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"MatchClass field \\\"kwd_patterns\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            kwd_patterns = _Py_asdl_pattern_seq_new(len, arena);\n            if (kwd_patterns == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                pattern_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'MatchClass' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_pattern(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"MatchClass field \\\"kwd_patterns\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(kwd_patterns, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_MatchClass(cls, patterns, kwd_attrs, kwd_patterns,\n                                 lineno, col_offset, end_lineno,\n                                 end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->MatchStar_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        identifier name;\n\n        if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            name = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'MatchStar' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &name, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_MatchStar(name, lineno, col_offset, end_lineno,\n                                end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->MatchAs_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        pattern_ty pattern;\n        identifier name;\n\n        if (_PyObject_LookupAttr(obj, state->pattern, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            pattern = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'MatchAs' node\")) {\n                goto failed;\n            }\n            res = obj2ast_pattern(state, tmp, &pattern, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            name = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'MatchAs' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &name, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_MatchAs(pattern, name, lineno, col_offset, end_lineno,\n                              end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->MatchOr_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        asdl_pattern_seq* patterns;\n\n        if (_PyObject_LookupAttr(obj, state->patterns, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"patterns\\\" missing from MatchOr\");\n            return 1;\n        }\n        else {\n            int res;\n            Py_ssize_t len;\n            Py_ssize_t i;\n            if (!PyList_Check(tmp)) {\n                PyErr_Format(PyExc_TypeError, \"MatchOr field \\\"patterns\\\" must be a list, not a %.200s\", _PyType_Name(Py_TYPE(tmp)));\n                goto failed;\n            }\n            len = PyList_GET_SIZE(tmp);\n            patterns = _Py_asdl_pattern_seq_new(len, arena);\n            if (patterns == NULL) goto failed;\n            for (i = 0; i < len; i++) {\n                pattern_ty val;\n                PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));\n                if (_Py_EnterRecursiveCall(\" while traversing 'MatchOr' node\")) {\n                    goto failed;\n                }\n                res = obj2ast_pattern(state, tmp2, &val, arena);\n                _Py_LeaveRecursiveCall();\n                Py_DECREF(tmp2);\n                if (res != 0) goto failed;\n                if (len != PyList_GET_SIZE(tmp)) {\n                    PyErr_SetString(PyExc_RuntimeError, \"MatchOr field \\\"patterns\\\" changed size during iteration\");\n                    goto failed;\n                }\n                asdl_seq_SET(patterns, i, val);\n            }\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_MatchOr(patterns, lineno, col_offset, end_lineno,\n                              end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"expected some sort of pattern, but got %R\", obj);\n    failed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty*\n                    out, PyArena* arena)\n{\n    int isinstance;\n\n    PyObject *tmp = NULL;\n    PyObject *tp;\n\n    if (obj == Py_None) {\n        *out = NULL;\n        return 0;\n    }\n    tp = state->TypeIgnore_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        int lineno;\n        string tag;\n\n        if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"lineno\\\" missing from TypeIgnore\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'TypeIgnore' node\")) {\n                goto failed;\n            }\n            res = obj2ast_int(state, tmp, &lineno, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->tag, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"tag\\\" missing from TypeIgnore\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'TypeIgnore' node\")) {\n                goto failed;\n            }\n            res = obj2ast_string(state, tmp, &tag, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_TypeIgnore(lineno, tag, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"expected some sort of type_ignore, but got %R\", obj);\n    failed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\nint\nobj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out,\n                   PyArena* arena)\n{\n    int isinstance;\n\n    PyObject *tmp = NULL;\n    PyObject *tp;\n    int lineno;\n    int col_offset;\n    int end_lineno;\n    int end_col_offset;\n\n    if (obj == Py_None) {\n        *out = NULL;\n        return 0;\n    }\n    if (_PyObject_LookupAttr(obj, state->lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"lineno\\\" missing from type_param\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'type_param' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL) {\n        PyErr_SetString(PyExc_TypeError, \"required field \\\"col_offset\\\" missing from type_param\");\n        return 1;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'type_param' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_lineno, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_lineno = lineno;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'type_param' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_lineno, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    if (_PyObject_LookupAttr(obj, state->end_col_offset, &tmp) < 0) {\n        return 1;\n    }\n    if (tmp == NULL || tmp == Py_None) {\n        Py_CLEAR(tmp);\n        end_col_offset = col_offset;\n    }\n    else {\n        int res;\n        if (_Py_EnterRecursiveCall(\" while traversing 'type_param' node\")) {\n            goto failed;\n        }\n        res = obj2ast_int(state, tmp, &end_col_offset, arena);\n        _Py_LeaveRecursiveCall();\n        if (res != 0) goto failed;\n        Py_CLEAR(tmp);\n    }\n    tp = state->TypeVar_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        identifier name;\n        expr_ty bound;\n\n        if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"name\\\" missing from TypeVar\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'TypeVar' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &name, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        if (_PyObject_LookupAttr(obj, state->bound, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL || tmp == Py_None) {\n            Py_CLEAR(tmp);\n            bound = NULL;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'TypeVar' node\")) {\n                goto failed;\n            }\n            res = obj2ast_expr(state, tmp, &bound, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_TypeVar(name, bound, lineno, col_offset, end_lineno,\n                              end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->ParamSpec_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        identifier name;\n\n        if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"name\\\" missing from ParamSpec\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'ParamSpec' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &name, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_ParamSpec(name, lineno, col_offset, end_lineno,\n                                end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n    tp = state->TypeVarTuple_type;\n    isinstance = PyObject_IsInstance(obj, tp);\n    if (isinstance == -1) {\n        return 1;\n    }\n    if (isinstance) {\n        identifier name;\n\n        if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) {\n            return 1;\n        }\n        if (tmp == NULL) {\n            PyErr_SetString(PyExc_TypeError, \"required field \\\"name\\\" missing from TypeVarTuple\");\n            return 1;\n        }\n        else {\n            int res;\n            if (_Py_EnterRecursiveCall(\" while traversing 'TypeVarTuple' node\")) {\n                goto failed;\n            }\n            res = obj2ast_identifier(state, tmp, &name, arena);\n            _Py_LeaveRecursiveCall();\n            if (res != 0) goto failed;\n            Py_CLEAR(tmp);\n        }\n        *out = _PyAST_TypeVarTuple(name, lineno, col_offset, end_lineno,\n                                   end_col_offset, arena);\n        if (*out == NULL) goto failed;\n        return 0;\n    }\n\n    PyErr_Format(PyExc_TypeError, \"expected some sort of type_param, but got %R\", obj);\n    failed:\n    Py_XDECREF(tmp);\n    return 1;\n}\n\n\nstatic int\nastmodule_exec(PyObject *m)\n{\n    struct ast_state *state = get_ast_state();\n    if (state == NULL) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"AST\", state->AST_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddIntMacro(m, PyCF_ALLOW_TOP_LEVEL_AWAIT) < 0) {\n        return -1;\n    }\n    if (PyModule_AddIntMacro(m, PyCF_ONLY_AST) < 0) {\n        return -1;\n    }\n    if (PyModule_AddIntMacro(m, PyCF_TYPE_COMMENTS) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"mod\", state->mod_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Module\", state->Module_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Interactive\", state->Interactive_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Expression\", state->Expression_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"FunctionType\", state->FunctionType_type) < 0)\n        {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"stmt\", state->stmt_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"FunctionDef\", state->FunctionDef_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"AsyncFunctionDef\",\n        state->AsyncFunctionDef_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"ClassDef\", state->ClassDef_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Return\", state->Return_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Delete\", state->Delete_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Assign\", state->Assign_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"TypeAlias\", state->TypeAlias_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"AugAssign\", state->AugAssign_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"AnnAssign\", state->AnnAssign_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"For\", state->For_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"AsyncFor\", state->AsyncFor_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"While\", state->While_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"If\", state->If_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"With\", state->With_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"AsyncWith\", state->AsyncWith_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Match\", state->Match_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Raise\", state->Raise_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Try\", state->Try_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"TryStar\", state->TryStar_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Assert\", state->Assert_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Import\", state->Import_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"ImportFrom\", state->ImportFrom_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Global\", state->Global_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Nonlocal\", state->Nonlocal_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Expr\", state->Expr_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Pass\", state->Pass_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Break\", state->Break_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Continue\", state->Continue_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"expr\", state->expr_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"BoolOp\", state->BoolOp_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"NamedExpr\", state->NamedExpr_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"BinOp\", state->BinOp_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"UnaryOp\", state->UnaryOp_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Lambda\", state->Lambda_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"IfExp\", state->IfExp_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Dict\", state->Dict_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Set\", state->Set_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"ListComp\", state->ListComp_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"SetComp\", state->SetComp_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"DictComp\", state->DictComp_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"GeneratorExp\", state->GeneratorExp_type) < 0)\n        {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Await\", state->Await_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Yield\", state->Yield_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"YieldFrom\", state->YieldFrom_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Compare\", state->Compare_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Call\", state->Call_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"FormattedValue\", state->FormattedValue_type)\n        < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"JoinedStr\", state->JoinedStr_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Constant\", state->Constant_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Attribute\", state->Attribute_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Subscript\", state->Subscript_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Starred\", state->Starred_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Name\", state->Name_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"List\", state->List_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Tuple\", state->Tuple_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Slice\", state->Slice_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"expr_context\", state->expr_context_type) < 0)\n        {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Load\", state->Load_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Store\", state->Store_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Del\", state->Del_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"boolop\", state->boolop_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"And\", state->And_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Or\", state->Or_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"operator\", state->operator_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Add\", state->Add_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Sub\", state->Sub_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Mult\", state->Mult_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"MatMult\", state->MatMult_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Div\", state->Div_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Mod\", state->Mod_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Pow\", state->Pow_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"LShift\", state->LShift_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"RShift\", state->RShift_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"BitOr\", state->BitOr_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"BitXor\", state->BitXor_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"BitAnd\", state->BitAnd_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"FloorDiv\", state->FloorDiv_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"unaryop\", state->unaryop_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Invert\", state->Invert_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Not\", state->Not_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"UAdd\", state->UAdd_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"USub\", state->USub_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"cmpop\", state->cmpop_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Eq\", state->Eq_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"NotEq\", state->NotEq_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Lt\", state->Lt_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"LtE\", state->LtE_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Gt\", state->Gt_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"GtE\", state->GtE_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"Is\", state->Is_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"IsNot\", state->IsNot_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"In\", state->In_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"NotIn\", state->NotIn_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"comprehension\", state->comprehension_type) <\n        0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"excepthandler\", state->excepthandler_type) <\n        0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"ExceptHandler\", state->ExceptHandler_type) <\n        0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"arguments\", state->arguments_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"arg\", state->arg_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"keyword\", state->keyword_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"alias\", state->alias_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"withitem\", state->withitem_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"match_case\", state->match_case_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"pattern\", state->pattern_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"MatchValue\", state->MatchValue_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"MatchSingleton\", state->MatchSingleton_type)\n        < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"MatchSequence\", state->MatchSequence_type) <\n        0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"MatchMapping\", state->MatchMapping_type) < 0)\n        {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"MatchClass\", state->MatchClass_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"MatchStar\", state->MatchStar_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"MatchAs\", state->MatchAs_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"MatchOr\", state->MatchOr_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"type_ignore\", state->type_ignore_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"TypeIgnore\", state->TypeIgnore_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"type_param\", state->type_param_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"TypeVar\", state->TypeVar_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"ParamSpec\", state->ParamSpec_type) < 0) {\n        return -1;\n    }\n    if (PyModule_AddObjectRef(m, \"TypeVarTuple\", state->TypeVarTuple_type) < 0)\n        {\n        return -1;\n    }\n    return 0;\n}\n\nstatic PyModuleDef_Slot astmodule_slots[] = {\n    {Py_mod_exec, astmodule_exec},\n    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},\n    {0, NULL}\n};\n\nstatic struct PyModuleDef _astmodule = {\n    PyModuleDef_HEAD_INIT,\n    .m_name = \"_ast\",\n    // The _ast module uses a per-interpreter state (PyInterpreterState.ast)\n    .m_size = 0,\n    .m_slots = astmodule_slots,\n};\n\nPyMODINIT_FUNC\nPyInit__ast(void)\n{\n    return PyModuleDef_Init(&_astmodule);\n}\n\n\nPyObject* PyAST_mod2obj(mod_ty t)\n{\n    struct ast_state *state = get_ast_state();\n    if (state == NULL) {\n        return NULL;\n    }\n\n    int starting_recursion_depth;\n    /* Be careful here to prevent overflow. */\n    int COMPILER_STACK_FRAME_SCALE = 3;\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (!tstate) {\n        return 0;\n    }\n    state->recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;\n    int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;\n    starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;\n    state->recursion_depth = starting_recursion_depth;\n\n    PyObject *result = ast2obj_mod(state, t);\n\n    /* Check that the recursion depth counting balanced correctly */\n    if (result && state->recursion_depth != starting_recursion_depth) {\n        PyErr_Format(PyExc_SystemError,\n            \"AST constructor recursion depth mismatch (before=%d, after=%d)\",\n            starting_recursion_depth, state->recursion_depth);\n        return 0;\n    }\n    return result;\n}\n\n/* mode is 0 for \"exec\", 1 for \"eval\" and 2 for \"single\" input */\nmod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode)\n{\n    const char * const req_name[] = {\"Module\", \"Expression\", \"Interactive\"};\n    int isinstance;\n\n    if (PySys_Audit(\"compile\", \"OO\", ast, Py_None) < 0) {\n        return NULL;\n    }\n\n    struct ast_state *state = get_ast_state();\n    if (state == NULL) {\n        return NULL;\n    }\n\n    PyObject *req_type[3];\n    req_type[0] = state->Module_type;\n    req_type[1] = state->Expression_type;\n    req_type[2] = state->Interactive_type;\n\n    assert(0 <= mode && mode <= 2);\n\n    isinstance = PyObject_IsInstance(ast, req_type[mode]);\n    if (isinstance == -1)\n        return NULL;\n    if (!isinstance) {\n        PyErr_Format(PyExc_TypeError, \"expected %s node, got %.400s\",\n                     req_name[mode], _PyType_Name(Py_TYPE(ast)));\n        return NULL;\n    }\n\n    mod_ty res = NULL;\n    if (obj2ast_mod(state, ast, &res, arena) != 0)\n        return NULL;\n    else\n        return res;\n}\n\nint PyAST_Check(PyObject* obj)\n{\n    struct ast_state *state = get_ast_state();\n    if (state == NULL) {\n        return -1;\n    }\n    return PyObject_IsInstance(obj, state->AST_type);\n}\n\n"
  },
  {
    "path": "Python-Tokenize.c",
    "content": "#include \"Python.h\"\n#include \"errcode.h\"\n#include \"../Parser/tokenizer.h\"\n#include \"../Parser/pegen.h\"      // _PyPegen_byte_offset_to_character_offset()\n#include \"../Parser/pegen.h\"      // _PyPegen_byte_offset_to_character_offset()\n\nstatic struct PyModuleDef _tokenizemodule;\n\ntypedef struct {\n    PyTypeObject *TokenizerIter;\n} tokenize_state;\n\nstatic tokenize_state *\nget_tokenize_state(PyObject *module) {\n    return (tokenize_state *)PyModule_GetState(module);\n}\n\n#define _tokenize_get_state_by_type(type) \\\n    get_tokenize_state(PyType_GetModuleByDef(type, &_tokenizemodule))\n\n#include \"pycore_runtime.h\"\n#include \"clinic/Python-tokenize.c.h\"\n\n/*[clinic input]\nmodule _tokenizer\nclass _tokenizer.tokenizeriter \"tokenizeriterobject *\" \"_tokenize_get_state_by_type(type)->TokenizerIter\"\n[clinic start generated code]*/\n/*[clinic end generated code: output=da39a3ee5e6b4b0d input=96d98ee2fef7a8bc]*/\n\ntypedef struct\n{\n    PyObject_HEAD struct tok_state *tok;\n    int done;\n} tokenizeriterobject;\n\n/*[clinic input]\n@classmethod\n_tokenizer.tokenizeriter.__new__ as tokenizeriter_new\n\n    readline: object\n    /\n    *\n    extra_tokens: bool\n    encoding: str(c_default=\"NULL\") = 'utf-8'\n[clinic start generated code]*/\n\nstatic PyObject *\ntokenizeriter_new_impl(PyTypeObject *type, PyObject *readline,\n                       int extra_tokens, const char *encoding)\n/*[clinic end generated code: output=7501a1211683ce16 input=f7dddf8a613ae8bd]*/\n{\n    tokenizeriterobject *self = (tokenizeriterobject *)type->tp_alloc(type, 0);\n    if (self == NULL) {\n        return NULL;\n    }\n    PyObject *filename = PyUnicode_FromString(\"<string>\");\n    if (filename == NULL) {\n        return NULL;\n    }\n    self->tok = _PyTokenizer_FromReadline(readline, encoding, 1, 1);\n    if (self->tok == NULL) {\n        Py_DECREF(filename);\n        return NULL;\n    }\n    self->tok->filename = filename;\n    if (extra_tokens) {\n        self->tok->tok_extra_tokens = 1;\n    }\n    self->done = 0;\n    return (PyObject *)self;\n}\n\nstatic int\n_tokenizer_error(struct tok_state *tok)\n{\n    if (PyErr_Occurred()) {\n        return -1;\n    }\n\n    const char *msg = NULL;\n    PyObject* errtype = PyExc_SyntaxError;\n    switch (tok->done) {\n        case E_TOKEN:\n            msg = \"invalid token\";\n            break;\n        case E_EOF:\n            if (tok->level > 0) {\n                    PyErr_Format(PyExc_SyntaxError,\n                                 \"parenthesis '%c' was never closed\",\n                                tok->parenstack[tok->level-1]);\n            } else {\n                PyErr_SetString(PyExc_SyntaxError, \"unexpected EOF while parsing\");\n            }\n            return -1;\n        case E_DEDENT:\n            msg = \"unindent does not match any outer indentation level\";\n            errtype = PyExc_IndentationError;\n            break;\n        case E_INTR:\n            if (!PyErr_Occurred()) {\n                PyErr_SetNone(PyExc_KeyboardInterrupt);\n            }\n            return -1;\n        case E_NOMEM:\n            PyErr_NoMemory();\n            return -1;\n        case E_TABSPACE:\n            errtype = PyExc_TabError;\n            msg = \"inconsistent use of tabs and spaces in indentation\";\n            break;\n        case E_TOODEEP:\n            errtype = PyExc_IndentationError;\n            msg = \"too many levels of indentation\";\n            break;\n        case E_LINECONT: {\n            msg = \"unexpected character after line continuation character\";\n            break;\n        }\n        default:\n            msg = \"unknown tokenization error\";\n    }\n\n    PyObject* errstr = NULL;\n    PyObject* error_line = NULL;\n    PyObject* tmp = NULL;\n    PyObject* value = NULL;\n    int result = 0;\n\n    Py_ssize_t size = tok->inp - tok->buf;\n    assert(tok->buf[size-1] == '\\n');\n    size -= 1; // Remove the newline character from the end of the line\n    error_line = PyUnicode_DecodeUTF8(tok->buf, size, \"replace\");\n    if (!error_line) {\n        result = -1;\n        goto exit;\n    }\n\n    Py_ssize_t offset = _PyPegen_byte_offset_to_character_offset(error_line, tok->inp - tok->buf);\n    if (offset == -1) {\n        result = -1;\n        goto exit;\n    }\n    tmp = Py_BuildValue(\"(OnnOOO)\", tok->filename, tok->lineno, offset, error_line, Py_None, Py_None);\n    if (!tmp) {\n        result = -1;\n        goto exit;\n    }\n\n    errstr = PyUnicode_FromString(msg);\n    if (!errstr) {\n        result = -1;\n        goto exit;\n    }\n\n    value = PyTuple_Pack(2, errstr, tmp);\n    if (!value) {\n        result = -1;\n        goto exit;\n    }\n\n    PyErr_SetObject(errtype, value);\n\nexit:\n    Py_XDECREF(errstr);\n    Py_XDECREF(error_line);\n    Py_XDECREF(tmp);\n    Py_XDECREF(value);\n    return result;\n}\n\nstatic PyObject *\ntokenizeriter_next(tokenizeriterobject *it)\n{\n    PyObject* result = NULL;\n    struct token token;\n    _PyToken_Init(&token);\n\n    int type = _PyTokenizer_Get(it->tok, &token);\n    if (type == ERRORTOKEN) {\n        if(!PyErr_Occurred()) {\n            _tokenizer_error(it->tok);\n            assert(PyErr_Occurred());\n        }\n        goto exit;\n    }\n    if (it->done || type == ERRORTOKEN) {\n        PyErr_SetString(PyExc_StopIteration, \"EOF\");\n        it->done = 1;\n        goto exit;\n    }\n    PyObject *str = NULL;\n    if (token.start == NULL || token.end == NULL) {\n        str = PyUnicode_FromString(\"\");\n    }\n    else {\n        str = PyUnicode_FromStringAndSize(token.start, token.end - token.start);\n    }\n    if (str == NULL) {\n        goto exit;\n    }\n\n    int is_trailing_token = 0;\n    if (type == ENDMARKER || (type == DEDENT && it->tok->done == E_EOF)) {\n        is_trailing_token = 1;\n    }\n\n    const char *line_start = ISSTRINGLIT(type) ? it->tok->multi_line_start : it->tok->line_start;\n    PyObject* line = NULL;\n    if (it->tok->tok_extra_tokens && is_trailing_token) {\n        line = PyUnicode_FromString(\"\");\n    } else {\n        Py_ssize_t size = it->tok->inp - line_start;\n        line = PyUnicode_DecodeUTF8(line_start, size, \"replace\");\n    }\n    if (line == NULL) {\n        Py_DECREF(str);\n        goto exit;\n    }\n\n    Py_ssize_t lineno = ISSTRINGLIT(type) ? it->tok->first_lineno : it->tok->lineno;\n    Py_ssize_t end_lineno = it->tok->lineno;\n    Py_ssize_t col_offset = -1;\n    Py_ssize_t end_col_offset = -1;\n    if (token.start != NULL && token.start >= line_start) {\n        col_offset = _PyPegen_byte_offset_to_character_offset(line, token.start - line_start);\n    }\n    if (token.end != NULL && token.end >= it->tok->line_start) {\n        end_col_offset = _PyPegen_byte_offset_to_character_offset(line, token.end - it->tok->line_start);\n    }\n\n    if (it->tok->tok_extra_tokens) {\n        if (is_trailing_token) {\n            lineno = end_lineno = lineno + 1;\n            col_offset = end_col_offset = 0;\n        }\n        // Necessary adjustments to match the original Python tokenize\n        // implementation\n        if (type > DEDENT && type < OP) {\n            type = OP;\n        }\n        else if (type == ASYNC || type == AWAIT) {\n            type = NAME;\n        }\n        else if (type == NEWLINE) {\n            Py_DECREF(str);\n            if (it->tok->start[0] == '\\r') {\n                str = PyUnicode_FromString(\"\\r\\n\");\n            } else {\n                str = PyUnicode_FromString(\"\\n\");\n            }\n            end_col_offset++;\n        }\n    }\n\n    result = Py_BuildValue(\"(iN(nn)(nn)N)\", type, str, lineno, col_offset, end_lineno, end_col_offset, line);\nexit:\n    _PyToken_Free(&token);\n    if (type == ENDMARKER) {\n        it->done = 1;\n    }\n    return result;\n}\n\nstatic void\ntokenizeriter_dealloc(tokenizeriterobject *it)\n{\n    PyTypeObject *tp = Py_TYPE(it);\n    _PyTokenizer_Free(it->tok);\n    tp->tp_free(it);\n    Py_DECREF(tp);\n}\n\nstatic PyType_Slot tokenizeriter_slots[] = {\n    {Py_tp_new, tokenizeriter_new},\n    {Py_tp_dealloc, tokenizeriter_dealloc},\n    {Py_tp_getattro, PyObject_GenericGetAttr},\n    {Py_tp_iter, PyObject_SelfIter},\n    {Py_tp_iternext, tokenizeriter_next},\n    {0, NULL},\n};\n\nstatic PyType_Spec tokenizeriter_spec = {\n    .name = \"_tokenize.TokenizerIter\",\n    .basicsize = sizeof(tokenizeriterobject),\n    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE),\n    .slots = tokenizeriter_slots,\n};\n\nstatic int\ntokenizemodule_exec(PyObject *m)\n{\n    tokenize_state *state = get_tokenize_state(m);\n    if (state == NULL) {\n        return -1;\n    }\n\n    state->TokenizerIter = (PyTypeObject *)PyType_FromModuleAndSpec(m, &tokenizeriter_spec, NULL);\n    if (state->TokenizerIter == NULL) {\n        return -1;\n    }\n    if (PyModule_AddType(m, state->TokenizerIter) < 0) {\n        return -1;\n    }\n\n    return 0;\n}\n\nstatic PyMethodDef tokenize_methods[] = {\n    {NULL, NULL, 0, NULL} /* Sentinel */\n};\n\nstatic PyModuleDef_Slot tokenizemodule_slots[] = {\n    {Py_mod_exec, tokenizemodule_exec},\n    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},\n    {0, NULL}\n};\n\nstatic int\ntokenizemodule_traverse(PyObject *m, visitproc visit, void *arg)\n{\n    tokenize_state *state = get_tokenize_state(m);\n    Py_VISIT(state->TokenizerIter);\n    return 0;\n}\n\nstatic int\ntokenizemodule_clear(PyObject *m)\n{\n    tokenize_state *state = get_tokenize_state(m);\n    Py_CLEAR(state->TokenizerIter);\n    return 0;\n}\n\nstatic void\ntokenizemodule_free(void *m)\n{\n    tokenizemodule_clear((PyObject *)m);\n}\n\nstatic struct PyModuleDef _tokenizemodule = {\n    PyModuleDef_HEAD_INIT,\n    .m_name = \"_tokenize\",\n    .m_size = sizeof(tokenize_state),\n    .m_slots = tokenizemodule_slots,\n    .m_methods = tokenize_methods,\n    .m_traverse = tokenizemodule_traverse,\n    .m_clear = tokenizemodule_clear,\n    .m_free = tokenizemodule_free,\n};\n\nPyMODINIT_FUNC\nPyInit__tokenize(void)\n{\n    return PyModuleDef_Init(&_tokenizemodule);\n}\n"
  },
  {
    "path": "PythonRun.c",
    "content": "\n/* Top level execution of Python code (including in __main__) */\n\n/* To help control the interfaces between the startup, execution and\n * shutdown code, the phases are split across separate modules (bootstrap,\n * pythonrun, shutdown)\n */\n\n/* TODO: Cull includes following phase split */\n\n#include <stdbool.h>\n\n#include \"Python.h\"\n\n#include \"pycore_ast.h\"           // PyAST_mod2obj\n#include \"pycore_ceval.h\"         // _Py_EnterRecursiveCall\n#include \"pycore_compile.h\"       // _PyAST_Compile()\n#include \"pycore_interp.h\"        // PyInterpreterState.importlib\n#include \"pycore_object.h\"        // _PyDebug_PrintTotalRefs()\n#include \"pycore_parser.h\"        // _PyParser_ASTFromString()\n#include \"pycore_pyerrors.h\"      // _PyErr_GetRaisedException, _Py_Offer_Suggestions\n#include \"pycore_pylifecycle.h\"   // _Py_UnhandledKeyboardInterrupt\n#include \"pycore_pystate.h\"       // _PyInterpreterState_GET()\n#include \"pycore_sysmodule.h\"     // _PySys_Audit()\n#include \"pycore_traceback.h\"     // _PyTraceBack_Print_Indented()\n\n#include \"errcode.h\"              // E_EOF\n#include \"marshal.h\"              // PyMarshal_ReadLongFromFile()\n\n#ifdef MS_WINDOWS\n#  include \"malloc.h\"             // alloca()\n#endif\n\n#ifdef MS_WINDOWS\n#  undef BYTE\n#  include \"windows.h\"\n#endif\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Forward */\nstatic void flush_io(void);\nstatic PyObject *run_mod(mod_ty, PyObject *, PyObject *, PyObject *,\n                          PyCompilerFlags *, PyArena *);\nstatic PyObject *run_pyc_file(FILE *, PyObject *, PyObject *,\n                              PyCompilerFlags *);\nstatic int PyRun_InteractiveOneObjectEx(FILE *, PyObject *, PyCompilerFlags *);\nstatic PyObject* pyrun_file(FILE *fp, PyObject *filename, int start,\n                            PyObject *globals, PyObject *locals, int closeit,\n                            PyCompilerFlags *flags);\n\n\nint\n_PyRun_AnyFileObject(FILE *fp, PyObject *filename, int closeit,\n                     PyCompilerFlags *flags)\n{\n    int decref_filename = 0;\n    if (filename == NULL) {\n        filename = PyUnicode_FromString(\"???\");\n        if (filename == NULL) {\n            PyErr_Print();\n            return -1;\n        }\n        decref_filename = 1;\n    }\n\n    int res;\n    if (_Py_FdIsInteractive(fp, filename)) {\n        res = _PyRun_InteractiveLoopObject(fp, filename, flags);\n        if (closeit) {\n            fclose(fp);\n        }\n    }\n    else {\n        res = _PyRun_SimpleFileObject(fp, filename, closeit, flags);\n    }\n\n    if (decref_filename) {\n        Py_DECREF(filename);\n    }\n    return res;\n}\n\n\n/* Parse input from a file and execute it */\nint\nPyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,\n                     PyCompilerFlags *flags)\n{\n    PyObject *filename_obj;\n    if (filename != NULL) {\n        filename_obj = PyUnicode_DecodeFSDefault(filename);\n        if (filename_obj == NULL) {\n            PyErr_Print();\n            return -1;\n        }\n    }\n    else {\n        filename_obj = NULL;\n    }\n    int res = _PyRun_AnyFileObject(fp, filename_obj, closeit, flags);\n    Py_XDECREF(filename_obj);\n    return res;\n}\n\n\nint\n_PyRun_InteractiveLoopObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)\n{\n    PyCompilerFlags local_flags = _PyCompilerFlags_INIT;\n    if (flags == NULL) {\n        flags = &local_flags;\n    }\n\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *v = _PySys_GetAttr(tstate, &_Py_ID(ps1));\n    if (v == NULL) {\n        _PySys_SetAttr(&_Py_ID(ps1), v = PyUnicode_FromString(\">>> \"));\n        Py_XDECREF(v);\n    }\n    v = _PySys_GetAttr(tstate, &_Py_ID(ps2));\n    if (v == NULL) {\n        _PySys_SetAttr(&_Py_ID(ps2), v = PyUnicode_FromString(\"... \"));\n        Py_XDECREF(v);\n    }\n\n#ifdef Py_REF_DEBUG\n    int show_ref_count = _Py_GetConfig()->show_ref_count;\n#endif\n    int err = 0;\n    int ret;\n    int nomem_count = 0;\n    do {\n        ret = PyRun_InteractiveOneObjectEx(fp, filename, flags);\n        if (ret == -1 && PyErr_Occurred()) {\n            /* Prevent an endless loop after multiple consecutive MemoryErrors\n             * while still allowing an interactive command to fail with a\n             * MemoryError. */\n            if (PyErr_ExceptionMatches(PyExc_MemoryError)) {\n                if (++nomem_count > 16) {\n                    PyErr_Clear();\n                    err = -1;\n                    break;\n                }\n            } else {\n                nomem_count = 0;\n            }\n            PyErr_Print();\n            flush_io();\n        } else {\n            nomem_count = 0;\n        }\n#ifdef Py_REF_DEBUG\n        if (show_ref_count) {\n            _PyDebug_PrintTotalRefs();\n        }\n#endif\n    } while (ret != E_EOF);\n    return err;\n}\n\n\nint\nPyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flags)\n{\n    PyObject *filename_obj = PyUnicode_DecodeFSDefault(filename);\n    if (filename_obj == NULL) {\n        PyErr_Print();\n        return -1;\n    }\n\n    int err = _PyRun_InteractiveLoopObject(fp, filename_obj, flags);\n    Py_DECREF(filename_obj);\n    return err;\n\n}\n\n\n/* A PyRun_InteractiveOneObject() auxiliary function that does not print the\n * error on failure. */\nstatic int\nPyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename,\n                             PyCompilerFlags *flags)\n{\n    PyObject *m, *d, *v, *w, *oenc = NULL;\n    mod_ty mod;\n    PyArena *arena;\n    const char *ps1 = \"\", *ps2 = \"\", *enc = NULL;\n    int errcode = 0;\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    if (fp == stdin) {\n        /* Fetch encoding from sys.stdin if possible. */\n        v = _PySys_GetAttr(tstate, &_Py_ID(stdin));\n        if (v && v != Py_None) {\n            oenc = PyObject_GetAttr(v, &_Py_ID(encoding));\n            if (oenc)\n                enc = PyUnicode_AsUTF8(oenc);\n            if (!enc)\n                PyErr_Clear();\n        }\n    }\n    v = _PySys_GetAttr(tstate, &_Py_ID(ps1));\n    if (v != NULL) {\n        v = PyObject_Str(v);\n        if (v == NULL)\n            PyErr_Clear();\n        else if (PyUnicode_Check(v)) {\n            ps1 = PyUnicode_AsUTF8(v);\n            if (ps1 == NULL) {\n                PyErr_Clear();\n                ps1 = \"\";\n            }\n        }\n    }\n    w = _PySys_GetAttr(tstate, &_Py_ID(ps2));\n    if (w != NULL) {\n        w = PyObject_Str(w);\n        if (w == NULL)\n            PyErr_Clear();\n        else if (PyUnicode_Check(w)) {\n            ps2 = PyUnicode_AsUTF8(w);\n            if (ps2 == NULL) {\n                PyErr_Clear();\n                ps2 = \"\";\n            }\n        }\n    }\n    arena = _PyArena_New();\n    if (arena == NULL) {\n        Py_XDECREF(v);\n        Py_XDECREF(w);\n        Py_XDECREF(oenc);\n        return -1;\n    }\n\n    mod = _PyParser_ASTFromFile(fp, filename, enc, Py_single_input,\n                                ps1, ps2, flags, &errcode, arena);\n\n    Py_XDECREF(v);\n    Py_XDECREF(w);\n    Py_XDECREF(oenc);\n    if (mod == NULL) {\n        _PyArena_Free(arena);\n        if (errcode == E_EOF) {\n            PyErr_Clear();\n            return E_EOF;\n        }\n        return -1;\n    }\n    m = PyImport_AddModuleObject(&_Py_ID(__main__));\n    if (m == NULL) {\n        _PyArena_Free(arena);\n        return -1;\n    }\n    d = PyModule_GetDict(m);\n    v = run_mod(mod, filename, d, d, flags, arena);\n    _PyArena_Free(arena);\n    if (v == NULL) {\n        return -1;\n    }\n    Py_DECREF(v);\n    flush_io();\n    return 0;\n}\n\nint\nPyRun_InteractiveOneObject(FILE *fp, PyObject *filename, PyCompilerFlags *flags)\n{\n    int res;\n\n    res = PyRun_InteractiveOneObjectEx(fp, filename, flags);\n    if (res == -1) {\n        PyErr_Print();\n        flush_io();\n    }\n    return res;\n}\n\nint\nPyRun_InteractiveOneFlags(FILE *fp, const char *filename_str, PyCompilerFlags *flags)\n{\n    PyObject *filename;\n    int res;\n\n    filename = PyUnicode_DecodeFSDefault(filename_str);\n    if (filename == NULL) {\n        PyErr_Print();\n        return -1;\n    }\n    res = PyRun_InteractiveOneObject(fp, filename, flags);\n    Py_DECREF(filename);\n    return res;\n}\n\n\n/* Check whether a file maybe a pyc file: Look at the extension,\n   the file type, and, if we may close it, at the first few bytes. */\n\nstatic int\nmaybe_pyc_file(FILE *fp, PyObject *filename, int closeit)\n{\n    PyObject *ext = PyUnicode_FromString(\".pyc\");\n    if (ext == NULL) {\n        return -1;\n    }\n    Py_ssize_t endswith = PyUnicode_Tailmatch(filename, ext, 0, PY_SSIZE_T_MAX, +1);\n    Py_DECREF(ext);\n    if (endswith) {\n        return 1;\n    }\n\n    /* Only look into the file if we are allowed to close it, since\n       it then should also be seekable. */\n    if (!closeit) {\n        return 0;\n    }\n\n    /* Read only two bytes of the magic. If the file was opened in\n       text mode, the bytes 3 and 4 of the magic (\\r\\n) might not\n       be read as they are on disk. */\n    unsigned int halfmagic = PyImport_GetMagicNumber() & 0xFFFF;\n    unsigned char buf[2];\n    /* Mess:  In case of -x, the stream is NOT at its start now,\n       and ungetc() was used to push back the first newline,\n       which makes the current stream position formally undefined,\n       and a x-platform nightmare.\n       Unfortunately, we have no direct way to know whether -x\n       was specified.  So we use a terrible hack:  if the current\n       stream position is not 0, we assume -x was specified, and\n       give up.  Bug 132850 on SourceForge spells out the\n       hopelessness of trying anything else (fseek and ftell\n       don't work predictably x-platform for text-mode files).\n    */\n    int ispyc = 0;\n    if (ftell(fp) == 0) {\n        if (fread(buf, 1, 2, fp) == 2 &&\n            ((unsigned int)buf[1]<<8 | buf[0]) == halfmagic)\n            ispyc = 1;\n        rewind(fp);\n    }\n    return ispyc;\n}\n\n\nstatic int\nset_main_loader(PyObject *d, PyObject *filename, const char *loader_name)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    PyObject *loader_type = _PyImport_GetImportlibExternalLoader(interp,\n                                                                 loader_name);\n    if (loader_type == NULL) {\n        return -1;\n    }\n\n    PyObject *loader = PyObject_CallFunction(loader_type,\n                                             \"sO\", \"__main__\", filename);\n    Py_DECREF(loader_type);\n    if (loader == NULL) {\n        return -1;\n    }\n\n    if (PyDict_SetItemString(d, \"__loader__\", loader) < 0) {\n        Py_DECREF(loader);\n        return -1;\n    }\n    Py_DECREF(loader);\n    return 0;\n}\n\n\nint\n_PyRun_SimpleFileObject(FILE *fp, PyObject *filename, int closeit,\n                        PyCompilerFlags *flags)\n{\n    PyObject *m, *d, *v;\n    int set_file_name = 0, ret = -1;\n\n    m = PyImport_AddModule(\"__main__\");\n    if (m == NULL)\n        return -1;\n    Py_INCREF(m);\n    d = PyModule_GetDict(m);\n    if (_PyDict_GetItemStringWithError(d, \"__file__\") == NULL) {\n        if (PyErr_Occurred()) {\n            goto done;\n        }\n        if (PyDict_SetItemString(d, \"__file__\", filename) < 0) {\n            goto done;\n        }\n        if (PyDict_SetItemString(d, \"__cached__\", Py_None) < 0) {\n            goto done;\n        }\n        set_file_name = 1;\n    }\n\n    int pyc = maybe_pyc_file(fp, filename, closeit);\n    if (pyc < 0) {\n        goto done;\n    }\n\n    if (pyc) {\n        FILE *pyc_fp;\n        /* Try to run a pyc file. First, re-open in binary */\n        if (closeit) {\n            fclose(fp);\n        }\n\n        pyc_fp = _Py_fopen_obj(filename, \"rb\");\n        if (pyc_fp == NULL) {\n            fprintf(stderr, \"python: Can't reopen .pyc file\\n\");\n            goto done;\n        }\n\n        if (set_main_loader(d, filename, \"SourcelessFileLoader\") < 0) {\n            fprintf(stderr, \"python: failed to set __main__.__loader__\\n\");\n            ret = -1;\n            fclose(pyc_fp);\n            goto done;\n        }\n        v = run_pyc_file(pyc_fp, d, d, flags);\n    } else {\n        /* When running from stdin, leave __main__.__loader__ alone */\n        if (PyUnicode_CompareWithASCIIString(filename, \"<stdin>\") != 0 &&\n            set_main_loader(d, filename, \"SourceFileLoader\") < 0) {\n            fprintf(stderr, \"python: failed to set __main__.__loader__\\n\");\n            ret = -1;\n            goto done;\n        }\n        v = pyrun_file(fp, filename, Py_file_input, d, d,\n                       closeit, flags);\n    }\n    flush_io();\n    if (v == NULL) {\n        Py_CLEAR(m);\n        PyErr_Print();\n        goto done;\n    }\n    Py_DECREF(v);\n    ret = 0;\n  done:\n    if (set_file_name) {\n        if (PyDict_DelItemString(d, \"__file__\")) {\n            PyErr_Clear();\n        }\n        if (PyDict_DelItemString(d, \"__cached__\")) {\n            PyErr_Clear();\n        }\n    }\n    Py_XDECREF(m);\n    return ret;\n}\n\n\nint\nPyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,\n                        PyCompilerFlags *flags)\n{\n    PyObject *filename_obj = PyUnicode_DecodeFSDefault(filename);\n    if (filename_obj == NULL) {\n        return -1;\n    }\n    int res = _PyRun_SimpleFileObject(fp, filename_obj, closeit, flags);\n    Py_DECREF(filename_obj);\n    return res;\n}\n\n\nint\nPyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags)\n{\n    PyObject *m, *d, *v;\n    m = PyImport_AddModule(\"__main__\");\n    if (m == NULL)\n        return -1;\n    d = PyModule_GetDict(m);\n    v = PyRun_StringFlags(command, Py_file_input, d, d, flags);\n    if (v == NULL) {\n        PyErr_Print();\n        return -1;\n    }\n    Py_DECREF(v);\n    return 0;\n}\n\nstatic int\nparse_syntax_error(PyObject *err, PyObject **message, PyObject **filename,\n                   Py_ssize_t *lineno, Py_ssize_t *offset,\n                   Py_ssize_t* end_lineno, Py_ssize_t* end_offset,\n                   PyObject **text)\n{\n    Py_ssize_t hold;\n    PyObject *v;\n\n    *message = NULL;\n    *filename = NULL;\n\n    /* new style errors.  `err' is an instance */\n    *message = PyObject_GetAttr(err, &_Py_ID(msg));\n    if (!*message)\n        goto finally;\n\n    v = PyObject_GetAttr(err, &_Py_ID(filename));\n    if (!v)\n        goto finally;\n    if (v == Py_None) {\n        Py_DECREF(v);\n        _Py_DECLARE_STR(anon_string, \"<string>\");\n        *filename = Py_NewRef(&_Py_STR(anon_string));\n    }\n    else {\n        *filename = v;\n    }\n\n    v = PyObject_GetAttr(err, &_Py_ID(lineno));\n    if (!v)\n        goto finally;\n    hold = PyLong_AsSsize_t(v);\n    Py_DECREF(v);\n    if (hold < 0 && PyErr_Occurred())\n        goto finally;\n    *lineno = hold;\n\n    v = PyObject_GetAttr(err, &_Py_ID(offset));\n    if (!v)\n        goto finally;\n    if (v == Py_None) {\n        *offset = -1;\n        Py_DECREF(v);\n    } else {\n        hold = PyLong_AsSsize_t(v);\n        Py_DECREF(v);\n        if (hold < 0 && PyErr_Occurred())\n            goto finally;\n        *offset = hold;\n    }\n\n    if (Py_TYPE(err) == (PyTypeObject*)PyExc_SyntaxError) {\n        v = PyObject_GetAttr(err, &_Py_ID(end_lineno));\n        if (!v) {\n            PyErr_Clear();\n            *end_lineno = *lineno;\n        }\n        else if (v == Py_None) {\n            *end_lineno = *lineno;\n            Py_DECREF(v);\n        } else {\n            hold = PyLong_AsSsize_t(v);\n            Py_DECREF(v);\n            if (hold < 0 && PyErr_Occurred())\n                goto finally;\n            *end_lineno = hold;\n        }\n\n        v = PyObject_GetAttr(err, &_Py_ID(end_offset));\n        if (!v) {\n            PyErr_Clear();\n            *end_offset = -1;\n        }\n        else if (v == Py_None) {\n            *end_offset = -1;\n            Py_DECREF(v);\n        } else {\n            hold = PyLong_AsSsize_t(v);\n            Py_DECREF(v);\n            if (hold < 0 && PyErr_Occurred())\n                goto finally;\n            *end_offset = hold;\n        }\n    } else {\n        // SyntaxError subclasses\n        *end_lineno = *lineno;\n        *end_offset = -1;\n    }\n\n    v = PyObject_GetAttr(err, &_Py_ID(text));\n    if (!v)\n        goto finally;\n    if (v == Py_None) {\n        Py_DECREF(v);\n        *text = NULL;\n    }\n    else {\n        *text = v;\n    }\n    return 1;\n\nfinally:\n    Py_XDECREF(*message);\n    Py_XDECREF(*filename);\n    return 0;\n}\n\nstatic int\nprint_error_text(PyObject *f, Py_ssize_t offset, Py_ssize_t end_offset,\n                 PyObject *text_obj)\n{\n    size_t caret_repetitions = (end_offset > 0 && end_offset > offset) ?\n                               end_offset - offset : 1;\n\n    /* Convert text to a char pointer; return if error */\n    const char *text = PyUnicode_AsUTF8(text_obj);\n    if (text == NULL) {\n        return -1;\n    }\n\n    /* Convert offset from 1-based to 0-based */\n    offset--;\n\n    /* Strip leading whitespace from text, adjusting offset as we go */\n    while (*text == ' ' || *text == '\\t' || *text == '\\f') {\n        text++;\n        offset--;\n    }\n\n    /* Calculate text length excluding trailing newline */\n    Py_ssize_t len = strlen(text);\n    if (len > 0 && text[len-1] == '\\n') {\n        len--;\n    }\n\n    /* Clip offset to at most len */\n    if (offset > len) {\n        offset = len;\n    }\n\n    /* Skip past newlines embedded in text */\n    for (;;) {\n        const char *nl = strchr(text, '\\n');\n        if (nl == NULL) {\n            break;\n        }\n        Py_ssize_t inl = nl - text;\n        if (inl >= offset) {\n            break;\n        }\n        inl += 1;\n        text += inl;\n        len -= inl;\n        offset -= (int)inl;\n    }\n\n    /* Print text */\n    if (PyFile_WriteString(\"    \", f) < 0) {\n        return -1;\n    }\n    if (PyFile_WriteString(text, f) < 0) {\n        return -1;\n    }\n\n    /* Make sure there's a newline at the end */\n    if (text[len] != '\\n') {\n        if (PyFile_WriteString(\"\\n\", f) < 0) {\n            return -1;\n        }\n    }\n\n    /* Don't print caret if it points to the left of the text */\n    if (offset < 0) {\n        return 0;\n    }\n\n    /* Write caret line */\n    if (PyFile_WriteString(\"    \", f) < 0) {\n        return -1;\n    }\n    while (--offset >= 0) {\n        if (PyFile_WriteString(\" \", f) < 0) {\n            return -1;\n        }\n    }\n    for (size_t caret_iter=0; caret_iter < caret_repetitions ; caret_iter++) {\n        if (PyFile_WriteString(\"^\", f) < 0) {\n            return -1;\n        }\n    }\n    if (PyFile_WriteString(\"\\n\", f) < 0) {\n        return -1;\n    }\n    return 0;\n}\n\n\nint\n_Py_HandleSystemExit(int *exitcode_p)\n{\n    int inspect = _Py_GetConfig()->inspect;\n    if (inspect) {\n        /* Don't exit if -i flag was given. This flag is set to 0\n         * when entering interactive mode for inspecting. */\n        return 0;\n    }\n\n    if (!PyErr_ExceptionMatches(PyExc_SystemExit)) {\n        return 0;\n    }\n\n    fflush(stdout);\n\n    int exitcode = 0;\n\n    PyObject *exc = PyErr_GetRaisedException();\n    if (exc == NULL) {\n        goto done;\n    }\n    assert(PyExceptionInstance_Check(exc));\n\n    /* The error code should be in the `code' attribute. */\n    PyObject *code = PyObject_GetAttr(exc, &_Py_ID(code));\n    if (code) {\n        Py_SETREF(exc, code);\n        if (exc == Py_None) {\n            goto done;\n        }\n    }\n    /* If we failed to dig out the 'code' attribute,\n     * just let the else clause below print the error.\n     */\n\n    if (PyLong_Check(exc)) {\n        exitcode = (int)PyLong_AsLong(exc);\n    }\n    else {\n        PyThreadState *tstate = _PyThreadState_GET();\n        PyObject *sys_stderr = _PySys_GetAttr(tstate, &_Py_ID(stderr));\n        /* We clear the exception here to avoid triggering the assertion\n         * in PyObject_Str that ensures it won't silently lose exception\n         * details.\n         */\n        PyErr_Clear();\n        if (sys_stderr != NULL && sys_stderr != Py_None) {\n            PyFile_WriteObject(exc, sys_stderr, Py_PRINT_RAW);\n        } else {\n            PyObject_Print(exc, stderr, Py_PRINT_RAW);\n            fflush(stderr);\n        }\n        PySys_WriteStderr(\"\\n\");\n        exitcode = 1;\n    }\n\ndone:\n    Py_CLEAR(exc);\n    *exitcode_p = exitcode;\n    return 1;\n}\n\n\nstatic void\nhandle_system_exit(void)\n{\n    int exitcode;\n    if (_Py_HandleSystemExit(&exitcode)) {\n        Py_Exit(exitcode);\n    }\n}\n\n\nstatic void\n_PyErr_PrintEx(PyThreadState *tstate, int set_sys_last_vars)\n{\n    PyObject *typ = NULL, *tb = NULL;\n    handle_system_exit();\n\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    if (exc == NULL) {\n        goto done;\n    }\n    assert(PyExceptionInstance_Check(exc));\n    typ = Py_NewRef(Py_TYPE(exc));\n    tb = PyException_GetTraceback(exc);\n    if (tb == NULL) {\n        tb = Py_NewRef(Py_None);\n    }\n\n    if (set_sys_last_vars) {\n        if (_PySys_SetAttr(&_Py_ID(last_exc), exc) < 0) {\n            _PyErr_Clear(tstate);\n        }\n        /* Legacy version: */\n        if (_PySys_SetAttr(&_Py_ID(last_type), typ) < 0) {\n            _PyErr_Clear(tstate);\n        }\n        if (_PySys_SetAttr(&_Py_ID(last_value), exc) < 0) {\n            _PyErr_Clear(tstate);\n        }\n        if (_PySys_SetAttr(&_Py_ID(last_traceback), tb) < 0) {\n            _PyErr_Clear(tstate);\n        }\n    }\n    PyObject *hook = _PySys_GetAttr(tstate, &_Py_ID(excepthook));\n    if (_PySys_Audit(tstate, \"sys.excepthook\", \"OOOO\", hook ? hook : Py_None,\n                     typ, exc, tb) < 0) {\n        if (PyErr_ExceptionMatches(PyExc_RuntimeError)) {\n            PyErr_Clear();\n            goto done;\n        }\n        _PyErr_WriteUnraisableMsg(\"in audit hook\", NULL);\n    }\n    if (hook) {\n        PyObject* stack[3];\n        stack[0] = typ;\n        stack[1] = exc;\n        stack[2] = tb;\n        PyObject *result = _PyObject_FastCall(hook, stack, 3);\n        if (result == NULL) {\n            handle_system_exit();\n\n            PyObject *exc2 = _PyErr_GetRaisedException(tstate);\n            assert(exc2 && PyExceptionInstance_Check(exc2));\n            fflush(stdout);\n            PySys_WriteStderr(\"Error in sys.excepthook:\\n\");\n            PyErr_DisplayException(exc2);\n            PySys_WriteStderr(\"\\nOriginal exception was:\\n\");\n            PyErr_DisplayException(exc);\n            Py_DECREF(exc2);\n        }\n        else {\n            Py_DECREF(result);\n        }\n    }\n    else {\n        PySys_WriteStderr(\"sys.excepthook is missing\\n\");\n        PyErr_DisplayException(exc);\n    }\n\ndone:\n    Py_XDECREF(typ);\n    Py_XDECREF(exc);\n    Py_XDECREF(tb);\n}\n\nvoid\n_PyErr_Print(PyThreadState *tstate)\n{\n    _PyErr_PrintEx(tstate, 1);\n}\n\nvoid\nPyErr_PrintEx(int set_sys_last_vars)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyErr_PrintEx(tstate, set_sys_last_vars);\n}\n\nvoid\nPyErr_Print(void)\n{\n    PyErr_PrintEx(1);\n}\n\nstruct exception_print_context\n{\n    PyObject *file;\n    PyObject *seen;            // Prevent cycles in recursion\n    int exception_group_depth; // nesting level of current exception group\n    bool need_close;           // Need a closing bottom frame\n    int max_group_width;       // Maximum number of children of each EG\n    int max_group_depth;       // Maximum nesting level of EGs\n};\n\n#define EXC_MARGIN(ctx) ((ctx)->exception_group_depth ? \"| \" : \"\")\n#define EXC_INDENT(ctx) (2 * (ctx)->exception_group_depth)\n\nstatic int\nwrite_indented_margin(struct exception_print_context *ctx, PyObject *f)\n{\n    return _Py_WriteIndentedMargin(EXC_INDENT(ctx), EXC_MARGIN(ctx), f);\n}\n\nstatic int\nprint_exception_invalid_type(struct exception_print_context *ctx,\n                             PyObject *value)\n{\n    PyObject *f = ctx->file;\n    if (_Py_WriteIndent(EXC_INDENT(ctx), f) < 0) {\n        return -1;\n    }\n    const char *const msg = \"TypeError: print_exception(): Exception expected \"\n                            \"for value, \";\n    if (PyFile_WriteString(msg, f) < 0) {\n        return -1;\n    }\n    if (PyFile_WriteString(Py_TYPE(value)->tp_name, f) < 0) {\n        return -1;\n    }\n    if (PyFile_WriteString(\" found\\n\", f) < 0) {\n        return -1;\n    }\n    return 0;\n}\n\nstatic int\nprint_exception_traceback(struct exception_print_context *ctx, PyObject *value)\n{\n    PyObject *f = ctx->file;\n    int err = 0;\n\n    PyObject *tb = PyException_GetTraceback(value);\n    if (tb && tb != Py_None) {\n        const char *header = EXCEPTION_TB_HEADER;\n        const char *header_margin = EXC_MARGIN(ctx);\n        if (_PyBaseExceptionGroup_Check(value)) {\n            header = EXCEPTION_GROUP_TB_HEADER;\n            if (ctx->exception_group_depth == 1) {\n                header_margin = \"+ \";\n            }\n        }\n        err = _PyTraceBack_Print_Indented(\n            tb, EXC_INDENT(ctx), EXC_MARGIN(ctx), header_margin, header, f);\n    }\n    Py_XDECREF(tb);\n    return err;\n}\n\nstatic int\nprint_exception_file_and_line(struct exception_print_context *ctx,\n                              PyObject **value_p)\n{\n    PyObject *f = ctx->file;\n\n    PyObject *tmp;\n    int res = _PyObject_LookupAttr(*value_p, &_Py_ID(print_file_and_line), &tmp);\n    if (res <= 0) {\n        if (res < 0) {\n            PyErr_Clear();\n        }\n        return 0;\n    }\n    Py_DECREF(tmp);\n\n    PyObject *message, *filename, *text;\n    Py_ssize_t lineno, offset, end_lineno, end_offset;\n    if (!parse_syntax_error(*value_p, &message, &filename,\n                            &lineno, &offset,\n                            &end_lineno, &end_offset, &text)) {\n        PyErr_Clear();\n        return 0;\n    }\n\n    Py_SETREF(*value_p, message);\n\n    PyObject *line = PyUnicode_FromFormat(\"  File \\\"%S\\\", line %zd\\n\",\n                                          filename, lineno);\n    Py_DECREF(filename);\n    if (line == NULL) {\n        goto error;\n    }\n    if (write_indented_margin(ctx, f) < 0) {\n        goto error;\n    }\n    if (PyFile_WriteObject(line, f, Py_PRINT_RAW) < 0) {\n        goto error;\n    }\n    Py_CLEAR(line);\n\n    if (text != NULL) {\n        Py_ssize_t line_size;\n        const char *error_line = PyUnicode_AsUTF8AndSize(text, &line_size);\n        // If the location of the error spawn multiple lines, we want\n        // to just print the first one and highlight everything until\n        // the end of that one since we don't support multi-line error\n        // messages.\n        if (end_lineno > lineno) {\n            end_offset = (error_line != NULL) ? line_size : -1;\n        }\n        // Limit the amount of '^' that we can display to\n        // the size of the text in the source line.\n        if (error_line != NULL && end_offset > line_size + 1) {\n            end_offset = line_size + 1;\n        }\n        if (print_error_text(f, offset, end_offset, text) < 0) {\n            goto error;\n        }\n        Py_DECREF(text);\n    }\n    assert(!PyErr_Occurred());\n    return 0;\n\nerror:\n    Py_XDECREF(line);\n    Py_XDECREF(text);\n    return -1;\n}\n\n/* Prints the message line: module.qualname[: str(exc)] */\nstatic int\nprint_exception_message(struct exception_print_context *ctx, PyObject *type,\n                        PyObject *value)\n{\n    PyObject *f = ctx->file;\n\n    assert(PyExceptionClass_Check(type));\n\n    if (write_indented_margin(ctx, f) < 0) {\n        return -1;\n    }\n    PyObject *modulename = PyObject_GetAttr(type, &_Py_ID(__module__));\n    if (modulename == NULL || !PyUnicode_Check(modulename)) {\n        Py_XDECREF(modulename);\n        PyErr_Clear();\n        if (PyFile_WriteString(\"<unknown>.\", f) < 0) {\n            return -1;\n        }\n    }\n    else {\n        if (!_PyUnicode_Equal(modulename, &_Py_ID(builtins)) &&\n            !_PyUnicode_Equal(modulename, &_Py_ID(__main__)))\n        {\n            int res = PyFile_WriteObject(modulename, f, Py_PRINT_RAW);\n            Py_DECREF(modulename);\n            if (res < 0) {\n                return -1;\n            }\n            if (PyFile_WriteString(\".\", f) < 0) {\n                return -1;\n            }\n        }\n        else {\n            Py_DECREF(modulename);\n        }\n    }\n\n    PyObject *qualname = PyType_GetQualName((PyTypeObject *)type);\n    if (qualname == NULL || !PyUnicode_Check(qualname)) {\n        Py_XDECREF(qualname);\n        PyErr_Clear();\n        if (PyFile_WriteString(\"<unknown>\", f) < 0) {\n            return -1;\n        }\n    }\n    else {\n        int res = PyFile_WriteObject(qualname, f, Py_PRINT_RAW);\n        Py_DECREF(qualname);\n        if (res < 0) {\n            return -1;\n        }\n    }\n\n    if (Py_IsNone(value)) {\n        return 0;\n    }\n\n    PyObject *s = PyObject_Str(value);\n    if (s == NULL) {\n        PyErr_Clear();\n        if (PyFile_WriteString(\": <exception str() failed>\", f) < 0) {\n            return -1;\n        }\n    }\n    else {\n        /* only print colon if the str() of the\n           object is not the empty string\n        */\n        if (!PyUnicode_Check(s) || PyUnicode_GetLength(s) != 0) {\n            if (PyFile_WriteString(\": \", f) < 0) {\n                Py_DECREF(s);\n                return -1;\n            }\n        }\n        int res = PyFile_WriteObject(s, f, Py_PRINT_RAW);\n        Py_DECREF(s);\n        if (res < 0) {\n            return -1;\n        }\n    }\n\n    return 0;\n}\n\nstatic int\nprint_exception_suggestions(struct exception_print_context *ctx,\n                            PyObject *value)\n{\n    PyObject *f = ctx->file;\n    PyObject *suggestions = _Py_Offer_Suggestions(value);\n    if (suggestions) {\n        if (PyFile_WriteObject(suggestions, f, Py_PRINT_RAW) < 0) {\n            goto error;\n        }\n        Py_DECREF(suggestions);\n    }\n    else if (PyErr_Occurred()) {\n        PyErr_Clear();\n    }\n    return 0;\nerror:\n    Py_XDECREF(suggestions);\n    return -1;\n}\n\nstatic int\nprint_exception_notes(struct exception_print_context *ctx, PyObject *value)\n{\n    PyObject *f = ctx->file;\n\n    if (!PyExceptionInstance_Check(value)) {\n        return 0;\n    }\n\n    if (!PyObject_HasAttr(value, &_Py_ID(__notes__))) {\n        return 0;\n    }\n    PyObject *notes = PyObject_GetAttr(value, &_Py_ID(__notes__));\n    if (notes == NULL) {\n        return -1;\n    }\n    if (!PySequence_Check(notes) || PyUnicode_Check(notes) || PyBytes_Check(notes)) {\n        int res = 0;\n        if (write_indented_margin(ctx, f) < 0) {\n            res = -1;\n        }\n        PyObject *s = PyObject_Repr(notes);\n        if (s == NULL) {\n            PyErr_Clear();\n            res = PyFile_WriteString(\"<__notes__ repr() failed>\", f);\n        }\n        else {\n            res = PyFile_WriteObject(s, f, Py_PRINT_RAW);\n            Py_DECREF(s);\n        }\n        Py_DECREF(notes);\n        if (PyFile_WriteString(\"\\n\", f) < 0) {\n            res = -1;\n        }\n        return res;\n    }\n    Py_ssize_t num_notes = PySequence_Length(notes);\n    PyObject *lines = NULL;\n    for (Py_ssize_t ni = 0; ni < num_notes; ni++) {\n        PyObject *note = PySequence_GetItem(notes, ni);\n        PyObject *note_str = PyObject_Str(note);\n        Py_DECREF(note);\n\n        if (note_str == NULL) {\n            PyErr_Clear();\n            if (PyFile_WriteString(\"<note str() failed>\", f) < 0) {\n                goto error;\n            }\n        }\n        else {\n            lines = PyUnicode_Splitlines(note_str, 1);\n            Py_DECREF(note_str);\n\n            if (lines == NULL) {\n                goto error;\n            }\n\n            Py_ssize_t n = PyList_GET_SIZE(lines);\n            for (Py_ssize_t i = 0; i < n; i++) {\n                PyObject *line = PyList_GET_ITEM(lines, i);\n                assert(PyUnicode_Check(line));\n                if (write_indented_margin(ctx, f) < 0) {\n                    goto error;\n                }\n                if (PyFile_WriteObject(line, f, Py_PRINT_RAW) < 0) {\n                    goto error;\n                }\n            }\n            Py_CLEAR(lines);\n        }\n        if (PyFile_WriteString(\"\\n\", f) < 0) {\n            goto error;\n        }\n    }\n\n    Py_DECREF(notes);\n    return 0;\nerror:\n    Py_XDECREF(lines);\n    Py_DECREF(notes);\n    return -1;\n}\n\nstatic int\nprint_exception(struct exception_print_context *ctx, PyObject *value)\n{\n    PyObject *f = ctx->file;\n\n    if (!PyExceptionInstance_Check(value)) {\n        return print_exception_invalid_type(ctx, value);\n    }\n\n    Py_INCREF(value);\n    fflush(stdout);\n\n    if (print_exception_traceback(ctx, value) < 0) {\n        goto error;\n    }\n\n    /* grab the type now because value can change below */\n    PyObject *type = (PyObject *) Py_TYPE(value);\n\n    if (print_exception_file_and_line(ctx, &value) < 0) {\n        goto error;\n    }\n    if (print_exception_message(ctx, type, value) < 0) {\n        goto error;\n    }\n    if (print_exception_suggestions(ctx, value) < 0) {\n        goto error;\n    }\n    if (PyFile_WriteString(\"\\n\", f) < 0) {\n        goto error;\n    }\n    if (print_exception_notes(ctx, value) < 0) {\n        goto error;\n    }\n\n    Py_DECREF(value);\n    assert(!PyErr_Occurred());\n    return 0;\nerror:\n    Py_DECREF(value);\n    return -1;\n}\n\nstatic const char cause_message[] =\n    \"The above exception was the direct cause \"\n    \"of the following exception:\\n\";\n\nstatic const char context_message[] =\n    \"During handling of the above exception, \"\n    \"another exception occurred:\\n\";\n\nstatic int\nprint_exception_recursive(struct exception_print_context*, PyObject*);\n\nstatic int\nprint_chained(struct exception_print_context* ctx, PyObject *value,\n              const char * message, const char *tag)\n{\n    PyObject *f = ctx->file;\n    if (_Py_EnterRecursiveCall(\" in print_chained\")) {\n        return -1;\n    }\n    bool need_close = ctx->need_close;\n    int res = print_exception_recursive(ctx, value);\n    ctx->need_close = need_close;\n    _Py_LeaveRecursiveCall();\n    if (res < 0) {\n        return -1;\n    }\n\n    if (write_indented_margin(ctx, f) < 0) {\n        return -1;\n    }\n    if (PyFile_WriteString(\"\\n\", f) < 0) {\n        return -1;\n    }\n    if (write_indented_margin(ctx, f) < 0) {\n        return -1;\n    }\n    if (PyFile_WriteString(message, f) < 0) {\n        return -1;\n    }\n    if (write_indented_margin(ctx, f) < 0) {\n        return -1;\n    }\n    if (PyFile_WriteString(\"\\n\", f) < 0) {\n        return -1;\n    }\n    return 0;\n}\n\n/* Return true if value is in seen or there was a lookup error.\n * Return false if lookup succeeded and the item was not found.\n * We suppress errors because this makes us err on the side of\n * under-printing which is better than over-printing irregular\n * exceptions (e.g., unhashable ones).\n */\nstatic bool\nprint_exception_seen_lookup(struct exception_print_context *ctx,\n                            PyObject *value)\n{\n    PyObject *check_id = PyLong_FromVoidPtr(value);\n    if (check_id == NULL) {\n        PyErr_Clear();\n        return true;\n    }\n\n    int in_seen = PySet_Contains(ctx->seen, check_id);\n    Py_DECREF(check_id);\n    if (in_seen == -1) {\n        PyErr_Clear();\n        return true;\n    }\n\n    if (in_seen == 1) {\n        /* value is in seen */\n        return true;\n    }\n    return false;\n}\n\nstatic int\nprint_exception_cause_and_context(struct exception_print_context *ctx,\n                                  PyObject *value)\n{\n    PyObject *value_id = PyLong_FromVoidPtr(value);\n    if (value_id == NULL || PySet_Add(ctx->seen, value_id) == -1) {\n        PyErr_Clear();\n        Py_XDECREF(value_id);\n        return 0;\n    }\n    Py_DECREF(value_id);\n\n    if (!PyExceptionInstance_Check(value)) {\n        return 0;\n    }\n\n    PyObject *cause = PyException_GetCause(value);\n    if (cause) {\n        int err = 0;\n        if (!print_exception_seen_lookup(ctx, cause)) {\n            err = print_chained(ctx, cause, cause_message, \"cause\");\n        }\n        Py_DECREF(cause);\n        return err;\n    }\n    if (((PyBaseExceptionObject *)value)->suppress_context) {\n        return 0;\n    }\n    PyObject *context = PyException_GetContext(value);\n    if (context) {\n        int err = 0;\n        if (!print_exception_seen_lookup(ctx, context)) {\n            err = print_chained(ctx, context, context_message, \"context\");\n        }\n        Py_DECREF(context);\n        return err;\n    }\n    return 0;\n}\n\nstatic int\nprint_exception_group(struct exception_print_context *ctx, PyObject *value)\n{\n    PyObject *f = ctx->file;\n\n    if (ctx->exception_group_depth > ctx->max_group_depth) {\n        /* depth exceeds limit */\n\n        if (write_indented_margin(ctx, f) < 0) {\n            return -1;\n        }\n\n        PyObject *line = PyUnicode_FromFormat(\"... (max_group_depth is %d)\\n\",\n                                              ctx->max_group_depth);\n        if (line == NULL) {\n            return -1;\n        }\n        int err = PyFile_WriteObject(line, f, Py_PRINT_RAW);\n        Py_DECREF(line);\n        return err;\n    }\n\n    if (ctx->exception_group_depth == 0) {\n        ctx->exception_group_depth += 1;\n    }\n    if (print_exception(ctx, value) < 0) {\n        return -1;\n    }\n\n    PyObject *excs = ((PyBaseExceptionGroupObject *)value)->excs;\n    assert(excs && PyTuple_Check(excs));\n    Py_ssize_t num_excs = PyTuple_GET_SIZE(excs);\n    assert(num_excs > 0);\n    Py_ssize_t n;\n    if (num_excs <= ctx->max_group_width) {\n        n = num_excs;\n    }\n    else {\n        n = ctx->max_group_width + 1;\n    }\n\n    ctx->need_close = false;\n    for (Py_ssize_t i = 0; i < n; i++) {\n        bool last_exc = (i == n - 1);\n        if (last_exc) {\n            // The closing frame may be added in a recursive call\n            ctx->need_close = true;\n        }\n\n        if (_Py_WriteIndent(EXC_INDENT(ctx), f) < 0) {\n            return -1;\n        }\n        bool truncated = (i >= ctx->max_group_width);\n        PyObject *line;\n        if (!truncated) {\n            line = PyUnicode_FromFormat(\n                \"%s+---------------- %zd ----------------\\n\",\n                (i == 0) ? \"+-\" : \"  \", i + 1);\n        }\n        else {\n            line = PyUnicode_FromFormat(\n                \"%s+---------------- ... ----------------\\n\",\n                (i == 0) ? \"+-\" : \"  \");\n        }\n        if (line == NULL) {\n            return -1;\n        }\n        int err = PyFile_WriteObject(line, f, Py_PRINT_RAW);\n        Py_DECREF(line);\n        if (err < 0) {\n            return -1;\n        }\n\n        ctx->exception_group_depth += 1;\n        PyObject *exc = PyTuple_GET_ITEM(excs, i);\n\n        if (!truncated) {\n            if (_Py_EnterRecursiveCall(\" in print_exception_group\")) {\n                return -1;\n            }\n            int res = print_exception_recursive(ctx, exc);\n            _Py_LeaveRecursiveCall();\n            if (res < 0) {\n                return -1;\n            }\n        }\n        else {\n            Py_ssize_t excs_remaining = num_excs - ctx->max_group_width;\n\n            if (write_indented_margin(ctx, f) < 0) {\n                return -1;\n            }\n\n            PyObject *line = PyUnicode_FromFormat(\n                \"and %zd more exception%s\\n\",\n                excs_remaining, excs_remaining > 1 ? \"s\" : \"\");\n\n            if (line == NULL) {\n                return -1;\n            }\n\n            int err = PyFile_WriteObject(line, f, Py_PRINT_RAW);\n            Py_DECREF(line);\n            if (err < 0) {\n                return -1;\n            }\n        }\n\n        if (last_exc && ctx->need_close) {\n            if (_Py_WriteIndent(EXC_INDENT(ctx), f) < 0) {\n                return -1;\n            }\n            if (PyFile_WriteString(\n                    \"+------------------------------------\\n\", f) < 0) {\n                return -1;\n            }\n            ctx->need_close = false;\n        }\n        ctx->exception_group_depth -= 1;\n    }\n\n    if (ctx->exception_group_depth == 1) {\n        ctx->exception_group_depth -= 1;\n    }\n    return 0;\n}\n\nstatic int\nprint_exception_recursive(struct exception_print_context *ctx, PyObject *value)\n{\n    if (_Py_EnterRecursiveCall(\" in print_exception_recursive\")) {\n        return -1;\n    }\n    if (ctx->seen != NULL) {\n        /* Exception chaining */\n        if (print_exception_cause_and_context(ctx, value) < 0) {\n            goto error;\n        }\n    }\n    if (!_PyBaseExceptionGroup_Check(value)) {\n        if (print_exception(ctx, value) < 0) {\n            goto error;\n        }\n    }\n    else if (print_exception_group(ctx, value) < 0) {\n        goto error;\n    }\n    assert(!PyErr_Occurred());\n\n    _Py_LeaveRecursiveCall();\n    return 0;\nerror:\n    _Py_LeaveRecursiveCall();\n    return -1;\n}\n\n#define PyErr_MAX_GROUP_WIDTH 15\n#define PyErr_MAX_GROUP_DEPTH 10\n\nvoid\n_PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb)\n{\n    assert(file != NULL && file != Py_None);\n    if (PyExceptionInstance_Check(value)\n        && tb != NULL && PyTraceBack_Check(tb)) {\n        /* Put the traceback on the exception, otherwise it won't get\n           displayed.  See issue #18776. */\n        PyObject *cur_tb = PyException_GetTraceback(value);\n        if (cur_tb == NULL) {\n            PyException_SetTraceback(value, tb);\n        }\n        else {\n            Py_DECREF(cur_tb);\n        }\n    }\n\n    struct exception_print_context ctx;\n    ctx.file = file;\n    ctx.exception_group_depth = 0;\n    ctx.need_close = false;\n    ctx.max_group_width = PyErr_MAX_GROUP_WIDTH;\n    ctx.max_group_depth = PyErr_MAX_GROUP_DEPTH;\n\n    /* We choose to ignore seen being possibly NULL, and report\n       at least the main exception (it could be a MemoryError).\n    */\n    ctx.seen = PySet_New(NULL);\n    if (ctx.seen == NULL) {\n        PyErr_Clear();\n    }\n    if (print_exception_recursive(&ctx, value) < 0) {\n        PyErr_Clear();\n        _PyObject_Dump(value);\n        fprintf(stderr, \"lost sys.stderr\\n\");\n    }\n    Py_XDECREF(ctx.seen);\n\n    /* Call file.flush() */\n    PyObject *res = _PyObject_CallMethodNoArgs(file, &_Py_ID(flush));\n    if (!res) {\n        /* Silently ignore file.flush() error */\n        PyErr_Clear();\n    }\n    else {\n        Py_DECREF(res);\n    }\n}\n\nvoid\nPyErr_Display(PyObject *unused, PyObject *value, PyObject *tb)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *file = _PySys_GetAttr(tstate, &_Py_ID(stderr));\n    if (file == NULL) {\n        _PyObject_Dump(value);\n        fprintf(stderr, \"lost sys.stderr\\n\");\n        return;\n    }\n    if (file == Py_None) {\n        return;\n    }\n    Py_INCREF(file);\n    _PyErr_Display(file, NULL, value, tb);\n    Py_DECREF(file);\n}\n\nvoid _PyErr_DisplayException(PyObject *file, PyObject *exc)\n{\n    _PyErr_Display(file, NULL, exc, NULL);\n}\n\nvoid PyErr_DisplayException(PyObject *exc)\n{\n    PyErr_Display(NULL, exc, NULL);\n}\n\nPyObject *\nPyRun_StringFlags(const char *str, int start, PyObject *globals,\n                  PyObject *locals, PyCompilerFlags *flags)\n{\n    PyObject *ret = NULL;\n    mod_ty mod;\n    PyArena *arena;\n\n    arena = _PyArena_New();\n    if (arena == NULL)\n        return NULL;\n\n    _Py_DECLARE_STR(anon_string, \"<string>\");\n    mod = _PyParser_ASTFromString(\n            str, &_Py_STR(anon_string), start, flags, arena);\n\n    if (mod != NULL)\n        ret = run_mod(mod, &_Py_STR(anon_string), globals, locals, flags, arena);\n    _PyArena_Free(arena);\n    return ret;\n}\n\n\nstatic PyObject *\npyrun_file(FILE *fp, PyObject *filename, int start, PyObject *globals,\n           PyObject *locals, int closeit, PyCompilerFlags *flags)\n{\n    PyArena *arena = _PyArena_New();\n    if (arena == NULL) {\n        return NULL;\n    }\n\n    mod_ty mod;\n    mod = _PyParser_ASTFromFile(fp, filename, NULL, start, NULL, NULL,\n                                flags, NULL, arena);\n\n    if (closeit) {\n        fclose(fp);\n    }\n\n    PyObject *ret;\n    if (mod != NULL) {\n        ret = run_mod(mod, filename, globals, locals, flags, arena);\n    }\n    else {\n        ret = NULL;\n    }\n    _PyArena_Free(arena);\n\n    return ret;\n}\n\n\nPyObject *\nPyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals,\n                  PyObject *locals, int closeit, PyCompilerFlags *flags)\n{\n    PyObject *filename_obj = PyUnicode_DecodeFSDefault(filename);\n    if (filename_obj == NULL) {\n        return NULL;\n    }\n\n    PyObject *res = pyrun_file(fp, filename_obj, start, globals,\n                               locals, closeit, flags);\n    Py_DECREF(filename_obj);\n    return res;\n\n}\n\nstatic void\nflush_io_stream(PyThreadState *tstate, PyObject *name)\n{\n    PyObject *f = _PySys_GetAttr(tstate, name);\n    if (f != NULL) {\n        PyObject *r = _PyObject_CallMethodNoArgs(f, &_Py_ID(flush));\n        if (r) {\n            Py_DECREF(r);\n        }\n        else {\n            PyErr_Clear();\n        }\n    }\n}\n\nstatic void\nflush_io(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    flush_io_stream(tstate, &_Py_ID(stderr));\n    flush_io_stream(tstate, &_Py_ID(stdout));\n    _PyErr_SetRaisedException(tstate, exc);\n}\n\nstatic PyObject *\nrun_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, PyObject *locals)\n{\n    PyObject *v;\n    /*\n     * We explicitly re-initialize _Py_UnhandledKeyboardInterrupt every eval\n     * _just in case_ someone is calling into an embedded Python where they\n     * don't care about an uncaught KeyboardInterrupt exception (why didn't they\n     * leave config.install_signal_handlers set to 0?!?) but then later call\n     * Py_Main() itself (which _checks_ this flag and dies with a signal after\n     * its interpreter exits).  We don't want a previous embedded interpreter's\n     * uncaught exception to trigger an unexplained signal exit from a future\n     * Py_Main() based one.\n     */\n    // XXX Isn't this dealt with by the move to _PyRuntimeState?\n    _PyRuntime.signals.unhandled_keyboard_interrupt = 0;\n\n    /* Set globals['__builtins__'] if it doesn't exist */\n    if (globals != NULL && _PyDict_GetItemStringWithError(globals, \"__builtins__\") == NULL) {\n        if (PyErr_Occurred() ||\n            PyDict_SetItemString(globals, \"__builtins__\",\n                                 tstate->interp->builtins) < 0)\n        {\n            return NULL;\n        }\n    }\n\n    v = PyEval_EvalCode((PyObject*)co, globals, locals);\n    if (!v && _PyErr_Occurred(tstate) == PyExc_KeyboardInterrupt) {\n        _PyRuntime.signals.unhandled_keyboard_interrupt = 1;\n    }\n    return v;\n}\n\nstatic PyObject *\nrun_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals,\n            PyCompilerFlags *flags, PyArena *arena)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyCodeObject *co = _PyAST_Compile(mod, filename, flags, -1, arena);\n    if (co == NULL)\n        return NULL;\n\n    if (_PySys_Audit(tstate, \"exec\", \"O\", co) < 0) {\n        Py_DECREF(co);\n        return NULL;\n    }\n\n    PyObject *v = run_eval_code_obj(tstate, co, globals, locals);\n    Py_DECREF(co);\n    return v;\n}\n\nstatic PyObject *\nrun_pyc_file(FILE *fp, PyObject *globals, PyObject *locals,\n             PyCompilerFlags *flags)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyCodeObject *co;\n    PyObject *v;\n    long magic;\n    long PyImport_GetMagicNumber(void);\n\n    magic = PyMarshal_ReadLongFromFile(fp);\n    if (magic != PyImport_GetMagicNumber()) {\n        if (!PyErr_Occurred())\n            PyErr_SetString(PyExc_RuntimeError,\n                       \"Bad magic number in .pyc file\");\n        goto error;\n    }\n    /* Skip the rest of the header. */\n    (void) PyMarshal_ReadLongFromFile(fp);\n    (void) PyMarshal_ReadLongFromFile(fp);\n    (void) PyMarshal_ReadLongFromFile(fp);\n    if (PyErr_Occurred()) {\n        goto error;\n    }\n    v = PyMarshal_ReadLastObjectFromFile(fp);\n    if (v == NULL || !PyCode_Check(v)) {\n        Py_XDECREF(v);\n        PyErr_SetString(PyExc_RuntimeError,\n                   \"Bad code object in .pyc file\");\n        goto error;\n    }\n    fclose(fp);\n    co = (PyCodeObject *)v;\n    v = run_eval_code_obj(tstate, co, globals, locals);\n    if (v && flags)\n        flags->cf_flags |= (co->co_flags & PyCF_MASK);\n    Py_DECREF(co);\n    return v;\nerror:\n    fclose(fp);\n    return NULL;\n}\n\nPyObject *\nPy_CompileStringObject(const char *str, PyObject *filename, int start,\n                       PyCompilerFlags *flags, int optimize)\n{\n    PyCodeObject *co;\n    mod_ty mod;\n    PyArena *arena = _PyArena_New();\n    if (arena == NULL)\n        return NULL;\n\n    mod = _PyParser_ASTFromString(str, filename, start, flags, arena);\n    if (mod == NULL) {\n        _PyArena_Free(arena);\n        return NULL;\n    }\n    if (flags && (flags->cf_flags & PyCF_ONLY_AST)) {\n        PyObject *result = PyAST_mod2obj(mod);\n        _PyArena_Free(arena);\n        return result;\n    }\n    co = _PyAST_Compile(mod, filename, flags, optimize, arena);\n    _PyArena_Free(arena);\n    return (PyObject *)co;\n}\n\nPyObject *\nPy_CompileStringExFlags(const char *str, const char *filename_str, int start,\n                        PyCompilerFlags *flags, int optimize)\n{\n    PyObject *filename, *co;\n    filename = PyUnicode_DecodeFSDefault(filename_str);\n    if (filename == NULL)\n        return NULL;\n    co = Py_CompileStringObject(str, filename, start, flags, optimize);\n    Py_DECREF(filename);\n    return co;\n}\n\nconst char *\n_Py_SourceAsString(PyObject *cmd, const char *funcname, const char *what, PyCompilerFlags *cf, PyObject **cmd_copy)\n{\n    const char *str;\n    Py_ssize_t size;\n    Py_buffer view;\n\n    *cmd_copy = NULL;\n    if (PyUnicode_Check(cmd)) {\n        cf->cf_flags |= PyCF_IGNORE_COOKIE;\n        str = PyUnicode_AsUTF8AndSize(cmd, &size);\n        if (str == NULL)\n            return NULL;\n    }\n    else if (PyBytes_Check(cmd)) {\n        str = PyBytes_AS_STRING(cmd);\n        size = PyBytes_GET_SIZE(cmd);\n    }\n    else if (PyByteArray_Check(cmd)) {\n        str = PyByteArray_AS_STRING(cmd);\n        size = PyByteArray_GET_SIZE(cmd);\n    }\n    else if (PyObject_GetBuffer(cmd, &view, PyBUF_SIMPLE) == 0) {\n        /* Copy to NUL-terminated buffer. */\n        *cmd_copy = PyBytes_FromStringAndSize(\n            (const char *)view.buf, view.len);\n        PyBuffer_Release(&view);\n        if (*cmd_copy == NULL) {\n            return NULL;\n        }\n        str = PyBytes_AS_STRING(*cmd_copy);\n        size = PyBytes_GET_SIZE(*cmd_copy);\n    }\n    else {\n        PyErr_Format(PyExc_TypeError,\n            \"%s() arg 1 must be a %s object\",\n            funcname, what);\n        return NULL;\n    }\n\n    if (strlen(str) != (size_t)size) {\n        PyErr_SetString(PyExc_SyntaxError,\n            \"source code string cannot contain null bytes\");\n        Py_CLEAR(*cmd_copy);\n        return NULL;\n    }\n    return str;\n}\n\n#if defined(USE_STACKCHECK)\n#if defined(WIN32) && defined(_MSC_VER)\n\n/* Stack checking for Microsoft C */\n\n#include <malloc.h>\n#include <excpt.h>\n\n/*\n * Return non-zero when we run out of memory on the stack; zero otherwise.\n */\nint\nPyOS_CheckStack(void)\n{\n    __try {\n        /* alloca throws a stack overflow exception if there's\n           not enough space left on the stack */\n        alloca(PYOS_STACK_MARGIN * sizeof(void*));\n        return 0;\n    } __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ?\n                    EXCEPTION_EXECUTE_HANDLER :\n            EXCEPTION_CONTINUE_SEARCH) {\n        int errcode = _resetstkoflw();\n        if (errcode == 0)\n        {\n            Py_FatalError(\"Could not reset the stack!\");\n        }\n    }\n    return 1;\n}\n\n#endif /* WIN32 && _MSC_VER */\n\n/* Alternate implementations can be added here... */\n\n#endif /* USE_STACKCHECK */\n\n/* Deprecated C API functions still provided for binary compatibility */\n\n#undef PyRun_AnyFile\nPyAPI_FUNC(int)\nPyRun_AnyFile(FILE *fp, const char *name)\n{\n    return PyRun_AnyFileExFlags(fp, name, 0, NULL);\n}\n\n#undef PyRun_AnyFileEx\nPyAPI_FUNC(int)\nPyRun_AnyFileEx(FILE *fp, const char *name, int closeit)\n{\n    return PyRun_AnyFileExFlags(fp, name, closeit, NULL);\n}\n\n#undef PyRun_AnyFileFlags\nPyAPI_FUNC(int)\nPyRun_AnyFileFlags(FILE *fp, const char *name, PyCompilerFlags *flags)\n{\n    return PyRun_AnyFileExFlags(fp, name, 0, flags);\n}\n\n#undef PyRun_File\nPyAPI_FUNC(PyObject *)\nPyRun_File(FILE *fp, const char *p, int s, PyObject *g, PyObject *l)\n{\n    return PyRun_FileExFlags(fp, p, s, g, l, 0, NULL);\n}\n\n#undef PyRun_FileEx\nPyAPI_FUNC(PyObject *)\nPyRun_FileEx(FILE *fp, const char *p, int s, PyObject *g, PyObject *l, int c)\n{\n    return PyRun_FileExFlags(fp, p, s, g, l, c, NULL);\n}\n\n#undef PyRun_FileFlags\nPyAPI_FUNC(PyObject *)\nPyRun_FileFlags(FILE *fp, const char *p, int s, PyObject *g, PyObject *l,\n                PyCompilerFlags *flags)\n{\n    return PyRun_FileExFlags(fp, p, s, g, l, 0, flags);\n}\n\n#undef PyRun_SimpleFile\nPyAPI_FUNC(int)\nPyRun_SimpleFile(FILE *f, const char *p)\n{\n    return PyRun_SimpleFileExFlags(f, p, 0, NULL);\n}\n\n#undef PyRun_SimpleFileEx\nPyAPI_FUNC(int)\nPyRun_SimpleFileEx(FILE *f, const char *p, int c)\n{\n    return PyRun_SimpleFileExFlags(f, p, c, NULL);\n}\n\n\n#undef PyRun_String\nPyAPI_FUNC(PyObject *)\nPyRun_String(const char *str, int s, PyObject *g, PyObject *l)\n{\n    return PyRun_StringFlags(str, s, g, l, NULL);\n}\n\n#undef PyRun_SimpleString\nPyAPI_FUNC(int)\nPyRun_SimpleString(const char *s)\n{\n    return PyRun_SimpleStringFlags(s, NULL);\n}\n\n#undef Py_CompileString\nPyAPI_FUNC(PyObject *)\nPy_CompileString(const char *str, const char *p, int s)\n{\n    return Py_CompileStringExFlags(str, p, s, NULL, -1);\n}\n\n#undef Py_CompileStringFlags\nPyAPI_FUNC(PyObject *)\nPy_CompileStringFlags(const char *str, const char *p, int s,\n                      PyCompilerFlags *flags)\n{\n    return Py_CompileStringExFlags(str, p, s, flags, -1);\n}\n\n#undef PyRun_InteractiveOne\nPyAPI_FUNC(int)\nPyRun_InteractiveOne(FILE *f, const char *p)\n{\n    return PyRun_InteractiveOneFlags(f, p, NULL);\n}\n\n#undef PyRun_InteractiveLoop\nPyAPI_FUNC(int)\nPyRun_InteractiveLoop(FILE *f, const char *p)\n{\n    return PyRun_InteractiveLoopFlags(f, p, NULL);\n}\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "Specialize.c",
    "content": "#include \"Python.h\"\n#include \"pycore_code.h\"\n#include \"pycore_dict.h\"\n#include \"pycore_function.h\"      // _PyFunction_GetVersionForCurrentState()\n#include \"pycore_global_strings.h\"  // _Py_ID()\n#include \"pycore_long.h\"\n#include \"pycore_moduleobject.h\"\n#include \"pycore_object.h\"\n#include \"pycore_opcode.h\"        // _PyOpcode_Caches\n#include \"structmember.h\"         // struct PyMemberDef, T_OFFSET_EX\n#include \"pycore_descrobject.h\"\n\n#include <stdlib.h> // rand()\n\n/* For guidance on adding or extending families of instructions see\n * ./adaptive.md\n */\n\n#ifdef Py_STATS\nPyStats _py_stats_struct = { 0 };\nPyStats *_py_stats = NULL;\n\n#define ADD_STAT_TO_DICT(res, field) \\\n    do { \\\n        PyObject *val = PyLong_FromUnsignedLongLong(stats->field); \\\n        if (val == NULL) { \\\n            Py_DECREF(res); \\\n            return NULL; \\\n        } \\\n        if (PyDict_SetItemString(res, #field, val) == -1) { \\\n            Py_DECREF(res); \\\n            Py_DECREF(val); \\\n            return NULL; \\\n        } \\\n        Py_DECREF(val); \\\n    } while(0);\n\nstatic PyObject*\nstats_to_dict(SpecializationStats *stats)\n{\n    PyObject *res = PyDict_New();\n    if (res == NULL) {\n        return NULL;\n    }\n    ADD_STAT_TO_DICT(res, success);\n    ADD_STAT_TO_DICT(res, failure);\n    ADD_STAT_TO_DICT(res, hit);\n    ADD_STAT_TO_DICT(res, deferred);\n    ADD_STAT_TO_DICT(res, miss);\n    ADD_STAT_TO_DICT(res, deopt);\n    PyObject *failure_kinds = PyTuple_New(SPECIALIZATION_FAILURE_KINDS);\n    if (failure_kinds == NULL) {\n        Py_DECREF(res);\n        return NULL;\n    }\n    for (int i = 0; i < SPECIALIZATION_FAILURE_KINDS; i++) {\n        PyObject *stat = PyLong_FromUnsignedLongLong(stats->failure_kinds[i]);\n        if (stat == NULL) {\n            Py_DECREF(res);\n            Py_DECREF(failure_kinds);\n            return NULL;\n        }\n        PyTuple_SET_ITEM(failure_kinds, i, stat);\n    }\n    if (PyDict_SetItemString(res, \"failure_kinds\", failure_kinds)) {\n        Py_DECREF(res);\n        Py_DECREF(failure_kinds);\n        return NULL;\n    }\n    Py_DECREF(failure_kinds);\n    return res;\n}\n#undef ADD_STAT_TO_DICT\n\nstatic int\nadd_stat_dict(\n    PyObject *res,\n    int opcode,\n    const char *name) {\n\n    SpecializationStats *stats = &_py_stats_struct.opcode_stats[opcode].specialization;\n    PyObject *d = stats_to_dict(stats);\n    if (d == NULL) {\n        return -1;\n    }\n    int err = PyDict_SetItemString(res, name, d);\n    Py_DECREF(d);\n    return err;\n}\n\n#ifdef Py_STATS\nPyObject*\n_Py_GetSpecializationStats(void) {\n    PyObject *stats = PyDict_New();\n    if (stats == NULL) {\n        return NULL;\n    }\n    int err = 0;\n    err += add_stat_dict(stats, LOAD_SUPER_ATTR, \"load_super_attr\");\n    err += add_stat_dict(stats, LOAD_ATTR, \"load_attr\");\n    err += add_stat_dict(stats, LOAD_GLOBAL, \"load_global\");\n    err += add_stat_dict(stats, BINARY_SUBSCR, \"binary_subscr\");\n    err += add_stat_dict(stats, STORE_SUBSCR, \"store_subscr\");\n    err += add_stat_dict(stats, STORE_ATTR, \"store_attr\");\n    err += add_stat_dict(stats, CALL, \"call\");\n    err += add_stat_dict(stats, BINARY_OP, \"binary_op\");\n    err += add_stat_dict(stats, COMPARE_OP, \"compare_op\");\n    err += add_stat_dict(stats, UNPACK_SEQUENCE, \"unpack_sequence\");\n    err += add_stat_dict(stats, FOR_ITER, \"for_iter\");\n    if (err < 0) {\n        Py_DECREF(stats);\n        return NULL;\n    }\n    return stats;\n}\n#endif\n\n\n#define PRINT_STAT(i, field) \\\n    if (stats[i].field) { \\\n        fprintf(out, \"    opcode[%d].\" #field \" : %\" PRIu64 \"\\n\", i, stats[i].field); \\\n    }\n\nstatic void\nprint_spec_stats(FILE *out, OpcodeStats *stats)\n{\n    /* Mark some opcodes as specializable for stats,\n     * even though we don't specialize them yet. */\n    fprintf(out, \"opcode[%d].specializable : 1\\n\", BINARY_SLICE);\n    fprintf(out, \"opcode[%d].specializable : 1\\n\", COMPARE_OP);\n    fprintf(out, \"opcode[%d].specializable : 1\\n\", STORE_SLICE);\n    fprintf(out, \"opcode[%d].specializable : 1\\n\", SEND);\n    for (int i = 0; i < 256; i++) {\n        if (_PyOpcode_Caches[i]) {\n            fprintf(out, \"opcode[%d].specializable : 1\\n\", i);\n        }\n        PRINT_STAT(i, specialization.success);\n        PRINT_STAT(i, specialization.failure);\n        PRINT_STAT(i, specialization.hit);\n        PRINT_STAT(i, specialization.deferred);\n        PRINT_STAT(i, specialization.miss);\n        PRINT_STAT(i, specialization.deopt);\n        PRINT_STAT(i, execution_count);\n        for (int j = 0; j < SPECIALIZATION_FAILURE_KINDS; j++) {\n            uint64_t val = stats[i].specialization.failure_kinds[j];\n            if (val) {\n                fprintf(out, \"    opcode[%d].specialization.failure_kinds[%d] : %\"\n                    PRIu64 \"\\n\", i, j, val);\n            }\n        }\n        for (int j = 0; j < 256; j++) {\n            if (stats[i].pair_count[j]) {\n                fprintf(out, \"opcode[%d].pair_count[%d] : %\" PRIu64 \"\\n\",\n                        i, j, stats[i].pair_count[j]);\n            }\n        }\n    }\n}\n#undef PRINT_STAT\n\n\nstatic void\nprint_call_stats(FILE *out, CallStats *stats)\n{\n    fprintf(out, \"Calls to PyEval_EvalDefault: %\" PRIu64 \"\\n\", stats->pyeval_calls);\n    fprintf(out, \"Calls to Python functions inlined: %\" PRIu64 \"\\n\", stats->inlined_py_calls);\n    fprintf(out, \"Frames pushed: %\" PRIu64 \"\\n\", stats->frames_pushed);\n    fprintf(out, \"Frame objects created: %\" PRIu64 \"\\n\", stats->frame_objects_created);\n    for (int i = 0; i < EVAL_CALL_KINDS; i++) {\n        fprintf(out, \"Calls via PyEval_EvalFrame[%d] : %\" PRIu64 \"\\n\", i, stats->eval_calls[i]);\n    }\n}\n\nstatic void\nprint_object_stats(FILE *out, ObjectStats *stats)\n{\n    fprintf(out, \"Object allocations from freelist: %\" PRIu64 \"\\n\", stats->from_freelist);\n    fprintf(out, \"Object frees to freelist: %\" PRIu64 \"\\n\", stats->to_freelist);\n    fprintf(out, \"Object allocations: %\" PRIu64 \"\\n\", stats->allocations);\n    fprintf(out, \"Object allocations to 512 bytes: %\" PRIu64 \"\\n\", stats->allocations512);\n    fprintf(out, \"Object allocations to 4 kbytes: %\" PRIu64 \"\\n\", stats->allocations4k);\n    fprintf(out, \"Object allocations over 4 kbytes: %\" PRIu64 \"\\n\", stats->allocations_big);\n    fprintf(out, \"Object frees: %\" PRIu64 \"\\n\", stats->frees);\n    fprintf(out, \"Object new values: %\" PRIu64 \"\\n\", stats->new_values);\n    fprintf(out, \"Object interpreter increfs: %\" PRIu64 \"\\n\", stats->interpreter_increfs);\n    fprintf(out, \"Object interpreter decrefs: %\" PRIu64 \"\\n\", stats->interpreter_decrefs);\n    fprintf(out, \"Object increfs: %\" PRIu64 \"\\n\", stats->increfs);\n    fprintf(out, \"Object decrefs: %\" PRIu64 \"\\n\", stats->decrefs);\n    fprintf(out, \"Object materialize dict (on request): %\" PRIu64 \"\\n\", stats->dict_materialized_on_request);\n    fprintf(out, \"Object materialize dict (new key): %\" PRIu64 \"\\n\", stats->dict_materialized_new_key);\n    fprintf(out, \"Object materialize dict (too big): %\" PRIu64 \"\\n\", stats->dict_materialized_too_big);\n    fprintf(out, \"Object materialize dict (str subclass): %\" PRIu64 \"\\n\", stats->dict_materialized_str_subclass);\n    fprintf(out, \"Object method cache hits: %\" PRIu64 \"\\n\", stats->type_cache_hits);\n    fprintf(out, \"Object method cache misses: %\" PRIu64 \"\\n\", stats->type_cache_misses);\n    fprintf(out, \"Object method cache collisions: %\" PRIu64 \"\\n\", stats->type_cache_collisions);\n    fprintf(out, \"Object method cache dunder hits: %\" PRIu64 \"\\n\", stats->type_cache_dunder_hits);\n    fprintf(out, \"Object method cache dunder misses: %\" PRIu64 \"\\n\", stats->type_cache_dunder_misses);\n}\n\nstatic void\nprint_stats(FILE *out, PyStats *stats) {\n    print_spec_stats(out, stats->opcode_stats);\n    print_call_stats(out, &stats->call_stats);\n    print_object_stats(out, &stats->object_stats);\n}\n\nvoid\n_Py_StatsClear(void)\n{\n    _py_stats_struct = (PyStats) { 0 };\n}\n\nvoid\n_Py_PrintSpecializationStats(int to_file)\n{\n    FILE *out = stderr;\n    if (to_file) {\n        /* Write to a file instead of stderr. */\n# ifdef MS_WINDOWS\n        const char *dirname = \"c:\\\\temp\\\\py_stats\\\\\";\n# else\n        const char *dirname = \"/tmp/py_stats/\";\n# endif\n        /* Use random 160 bit number as file name,\n        * to avoid both accidental collisions and\n        * symlink attacks. */\n        unsigned char rand[20];\n        char hex_name[41];\n        _PyOS_URandomNonblock(rand, 20);\n        for (int i = 0; i < 20; i++) {\n            hex_name[2*i] = \"0123456789abcdef\"[rand[i]&15];\n            hex_name[2*i+1] = \"0123456789abcdef\"[(rand[i]>>4)&15];\n        }\n        hex_name[40] = '\\0';\n        char buf[64];\n        assert(strlen(dirname) + 40 + strlen(\".txt\") < 64);\n        sprintf(buf, \"%s%s.txt\", dirname, hex_name);\n        FILE *fout = fopen(buf, \"w\");\n        if (fout) {\n            out = fout;\n        }\n    }\n    else {\n        fprintf(out, \"Specialization stats:\\n\");\n    }\n    print_stats(out, &_py_stats_struct);\n    if (out != stderr) {\n        fclose(out);\n    }\n}\n\n#ifdef Py_STATS\n\n#define SPECIALIZATION_FAIL(opcode, kind) \\\ndo { \\\n    if (_py_stats) { \\\n        _py_stats->opcode_stats[opcode].specialization.failure_kinds[kind]++; \\\n    } \\\n} while (0)\n\n#endif\n#endif\n\n#ifndef SPECIALIZATION_FAIL\n#define SPECIALIZATION_FAIL(opcode, kind) ((void)0)\n#endif\n\n// Initialize warmup counters and insert superinstructions. This cannot fail.\nvoid\n_PyCode_Quicken(PyCodeObject *code)\n{\n    #if ENABLE_SPECIALIZATION\n    int opcode = 0;\n    _Py_CODEUNIT *instructions = _PyCode_CODE(code);\n    for (int i = 0; i < Py_SIZE(code); i++) {\n        int previous_opcode = opcode;\n        opcode = _Py_GetBaseOpcode(code, i);\n        assert(opcode < MIN_INSTRUMENTED_OPCODE);\n        int caches = _PyOpcode_Caches[opcode];\n        if (caches) {\n            instructions[i + 1].cache = adaptive_counter_warmup();\n            i += caches;\n            continue;\n        }\n        switch (previous_opcode << 8 | opcode) {\n            case LOAD_CONST << 8 | LOAD_FAST:\n                instructions[i - 1].op.code = LOAD_CONST__LOAD_FAST;\n                break;\n            case LOAD_FAST << 8 | LOAD_CONST:\n                instructions[i - 1].op.code = LOAD_FAST__LOAD_CONST;\n                break;\n            case LOAD_FAST << 8 | LOAD_FAST:\n                instructions[i - 1].op.code = LOAD_FAST__LOAD_FAST;\n                break;\n            case STORE_FAST << 8 | LOAD_FAST:\n                instructions[i - 1].op.code = STORE_FAST__LOAD_FAST;\n                break;\n            case STORE_FAST << 8 | STORE_FAST:\n                instructions[i - 1].op.code = STORE_FAST__STORE_FAST;\n                break;\n        }\n    }\n    #endif /* ENABLE_SPECIALIZATION */\n}\n\n#define SIMPLE_FUNCTION 0\n\n/* Common */\n\n#define SPEC_FAIL_OTHER 0\n#define SPEC_FAIL_NO_DICT 1\n#define SPEC_FAIL_OVERRIDDEN 2\n#define SPEC_FAIL_OUT_OF_VERSIONS 3\n#define SPEC_FAIL_OUT_OF_RANGE 4\n#define SPEC_FAIL_EXPECTED_ERROR 5\n#define SPEC_FAIL_WRONG_NUMBER_ARGUMENTS 6\n#define SPEC_FAIL_CODE_COMPLEX_PARAMETERS 7\n#define SPEC_FAIL_CODE_NOT_OPTIMIZED 8\n\n\n#define SPEC_FAIL_LOAD_GLOBAL_NON_DICT 17\n#define SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT 18\n\n/* Super */\n\n#define SPEC_FAIL_SUPER_BAD_CLASS 9\n#define SPEC_FAIL_SUPER_SHADOWED 10\n\n/* Attributes */\n\n#define SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR 9\n#define SPEC_FAIL_ATTR_NON_OVERRIDING_DESCRIPTOR 10\n#define SPEC_FAIL_ATTR_NOT_DESCRIPTOR 11\n#define SPEC_FAIL_ATTR_METHOD 12\n#define SPEC_FAIL_ATTR_MUTABLE_CLASS 13\n#define SPEC_FAIL_ATTR_PROPERTY 14\n#define SPEC_FAIL_ATTR_NON_OBJECT_SLOT 15\n#define SPEC_FAIL_ATTR_READ_ONLY 16\n#define SPEC_FAIL_ATTR_AUDITED_SLOT 17\n#define SPEC_FAIL_ATTR_NOT_MANAGED_DICT 18\n#define SPEC_FAIL_ATTR_NON_STRING_OR_SPLIT 19\n#define SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND 20\n\n#define SPEC_FAIL_ATTR_SHADOWED 21\n#define SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD 22\n#define SPEC_FAIL_ATTR_CLASS_METHOD_OBJ 23\n#define SPEC_FAIL_ATTR_OBJECT_SLOT 24\n#define SPEC_FAIL_ATTR_HAS_MANAGED_DICT 25\n#define SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE 26\n#define SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE 27\n#define SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION 28\n#define SPEC_FAIL_ATTR_NOT_IN_KEYS 29\n#define SPEC_FAIL_ATTR_NOT_IN_DICT 30\n#define SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE 31\n#define SPEC_FAIL_ATTR_CLASS_ATTR_DESCRIPTOR 32\n#define SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD_OBJ 33\n\n/* Binary subscr and store subscr */\n\n#define SPEC_FAIL_SUBSCR_ARRAY_INT 9\n#define SPEC_FAIL_SUBSCR_ARRAY_SLICE 10\n#define SPEC_FAIL_SUBSCR_LIST_SLICE 11\n#define SPEC_FAIL_SUBSCR_TUPLE_SLICE 12\n#define SPEC_FAIL_SUBSCR_STRING_INT 13\n#define SPEC_FAIL_SUBSCR_STRING_SLICE 14\n#define SPEC_FAIL_SUBSCR_BUFFER_INT 15\n#define SPEC_FAIL_SUBSCR_BUFFER_SLICE 16\n#define SPEC_FAIL_SUBSCR_SEQUENCE_INT 17\n\n/* Store subscr */\n#define SPEC_FAIL_SUBSCR_BYTEARRAY_INT 18\n#define SPEC_FAIL_SUBSCR_BYTEARRAY_SLICE 19\n#define SPEC_FAIL_SUBSCR_PY_SIMPLE 20\n#define SPEC_FAIL_SUBSCR_PY_OTHER 21\n#define SPEC_FAIL_SUBSCR_DICT_SUBCLASS_NO_OVERRIDE 22\n#define SPEC_FAIL_SUBSCR_NOT_HEAP_TYPE 23\n\n/* Binary op */\n\n#define SPEC_FAIL_BINARY_OP_ADD_DIFFERENT_TYPES          9\n#define SPEC_FAIL_BINARY_OP_ADD_OTHER                   10\n#define SPEC_FAIL_BINARY_OP_AND_DIFFERENT_TYPES         11\n#define SPEC_FAIL_BINARY_OP_AND_INT                     12\n#define SPEC_FAIL_BINARY_OP_AND_OTHER                   13\n#define SPEC_FAIL_BINARY_OP_FLOOR_DIVIDE                14\n#define SPEC_FAIL_BINARY_OP_LSHIFT                      15\n#define SPEC_FAIL_BINARY_OP_MATRIX_MULTIPLY             16\n#define SPEC_FAIL_BINARY_OP_MULTIPLY_DIFFERENT_TYPES    17\n#define SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER              18\n#define SPEC_FAIL_BINARY_OP_OR                          19\n#define SPEC_FAIL_BINARY_OP_POWER                       20\n#define SPEC_FAIL_BINARY_OP_REMAINDER                   21\n#define SPEC_FAIL_BINARY_OP_RSHIFT                      22\n#define SPEC_FAIL_BINARY_OP_SUBTRACT_DIFFERENT_TYPES    23\n#define SPEC_FAIL_BINARY_OP_SUBTRACT_OTHER              24\n#define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_DIFFERENT_TYPES 25\n#define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT           26\n#define SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER           27\n#define SPEC_FAIL_BINARY_OP_XOR                         28\n\n/* Calls */\n\n#define SPEC_FAIL_CALL_INSTANCE_METHOD 11\n#define SPEC_FAIL_CALL_CMETHOD 12\n#define SPEC_FAIL_CALL_CFUNC_VARARGS 13\n#define SPEC_FAIL_CALL_CFUNC_VARARGS_KEYWORDS 14\n#define SPEC_FAIL_CALL_CFUNC_NOARGS 15\n#define SPEC_FAIL_CALL_CFUNC_METHOD_FASTCALL_KEYWORDS 16\n#define SPEC_FAIL_CALL_METH_DESCR_VARARGS 17\n#define SPEC_FAIL_CALL_METH_DESCR_VARARGS_KEYWORDS 18\n#define SPEC_FAIL_CALL_METH_DESCR_METHOD_FASTCALL_KEYWORDS 19\n#define SPEC_FAIL_CALL_BAD_CALL_FLAGS 20\n#define SPEC_FAIL_CALL_PYTHON_CLASS 21\n#define SPEC_FAIL_CALL_PEP_523 22\n#define SPEC_FAIL_CALL_BOUND_METHOD 23\n#define SPEC_FAIL_CALL_STR 24\n#define SPEC_FAIL_CALL_CLASS_NO_VECTORCALL 25\n#define SPEC_FAIL_CALL_CLASS_MUTABLE 26\n#define SPEC_FAIL_CALL_KWNAMES 27\n#define SPEC_FAIL_CALL_METHOD_WRAPPER 28\n#define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29\n\n/* COMPARE_OP */\n#define SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES 12\n#define SPEC_FAIL_COMPARE_OP_STRING 13\n#define SPEC_FAIL_COMPARE_OP_BIG_INT 14\n#define SPEC_FAIL_COMPARE_OP_BYTES 15\n#define SPEC_FAIL_COMPARE_OP_TUPLE 16\n#define SPEC_FAIL_COMPARE_OP_LIST 17\n#define SPEC_FAIL_COMPARE_OP_SET 18\n#define SPEC_FAIL_COMPARE_OP_BOOL 19\n#define SPEC_FAIL_COMPARE_OP_BASEOBJECT 20\n#define SPEC_FAIL_COMPARE_OP_FLOAT_LONG 21\n#define SPEC_FAIL_COMPARE_OP_LONG_FLOAT 22\n\n/* FOR_ITER and SEND */\n#define SPEC_FAIL_ITER_GENERATOR 10\n#define SPEC_FAIL_ITER_COROUTINE 11\n#define SPEC_FAIL_ITER_ASYNC_GENERATOR 12\n#define SPEC_FAIL_ITER_LIST 13\n#define SPEC_FAIL_ITER_TUPLE 14\n#define SPEC_FAIL_ITER_SET 15\n#define SPEC_FAIL_ITER_STRING 16\n#define SPEC_FAIL_ITER_BYTES 17\n#define SPEC_FAIL_ITER_RANGE 18\n#define SPEC_FAIL_ITER_ITERTOOLS 19\n#define SPEC_FAIL_ITER_DICT_KEYS 20\n#define SPEC_FAIL_ITER_DICT_ITEMS 21\n#define SPEC_FAIL_ITER_DICT_VALUES 22\n#define SPEC_FAIL_ITER_ENUMERATE 23\n#define SPEC_FAIL_ITER_MAP 24\n#define SPEC_FAIL_ITER_ZIP 25\n#define SPEC_FAIL_ITER_SEQ_ITER 26\n#define SPEC_FAIL_ITER_REVERSED_LIST 27\n#define SPEC_FAIL_ITER_CALLABLE 28\n#define SPEC_FAIL_ITER_ASCII_STRING 29\n#define SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND 30\n\n// UNPACK_SEQUENCE\n\n#define SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR 9\n#define SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE 10\n\nstatic int function_kind(PyCodeObject *code);\nstatic bool function_check_args(PyObject *o, int expected_argcount, int opcode);\nstatic uint32_t function_get_version(PyObject *o, int opcode);\n\nstatic int\nspecialize_module_load_attr(\n    PyObject *owner, _Py_CODEUNIT *instr, PyObject *name\n) {\n    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);\n    PyModuleObject *m = (PyModuleObject *)owner;\n    assert((owner->ob_type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0);\n    PyDictObject *dict = (PyDictObject *)m->md_dict;\n    if (dict == NULL) {\n        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_NO_DICT);\n        return -1;\n    }\n    if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {\n        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_STRING_OR_SPLIT);\n        return -1;\n    }\n    Py_ssize_t index = _PyDict_LookupIndex(dict, &_Py_ID(__getattr__));\n    assert(index != DKIX_ERROR);\n    if (index != DKIX_EMPTY) {\n        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND);\n        return -1;\n    }\n    index = _PyDict_LookupIndex(dict, name);\n    assert (index != DKIX_ERROR);\n    if (index != (uint16_t)index) {\n        SPECIALIZATION_FAIL(LOAD_ATTR,\n                            index == DKIX_EMPTY ?\n                            SPEC_FAIL_ATTR_MODULE_ATTR_NOT_FOUND :\n                            SPEC_FAIL_OUT_OF_RANGE);\n        return -1;\n    }\n    uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(\n            _PyInterpreterState_GET(), dict->ma_keys);\n    if (keys_version == 0) {\n        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);\n        return -1;\n    }\n    write_u32(cache->version, keys_version);\n    cache->index = (uint16_t)index;\n    instr->op.code = LOAD_ATTR_MODULE;\n    return 0;\n}\n\n\n\n/* Attribute specialization */\n\nvoid\n_Py_Specialize_LoadSuperAttr(PyObject *global_super, PyObject *cls, _Py_CODEUNIT *instr, int load_method) {\n    assert(ENABLE_SPECIALIZATION);\n    assert(_PyOpcode_Caches[LOAD_SUPER_ATTR] == INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR);\n    _PySuperAttrCache *cache = (_PySuperAttrCache *)(instr + 1);\n    if (global_super != (PyObject *)&PySuper_Type) {\n        SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_SHADOWED);\n        goto fail;\n    }\n    if (!PyType_Check(cls)) {\n        SPECIALIZATION_FAIL(LOAD_SUPER_ATTR, SPEC_FAIL_SUPER_BAD_CLASS);\n        goto fail;\n    }\n    instr->op.code = load_method ? LOAD_SUPER_ATTR_METHOD : LOAD_SUPER_ATTR_ATTR;\n    goto success;\n\nfail:\n    STAT_INC(LOAD_SUPER_ATTR, failure);\n    assert(!PyErr_Occurred());\n    instr->op.code = LOAD_SUPER_ATTR;\n    cache->counter = adaptive_counter_backoff(cache->counter);\n    return;\nsuccess:\n    STAT_INC(LOAD_SUPER_ATTR, success);\n    assert(!PyErr_Occurred());\n    cache->counter = adaptive_counter_cooldown();\n}\n\ntypedef enum {\n    OVERRIDING, /* Is an overriding descriptor, and will remain so. */\n    METHOD, /* Attribute has Py_TPFLAGS_METHOD_DESCRIPTOR set */\n    PROPERTY, /* Is a property */\n    OBJECT_SLOT, /* Is an object slot descriptor */\n    OTHER_SLOT, /* Is a slot descriptor of another type */\n    NON_OVERRIDING, /* Is another non-overriding descriptor, and is an instance of an immutable class*/\n    BUILTIN_CLASSMETHOD, /* Builtin methods with METH_CLASS */\n    PYTHON_CLASSMETHOD, /* Python classmethod(func) object */\n    NON_DESCRIPTOR, /* Is not a descriptor, and is an instance of an immutable class */\n    MUTABLE,   /* Instance of a mutable class; might, or might not, be a descriptor */\n    ABSENT, /* Attribute is not present on the class */\n    DUNDER_CLASS, /* __class__ attribute */\n    GETSET_OVERRIDDEN, /* __getattribute__ or __setattr__ has been overridden */\n    GETATTRIBUTE_IS_PYTHON_FUNCTION  /* Descriptor requires calling a Python __getattribute__ */\n} DescriptorClassification;\n\n\nstatic DescriptorClassification\nanalyze_descriptor(PyTypeObject *type, PyObject *name, PyObject **descr, int store)\n{\n    bool has_getattr = false;\n    if (store) {\n        if (type->tp_setattro != PyObject_GenericSetAttr) {\n            *descr = NULL;\n            return GETSET_OVERRIDDEN;\n        }\n    }\n    else {\n        getattrofunc getattro_slot = type->tp_getattro;\n        if (getattro_slot == PyObject_GenericGetAttr) {\n            /* Normal attribute lookup; */\n            has_getattr = false;\n        }\n        else if (getattro_slot == _Py_slot_tp_getattr_hook ||\n            getattro_slot == _Py_slot_tp_getattro) {\n            /* One or both of __getattribute__ or __getattr__ may have been\n             overridden See typeobject.c for why these functions are special. */\n            PyObject *getattribute = _PyType_Lookup(type,\n                &_Py_ID(__getattribute__));\n            PyInterpreterState *interp = _PyInterpreterState_GET();\n            bool has_custom_getattribute = getattribute != NULL &&\n                getattribute != interp->callable_cache.object__getattribute__;\n            has_getattr = _PyType_Lookup(type, &_Py_ID(__getattr__)) != NULL;\n            if (has_custom_getattribute) {\n                if (getattro_slot == _Py_slot_tp_getattro &&\n                    !has_getattr &&\n                    Py_IS_TYPE(getattribute, &PyFunction_Type)) {\n                    *descr = getattribute;\n                    return GETATTRIBUTE_IS_PYTHON_FUNCTION;\n                }\n                /* Potentially both __getattr__ and __getattribute__ are set.\n                   Too complicated */\n                *descr = NULL;\n                return GETSET_OVERRIDDEN;\n            }\n            /* Potentially has __getattr__ but no custom __getattribute__.\n               Fall through to usual descriptor analysis.\n               Usual attribute lookup should only be allowed at runtime\n               if we can guarantee that there is no way an exception can be\n               raised. This means some specializations, e.g. specializing\n               for property() isn't safe.\n            */\n        }\n        else {\n            *descr = NULL;\n            return GETSET_OVERRIDDEN;\n        }\n    }\n    PyObject *descriptor = _PyType_Lookup(type, name);\n    *descr = descriptor;\n    if (descriptor == NULL) {\n        return ABSENT;\n    }\n    PyTypeObject *desc_cls = Py_TYPE(descriptor);\n    if (!(desc_cls->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)) {\n        return MUTABLE;\n    }\n    if (desc_cls->tp_descr_set) {\n        if (desc_cls == &PyMemberDescr_Type) {\n            PyMemberDescrObject *member = (PyMemberDescrObject *)descriptor;\n            struct PyMemberDef *dmem = member->d_member;\n            if (dmem->type == T_OBJECT_EX) {\n                return OBJECT_SLOT;\n            }\n            return OTHER_SLOT;\n        }\n        if (desc_cls == &PyProperty_Type) {\n            /* We can't detect at runtime whether an attribute exists\n               with property. So that means we may have to call\n               __getattr__. */\n            return has_getattr ? GETSET_OVERRIDDEN : PROPERTY;\n        }\n        if (PyUnicode_CompareWithASCIIString(name, \"__class__\") == 0) {\n            if (descriptor == _PyType_Lookup(&PyBaseObject_Type, name)) {\n                return DUNDER_CLASS;\n            }\n        }\n        if (store) {\n            return OVERRIDING;\n        }\n    }\n    if (desc_cls->tp_descr_get) {\n        if (desc_cls->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR) {\n            return METHOD;\n        }\n        if (Py_IS_TYPE(descriptor, &PyClassMethodDescr_Type)) {\n            return BUILTIN_CLASSMETHOD;\n        }\n        if (Py_IS_TYPE(descriptor, &PyClassMethod_Type)) {\n            return PYTHON_CLASSMETHOD;\n        }\n        return NON_OVERRIDING;\n    }\n    return NON_DESCRIPTOR;\n}\n\nstatic int\nspecialize_dict_access(\n    PyObject *owner, _Py_CODEUNIT *instr, PyTypeObject *type,\n    DescriptorClassification kind, PyObject *name,\n    int base_op, int values_op, int hint_op)\n{\n    assert(kind == NON_OVERRIDING || kind == NON_DESCRIPTOR || kind == ABSENT ||\n        kind == BUILTIN_CLASSMETHOD || kind == PYTHON_CLASSMETHOD);\n    // No descriptor, or non overriding.\n    if ((type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0) {\n        SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);\n        return 0;\n    }\n    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);\n    PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);\n    if (_PyDictOrValues_IsValues(dorv)) {\n        // Virtual dictionary\n        PyDictKeysObject *keys = ((PyHeapTypeObject *)type)->ht_cached_keys;\n        assert(PyUnicode_CheckExact(name));\n        Py_ssize_t index = _PyDictKeys_StringLookup(keys, name);\n        assert (index != DKIX_ERROR);\n        if (index != (uint16_t)index) {\n            SPECIALIZATION_FAIL(base_op,\n                                index == DKIX_EMPTY ?\n                                SPEC_FAIL_ATTR_NOT_IN_KEYS :\n                                SPEC_FAIL_OUT_OF_RANGE);\n            return 0;\n        }\n        write_u32(cache->version, type->tp_version_tag);\n        cache->index = (uint16_t)index;\n        instr->op.code = values_op;\n    }\n    else {\n        PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);\n        if (dict == NULL || !PyDict_CheckExact(dict)) {\n            SPECIALIZATION_FAIL(base_op, SPEC_FAIL_NO_DICT);\n            return 0;\n        }\n        // We found an instance with a __dict__.\n        Py_ssize_t index =\n            _PyDict_LookupIndex(dict, name);\n        if (index != (uint16_t)index) {\n            SPECIALIZATION_FAIL(base_op,\n                                index == DKIX_EMPTY ?\n                                SPEC_FAIL_ATTR_NOT_IN_DICT :\n                                SPEC_FAIL_OUT_OF_RANGE);\n            return 0;\n        }\n        cache->index = (uint16_t)index;\n        write_u32(cache->version, type->tp_version_tag);\n        instr->op.code = hint_op;\n    }\n    return 1;\n}\n\nstatic int specialize_attr_loadmethod(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name,\n    PyObject* descr, DescriptorClassification kind);\nstatic int specialize_class_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name);\n\nvoid\n_Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)\n{\n    assert(ENABLE_SPECIALIZATION);\n    assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR);\n    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);\n    PyTypeObject *type = Py_TYPE(owner);\n    if (!_PyType_IsReady(type)) {\n        // We *might* not really need this check, but we inherited it from\n        // PyObject_GenericGetAttr and friends... and this way we still do the\n        // right thing if someone forgets to call PyType_Ready(type):\n        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);\n        goto fail;\n    }\n    if (PyModule_CheckExact(owner)) {\n        if (specialize_module_load_attr(owner, instr, name))\n        {\n            goto fail;\n        }\n        goto success;\n    }\n    if (PyType_Check(owner)) {\n        if (specialize_class_load_attr(owner, instr, name)) {\n            goto fail;\n        }\n        goto success;\n    }\n    PyObject *descr = NULL;\n    DescriptorClassification kind = analyze_descriptor(type, name, &descr, 0);\n    assert(descr != NULL || kind == ABSENT || kind == GETSET_OVERRIDDEN);\n    switch(kind) {\n        case OVERRIDING:\n            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);\n            goto fail;\n        case METHOD:\n        {\n            int oparg = instr->op.arg;\n            if (oparg & 1) {\n                if (specialize_attr_loadmethod(owner, instr, name, descr, kind)) {\n                    goto success;\n                }\n            }\n            else {\n                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);\n            }\n            goto fail;\n        }\n        case PROPERTY:\n        {\n            _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);\n            assert(Py_TYPE(descr) == &PyProperty_Type);\n            PyObject *fget = ((_PyPropertyObject *)descr)->prop_get;\n            if (fget == NULL) {\n                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);\n                goto fail;\n            }\n            if (!Py_IS_TYPE(fget, &PyFunction_Type)) {\n                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY_NOT_PY_FUNCTION);\n                goto fail;\n            }\n            if (!function_check_args(fget, 1, LOAD_ATTR)) {\n                goto fail;\n            }\n            uint32_t version = function_get_version(fget, LOAD_ATTR);\n            if (version == 0) {\n                goto fail;\n            }\n            if (_PyInterpreterState_GET()->eval_frame) {\n                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);\n                goto fail;\n            }\n            write_u32(lm_cache->keys_version, version);\n            assert(type->tp_version_tag != 0);\n            write_u32(lm_cache->type_version, type->tp_version_tag);\n            /* borrowed */\n            write_obj(lm_cache->descr, fget);\n            instr->op.code = LOAD_ATTR_PROPERTY;\n            goto success;\n        }\n        case OBJECT_SLOT:\n        {\n            PyMemberDescrObject *member = (PyMemberDescrObject *)descr;\n            struct PyMemberDef *dmem = member->d_member;\n            Py_ssize_t offset = dmem->offset;\n            if (!PyObject_TypeCheck(owner, member->d_common.d_type)) {\n                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);\n                goto fail;\n            }\n            if (dmem->flags & PY_AUDIT_READ) {\n                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_AUDITED_SLOT);\n                goto fail;\n            }\n            if (offset != (uint16_t)offset) {\n                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);\n                goto fail;\n            }\n            assert(dmem->type == T_OBJECT_EX);\n            assert(offset > 0);\n            cache->index = (uint16_t)offset;\n            write_u32(cache->version, type->tp_version_tag);\n            instr->op.code = LOAD_ATTR_SLOT;\n            goto success;\n        }\n        case DUNDER_CLASS:\n        {\n            Py_ssize_t offset = offsetof(PyObject, ob_type);\n            assert(offset == (uint16_t)offset);\n            cache->index = (uint16_t)offset;\n            write_u32(cache->version, type->tp_version_tag);\n            instr->op.code = LOAD_ATTR_SLOT;\n            goto success;\n        }\n        case OTHER_SLOT:\n            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);\n            goto fail;\n        case MUTABLE:\n            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);\n            goto fail;\n        case GETSET_OVERRIDDEN:\n            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OVERRIDDEN);\n            goto fail;\n        case GETATTRIBUTE_IS_PYTHON_FUNCTION:\n        {\n            assert(type->tp_getattro == _Py_slot_tp_getattro);\n            assert(Py_IS_TYPE(descr, &PyFunction_Type));\n            _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);\n            if (!function_check_args(descr, 2, LOAD_ATTR)) {\n                goto fail;\n            }\n            uint32_t version = function_get_version(descr, LOAD_ATTR);\n            if (version == 0) {\n                goto fail;\n            }\n            if (_PyInterpreterState_GET()->eval_frame) {\n                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);\n                goto fail;\n            }\n            write_u32(lm_cache->keys_version, version);\n            /* borrowed */\n            write_obj(lm_cache->descr, descr);\n            write_u32(lm_cache->type_version, type->tp_version_tag);\n            instr->op.code = LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN;\n            goto success;\n        }\n        case BUILTIN_CLASSMETHOD:\n            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD_OBJ);\n            goto fail;\n        case PYTHON_CLASSMETHOD:\n            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_METHOD_OBJ);\n            goto fail;\n        case NON_OVERRIDING:\n            SPECIALIZATION_FAIL(LOAD_ATTR,\n                                (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) ?\n                                SPEC_FAIL_ATTR_CLASS_ATTR_DESCRIPTOR :\n                                SPEC_FAIL_ATTR_NOT_MANAGED_DICT);\n            goto fail;\n        case NON_DESCRIPTOR:\n            SPECIALIZATION_FAIL(LOAD_ATTR,\n                                (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) ?\n                                SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE :\n                                SPEC_FAIL_ATTR_NOT_MANAGED_DICT);\n            goto fail;\n        case ABSENT:\n            if (specialize_dict_access(owner, instr, type, kind, name, LOAD_ATTR,\n                                    LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT))\n            {\n                goto success;\n            }\n    }\nfail:\n    STAT_INC(LOAD_ATTR, failure);\n    assert(!PyErr_Occurred());\n    instr->op.code = LOAD_ATTR;\n    cache->counter = adaptive_counter_backoff(cache->counter);\n    return;\nsuccess:\n    STAT_INC(LOAD_ATTR, success);\n    assert(!PyErr_Occurred());\n    cache->counter = adaptive_counter_cooldown();\n}\n\nvoid\n_Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)\n{\n    assert(ENABLE_SPECIALIZATION);\n    assert(_PyOpcode_Caches[STORE_ATTR] == INLINE_CACHE_ENTRIES_STORE_ATTR);\n    _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);\n    PyTypeObject *type = Py_TYPE(owner);\n    if (!_PyType_IsReady(type)) {\n        // We *might* not really need this check, but we inherited it from\n        // PyObject_GenericSetAttr and friends... and this way we still do the\n        // right thing if someone forgets to call PyType_Ready(type):\n        SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OTHER);\n        goto fail;\n    }\n    if (PyModule_CheckExact(owner)) {\n        SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN);\n        goto fail;\n    }\n    PyObject *descr;\n    DescriptorClassification kind = analyze_descriptor(type, name, &descr, 1);\n    switch(kind) {\n        case OVERRIDING:\n            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR);\n            goto fail;\n        case METHOD:\n            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_METHOD);\n            goto fail;\n        case PROPERTY:\n            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_PROPERTY);\n            goto fail;\n        case OBJECT_SLOT:\n        {\n            PyMemberDescrObject *member = (PyMemberDescrObject *)descr;\n            struct PyMemberDef *dmem = member->d_member;\n            Py_ssize_t offset = dmem->offset;\n            if (!PyObject_TypeCheck(owner, member->d_common.d_type)) {\n                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_EXPECTED_ERROR);\n                goto fail;\n            }\n            if (dmem->flags & READONLY) {\n                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_READ_ONLY);\n                goto fail;\n            }\n            if (offset != (uint16_t)offset) {\n                SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OUT_OF_RANGE);\n                goto fail;\n            }\n            assert(dmem->type == T_OBJECT_EX);\n            assert(offset > 0);\n            cache->index = (uint16_t)offset;\n            write_u32(cache->version, type->tp_version_tag);\n            instr->op.code = STORE_ATTR_SLOT;\n            goto success;\n        }\n        case DUNDER_CLASS:\n        case OTHER_SLOT:\n            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT);\n            goto fail;\n        case MUTABLE:\n            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);\n            goto fail;\n        case GETATTRIBUTE_IS_PYTHON_FUNCTION:\n        case GETSET_OVERRIDDEN:\n            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN);\n            goto fail;\n        case BUILTIN_CLASSMETHOD:\n            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD_OBJ);\n            goto fail;\n        case PYTHON_CLASSMETHOD:\n            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_METHOD_OBJ);\n            goto fail;\n        case NON_OVERRIDING:\n            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_DESCRIPTOR);\n            goto fail;\n        case NON_DESCRIPTOR:\n            SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);\n            goto fail;\n        case ABSENT:\n            if (specialize_dict_access(owner, instr, type, kind, name, STORE_ATTR,\n                                    STORE_ATTR_INSTANCE_VALUE, STORE_ATTR_WITH_HINT))\n            {\n                goto success;\n            }\n    }\nfail:\n    STAT_INC(STORE_ATTR, failure);\n    assert(!PyErr_Occurred());\n    instr->op.code = STORE_ATTR;\n    cache->counter = adaptive_counter_backoff(cache->counter);\n    return;\nsuccess:\n    STAT_INC(STORE_ATTR, success);\n    assert(!PyErr_Occurred());\n    cache->counter = adaptive_counter_cooldown();\n}\n\n\n#ifdef Py_STATS\nstatic int\nload_attr_fail_kind(DescriptorClassification kind)\n{\n    switch (kind) {\n        case OVERRIDING:\n            return SPEC_FAIL_ATTR_OVERRIDING_DESCRIPTOR;\n        case METHOD:\n            return SPEC_FAIL_ATTR_METHOD;\n        case PROPERTY:\n            return SPEC_FAIL_ATTR_PROPERTY;\n        case OBJECT_SLOT:\n            return SPEC_FAIL_ATTR_OBJECT_SLOT;\n        case OTHER_SLOT:\n            return SPEC_FAIL_ATTR_NON_OBJECT_SLOT;\n        case DUNDER_CLASS:\n            return SPEC_FAIL_OTHER;\n        case MUTABLE:\n            return SPEC_FAIL_ATTR_MUTABLE_CLASS;\n        case GETSET_OVERRIDDEN:\n        case GETATTRIBUTE_IS_PYTHON_FUNCTION:\n            return SPEC_FAIL_OVERRIDDEN;\n        case BUILTIN_CLASSMETHOD:\n            return SPEC_FAIL_ATTR_BUILTIN_CLASS_METHOD;\n        case PYTHON_CLASSMETHOD:\n            return SPEC_FAIL_ATTR_CLASS_METHOD_OBJ;\n        case NON_OVERRIDING:\n            return SPEC_FAIL_ATTR_NON_OVERRIDING_DESCRIPTOR;\n        case NON_DESCRIPTOR:\n            return SPEC_FAIL_ATTR_NOT_DESCRIPTOR;\n        case ABSENT:\n            return SPEC_FAIL_ATTR_INSTANCE_ATTRIBUTE;\n    }\n    Py_UNREACHABLE();\n}\n#endif\n\nstatic int\nspecialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr,\n                             PyObject *name)\n{\n    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);\n    if (!PyType_CheckExact(owner) || _PyType_Lookup(Py_TYPE(owner), name)) {\n        SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METACLASS_ATTRIBUTE);\n        return -1;\n    }\n    PyObject *descr = NULL;\n    DescriptorClassification kind = 0;\n    kind = analyze_descriptor((PyTypeObject *)owner, name, &descr, 0);\n    switch (kind) {\n        case METHOD:\n        case NON_DESCRIPTOR:\n            write_u32(cache->type_version, ((PyTypeObject *)owner)->tp_version_tag);\n            write_obj(cache->descr, descr);\n            instr->op.code = LOAD_ATTR_CLASS;\n            return 0;\n#ifdef Py_STATS\n        case ABSENT:\n            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);\n            return -1;\n#endif\n        default:\n            SPECIALIZATION_FAIL(LOAD_ATTR, load_attr_fail_kind(kind));\n            return -1;\n    }\n}\n\n// Please collect stats carefully before and after modifying. A subtle change\n// can cause a significant drop in cache hits. A possible test is\n// python.exe -m test_typing test_re test_dis test_zlib.\nstatic int\nspecialize_attr_loadmethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,\nPyObject *descr, DescriptorClassification kind)\n{\n    _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1);\n    PyTypeObject *owner_cls = Py_TYPE(owner);\n\n    assert(kind == METHOD && descr != NULL);\n    if (owner_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT) {\n        PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);\n        PyDictKeysObject *keys = ((PyHeapTypeObject *)owner_cls)->ht_cached_keys;\n        if (!_PyDictOrValues_IsValues(dorv)) {\n            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_HAS_MANAGED_DICT);\n            return 0;\n        }\n        Py_ssize_t index = _PyDictKeys_StringLookup(keys, name);\n        if (index != DKIX_EMPTY) {\n            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_SHADOWED);\n            return 0;\n        }\n        uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(\n                _PyInterpreterState_GET(), keys);\n        if (keys_version == 0) {\n            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);\n            return 0;\n        }\n        write_u32(cache->keys_version, keys_version);\n        instr->op.code = LOAD_ATTR_METHOD_WITH_VALUES;\n    }\n    else {\n        Py_ssize_t dictoffset = owner_cls->tp_dictoffset;\n        if (dictoffset < 0 || dictoffset > INT16_MAX) {\n            SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_RANGE);\n            return 0;\n        }\n        if (dictoffset == 0) {\n            instr->op.code = LOAD_ATTR_METHOD_NO_DICT;\n        }\n        else {\n            PyObject *dict = *(PyObject **) ((char *)owner + dictoffset);\n            if (dict) {\n                SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NOT_MANAGED_DICT);\n                return 0;\n            }\n            assert(owner_cls->tp_dictoffset > 0);\n            assert(owner_cls->tp_dictoffset <= INT16_MAX);\n            instr->op.code = LOAD_ATTR_METHOD_LAZY_DICT;\n        }\n    }\n    /* `descr` is borrowed. This is safe for methods (even inherited ones from\n    *  super classes!) as long as tp_version_tag is validated for two main reasons:\n    *\n    *  1. The class will always hold a reference to the method so it will\n    *  usually not be GC-ed. Should it be deleted in Python, e.g.\n    *  `del obj.meth`, tp_version_tag will be invalidated, because of reason 2.\n    *\n    *  2. The pre-existing type method cache (MCACHE) uses the same principles\n    *  of caching a borrowed descriptor. The MCACHE infrastructure does all the\n    *  heavy lifting for us. E.g. it invalidates tp_version_tag on any MRO\n    *  modification, on any type object change along said MRO, etc. (see\n    *  PyType_Modified usages in typeobject.c). The MCACHE has been\n    *  working since Python 2.6 and it's battle-tested.\n    */\n    write_u32(cache->type_version, owner_cls->tp_version_tag);\n    write_obj(cache->descr, descr);\n    return 1;\n}\n\nvoid\n_Py_Specialize_LoadGlobal(\n    PyObject *globals, PyObject *builtins,\n    _Py_CODEUNIT *instr, PyObject *name)\n{\n    assert(ENABLE_SPECIALIZATION);\n    assert(_PyOpcode_Caches[LOAD_GLOBAL] == INLINE_CACHE_ENTRIES_LOAD_GLOBAL);\n    /* Use inline cache */\n    _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1);\n    assert(PyUnicode_CheckExact(name));\n    if (!PyDict_CheckExact(globals)) {\n        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);\n        goto fail;\n    }\n    PyDictKeysObject * globals_keys = ((PyDictObject *)globals)->ma_keys;\n    if (!DK_IS_UNICODE(globals_keys)) {\n        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT);\n        goto fail;\n    }\n    Py_ssize_t index = _PyDictKeys_StringLookup(globals_keys, name);\n    if (index == DKIX_ERROR) {\n        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);\n        goto fail;\n    }\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (index != DKIX_EMPTY) {\n        if (index != (uint16_t)index) {\n            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);\n            goto fail;\n        }\n        uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(\n                interp, globals_keys);\n        if (keys_version == 0) {\n            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);\n            goto fail;\n        }\n        if (keys_version != (uint16_t)keys_version) {\n            SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);\n            goto fail;\n        }\n        cache->index = (uint16_t)index;\n        cache->module_keys_version = (uint16_t)keys_version;\n        instr->op.code = LOAD_GLOBAL_MODULE;\n        goto success;\n    }\n    if (!PyDict_CheckExact(builtins)) {\n        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_DICT);\n        goto fail;\n    }\n    PyDictKeysObject * builtin_keys = ((PyDictObject *)builtins)->ma_keys;\n    if (!DK_IS_UNICODE(builtin_keys)) {\n        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT);\n        goto fail;\n    }\n    index = _PyDictKeys_StringLookup(builtin_keys, name);\n    if (index == DKIX_ERROR) {\n        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);\n        goto fail;\n    }\n    if (index != (uint16_t)index) {\n        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);\n        goto fail;\n    }\n    uint32_t globals_version = _PyDictKeys_GetVersionForCurrentState(\n            interp, globals_keys);\n    if (globals_version == 0) {\n        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);\n        goto fail;\n    }\n    if (globals_version != (uint16_t)globals_version) {\n        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);\n        goto fail;\n    }\n    uint32_t builtins_version = _PyDictKeys_GetVersionForCurrentState(\n            interp, builtin_keys);\n    if (builtins_version == 0) {\n        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);\n        goto fail;\n    }\n    if (builtins_version > UINT16_MAX) {\n        SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);\n        goto fail;\n    }\n    cache->index = (uint16_t)index;\n    cache->module_keys_version = (uint16_t)globals_version;\n    cache->builtin_keys_version = (uint16_t)builtins_version;\n    instr->op.code = LOAD_GLOBAL_BUILTIN;\n    goto success;\nfail:\n    STAT_INC(LOAD_GLOBAL, failure);\n    assert(!PyErr_Occurred());\n    instr->op.code = LOAD_GLOBAL;\n    cache->counter = adaptive_counter_backoff(cache->counter);\n    return;\nsuccess:\n    STAT_INC(LOAD_GLOBAL, success);\n    assert(!PyErr_Occurred());\n    cache->counter = adaptive_counter_cooldown();\n}\n\n#ifdef Py_STATS\nstatic int\nbinary_subscr_fail_kind(PyTypeObject *container_type, PyObject *sub)\n{\n    if (container_type == &PyUnicode_Type) {\n        if (PyLong_CheckExact(sub)) {\n            return SPEC_FAIL_SUBSCR_STRING_INT;\n        }\n        if (PySlice_Check(sub)) {\n            return SPEC_FAIL_SUBSCR_STRING_SLICE;\n        }\n        return SPEC_FAIL_OTHER;\n    }\n    else if (strcmp(container_type->tp_name, \"array.array\") == 0) {\n        if (PyLong_CheckExact(sub)) {\n            return SPEC_FAIL_SUBSCR_ARRAY_INT;\n        }\n        if (PySlice_Check(sub)) {\n            return SPEC_FAIL_SUBSCR_ARRAY_SLICE;\n        }\n        return SPEC_FAIL_OTHER;\n    }\n    else if (container_type->tp_as_buffer) {\n        if (PyLong_CheckExact(sub)) {\n            return SPEC_FAIL_SUBSCR_BUFFER_INT;\n        }\n        if (PySlice_Check(sub)) {\n            return SPEC_FAIL_SUBSCR_BUFFER_SLICE;\n        }\n        return SPEC_FAIL_OTHER;\n    }\n    else if (container_type->tp_as_sequence) {\n        if (PyLong_CheckExact(sub) && container_type->tp_as_sequence->sq_item) {\n            return SPEC_FAIL_SUBSCR_SEQUENCE_INT;\n        }\n    }\n    return SPEC_FAIL_OTHER;\n}\n#endif\n\nstatic int\nfunction_kind(PyCodeObject *code) {\n    int flags = code->co_flags;\n    if ((flags & (CO_VARKEYWORDS | CO_VARARGS)) || code->co_kwonlyargcount) {\n        return SPEC_FAIL_CODE_COMPLEX_PARAMETERS;\n    }\n    if ((flags & CO_OPTIMIZED) == 0) {\n        return SPEC_FAIL_CODE_NOT_OPTIMIZED;\n    }\n    return SIMPLE_FUNCTION;\n}\n\n/* Returning false indicates a failure. */\nstatic bool\nfunction_check_args(PyObject *o, int expected_argcount, int opcode)\n{\n    assert(Py_IS_TYPE(o, &PyFunction_Type));\n    PyFunctionObject *func = (PyFunctionObject *)o;\n    PyCodeObject *fcode = (PyCodeObject *)func->func_code;\n    int kind = function_kind(fcode);\n    if (kind != SIMPLE_FUNCTION) {\n        SPECIALIZATION_FAIL(opcode, kind);\n        return false;\n    }\n    if (fcode->co_argcount != expected_argcount) {\n        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);\n        return false;\n    }\n    return true;\n}\n\n/* Returning 0 indicates a failure. */\nstatic uint32_t\nfunction_get_version(PyObject *o, int opcode)\n{\n    assert(Py_IS_TYPE(o, &PyFunction_Type));\n    PyFunctionObject *func = (PyFunctionObject *)o;\n    uint32_t version = _PyFunction_GetVersionForCurrentState(func);\n    if (version == 0) {\n        SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_VERSIONS);\n        return 0;\n    }\n    return version;\n}\n\nvoid\n_Py_Specialize_BinarySubscr(\n     PyObject *container, PyObject *sub, _Py_CODEUNIT *instr)\n{\n    assert(ENABLE_SPECIALIZATION);\n    assert(_PyOpcode_Caches[BINARY_SUBSCR] ==\n           INLINE_CACHE_ENTRIES_BINARY_SUBSCR);\n    _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)(instr + 1);\n    PyTypeObject *container_type = Py_TYPE(container);\n    if (container_type == &PyList_Type) {\n        if (PyLong_CheckExact(sub)) {\n            if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {\n                instr->op.code = BINARY_SUBSCR_LIST_INT;\n                goto success;\n            }\n            SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);\n            goto fail;\n        }\n        SPECIALIZATION_FAIL(BINARY_SUBSCR,\n            PySlice_Check(sub) ? SPEC_FAIL_SUBSCR_LIST_SLICE : SPEC_FAIL_OTHER);\n        goto fail;\n    }\n    if (container_type == &PyTuple_Type) {\n        if (PyLong_CheckExact(sub)) {\n            if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) {\n                instr->op.code = BINARY_SUBSCR_TUPLE_INT;\n                goto success;\n            }\n            SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);\n            goto fail;\n        }\n        SPECIALIZATION_FAIL(BINARY_SUBSCR,\n            PySlice_Check(sub) ? SPEC_FAIL_SUBSCR_TUPLE_SLICE : SPEC_FAIL_OTHER);\n        goto fail;\n    }\n    if (container_type == &PyDict_Type) {\n        instr->op.code = BINARY_SUBSCR_DICT;\n        goto success;\n    }\n    PyTypeObject *cls = Py_TYPE(container);\n    PyObject *descriptor = _PyType_Lookup(cls, &_Py_ID(__getitem__));\n    if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {\n        if (!(container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {\n            SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_SUBSCR_NOT_HEAP_TYPE);\n            goto fail;\n        }\n        PyFunctionObject *func = (PyFunctionObject *)descriptor;\n        PyCodeObject *fcode = (PyCodeObject *)func->func_code;\n        int kind = function_kind(fcode);\n        if (kind != SIMPLE_FUNCTION) {\n            SPECIALIZATION_FAIL(BINARY_SUBSCR, kind);\n            goto fail;\n        }\n        if (fcode->co_argcount != 2) {\n            SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);\n            goto fail;\n        }\n        uint32_t version = _PyFunction_GetVersionForCurrentState(func);\n        if (version == 0) {\n            SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_VERSIONS);\n            goto fail;\n        }\n        if (_PyInterpreterState_GET()->eval_frame) {\n            SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OTHER);\n            goto fail;\n        }\n        PyHeapTypeObject *ht = (PyHeapTypeObject *)container_type;\n        // This pointer is invalidated by PyType_Modified (see the comment on\n        // struct _specialization_cache):\n        ht->_spec_cache.getitem = descriptor;\n        ht->_spec_cache.getitem_version = version;\n        instr->op.code = BINARY_SUBSCR_GETITEM;\n        goto success;\n    }\n    SPECIALIZATION_FAIL(BINARY_SUBSCR,\n                        binary_subscr_fail_kind(container_type, sub));\nfail:\n    STAT_INC(BINARY_SUBSCR, failure);\n    assert(!PyErr_Occurred());\n    instr->op.code = BINARY_SUBSCR;\n    cache->counter = adaptive_counter_backoff(cache->counter);\n    return;\nsuccess:\n    STAT_INC(BINARY_SUBSCR, success);\n    assert(!PyErr_Occurred());\n    cache->counter = adaptive_counter_cooldown();\n}\n\nvoid\n_Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr)\n{\n    assert(ENABLE_SPECIALIZATION);\n    _PyStoreSubscrCache *cache = (_PyStoreSubscrCache *)(instr + 1);\n    PyTypeObject *container_type = Py_TYPE(container);\n    if (container_type == &PyList_Type) {\n        if (PyLong_CheckExact(sub)) {\n            if (_PyLong_IsNonNegativeCompact((PyLongObject *)sub)\n                && ((PyLongObject *)sub)->long_value.ob_digit[0] < (size_t)PyList_GET_SIZE(container))\n            {\n                instr->op.code = STORE_SUBSCR_LIST_INT;\n                goto success;\n            }\n            else {\n                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);\n                goto fail;\n            }\n        }\n        else if (PySlice_Check(sub)) {\n            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_LIST_SLICE);\n            goto fail;\n        }\n        else {\n            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);\n            goto fail;\n        }\n    }\n    if (container_type == &PyDict_Type) {\n        instr->op.code = STORE_SUBSCR_DICT;\n        goto success;\n    }\n#ifdef Py_STATS\n    PyMappingMethods *as_mapping = container_type->tp_as_mapping;\n    if (as_mapping && (as_mapping->mp_ass_subscript\n                       == PyDict_Type.tp_as_mapping->mp_ass_subscript)) {\n        SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_DICT_SUBCLASS_NO_OVERRIDE);\n        goto fail;\n    }\n    if (PyObject_CheckBuffer(container)) {\n        if (PyLong_CheckExact(sub) && (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub))) {\n            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OUT_OF_RANGE);\n        }\n        else if (strcmp(container_type->tp_name, \"array.array\") == 0) {\n            if (PyLong_CheckExact(sub)) {\n                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_ARRAY_INT);\n            }\n            else if (PySlice_Check(sub)) {\n                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_ARRAY_SLICE);\n            }\n            else {\n                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);\n            }\n        }\n        else if (PyByteArray_CheckExact(container)) {\n            if (PyLong_CheckExact(sub)) {\n                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_BYTEARRAY_INT);\n            }\n            else if (PySlice_Check(sub)) {\n                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_BYTEARRAY_SLICE);\n            }\n            else {\n                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);\n            }\n        }\n        else {\n            if (PyLong_CheckExact(sub)) {\n                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_BUFFER_INT);\n            }\n            else if (PySlice_Check(sub)) {\n                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_BUFFER_SLICE);\n            }\n            else {\n                SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);\n            }\n        }\n        goto fail;\n    }\n    PyObject *descriptor = _PyType_Lookup(container_type, &_Py_ID(__setitem__));\n    if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {\n        PyFunctionObject *func = (PyFunctionObject *)descriptor;\n        PyCodeObject *code = (PyCodeObject *)func->func_code;\n        int kind = function_kind(code);\n        if (kind == SIMPLE_FUNCTION) {\n            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_PY_SIMPLE);\n        }\n        else {\n            SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_SUBSCR_PY_OTHER);\n        }\n        goto fail;\n    }\n#endif\n    SPECIALIZATION_FAIL(STORE_SUBSCR, SPEC_FAIL_OTHER);\nfail:\n    STAT_INC(STORE_SUBSCR, failure);\n    assert(!PyErr_Occurred());\n    instr->op.code = STORE_SUBSCR;\n    cache->counter = adaptive_counter_backoff(cache->counter);\n    return;\nsuccess:\n    STAT_INC(STORE_SUBSCR, success);\n    assert(!PyErr_Occurred());\n    cache->counter = adaptive_counter_cooldown();\n}\n\nstatic int\nspecialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,\n                      PyObject *kwnames)\n{\n    PyTypeObject *tp = _PyType_CAST(callable);\n    if (tp->tp_new == PyBaseObject_Type.tp_new) {\n        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PYTHON_CLASS);\n        return -1;\n    }\n    if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {\n        int oparg = instr->op.arg;\n        if (nargs == 1 && kwnames == NULL && oparg == 1) {\n            if (tp == &PyUnicode_Type) {\n                instr->op.code = CALL_NO_KW_STR_1;\n                return 0;\n            }\n            else if (tp == &PyType_Type) {\n                instr->op.code = CALL_NO_KW_TYPE_1;\n                return 0;\n            }\n            else if (tp == &PyTuple_Type) {\n                instr->op.code = CALL_NO_KW_TUPLE_1;\n                return 0;\n            }\n        }\n        if (tp->tp_vectorcall != NULL) {\n            instr->op.code = CALL_BUILTIN_CLASS;\n            return 0;\n        }\n        SPECIALIZATION_FAIL(CALL, tp == &PyUnicode_Type ?\n            SPEC_FAIL_CALL_STR : SPEC_FAIL_CALL_CLASS_NO_VECTORCALL);\n        return -1;\n    }\n    SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_CLASS_MUTABLE);\n    return -1;\n}\n\n#ifdef Py_STATS\nstatic int\nbuiltin_call_fail_kind(int ml_flags)\n{\n    switch (ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |\n        METH_KEYWORDS | METH_METHOD)) {\n        case METH_VARARGS:\n            return SPEC_FAIL_CALL_CFUNC_VARARGS;\n        case METH_VARARGS | METH_KEYWORDS:\n            return SPEC_FAIL_CALL_CFUNC_VARARGS_KEYWORDS;\n        case METH_NOARGS:\n            return SPEC_FAIL_CALL_CFUNC_NOARGS;\n        case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:\n            return SPEC_FAIL_CALL_CFUNC_METHOD_FASTCALL_KEYWORDS;\n        /* These cases should be optimized, but return \"other\" just in case */\n        case METH_O:\n        case METH_FASTCALL:\n        case METH_FASTCALL | METH_KEYWORDS:\n            return SPEC_FAIL_OTHER;\n        default:\n            return SPEC_FAIL_CALL_BAD_CALL_FLAGS;\n    }\n}\n\nstatic int\nmeth_descr_call_fail_kind(int ml_flags)\n{\n    switch (ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |\n                        METH_KEYWORDS | METH_METHOD)) {\n        case METH_VARARGS:\n            return SPEC_FAIL_CALL_METH_DESCR_VARARGS;\n        case METH_VARARGS | METH_KEYWORDS:\n            return SPEC_FAIL_CALL_METH_DESCR_VARARGS_KEYWORDS;\n        case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:\n            return SPEC_FAIL_CALL_METH_DESCR_METHOD_FASTCALL_KEYWORDS;\n            /* These cases should be optimized, but return \"other\" just in case */\n        case METH_NOARGS:\n        case METH_O:\n        case METH_FASTCALL:\n        case METH_FASTCALL | METH_KEYWORDS:\n            return SPEC_FAIL_OTHER;\n        default:\n            return SPEC_FAIL_CALL_BAD_CALL_FLAGS;\n    }\n}\n#endif\n\nstatic int\nspecialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,\n                             int nargs, PyObject *kwnames)\n{\n    if (kwnames) {\n        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);\n        return -1;\n    }\n\n    switch (descr->d_method->ml_flags &\n        (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |\n        METH_KEYWORDS | METH_METHOD)) {\n        case METH_NOARGS: {\n            if (nargs != 1) {\n                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);\n                return -1;\n            }\n            instr->op.code = CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS;\n            return 0;\n        }\n        case METH_O: {\n            if (nargs != 2) {\n                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);\n                return -1;\n            }\n            PyInterpreterState *interp = _PyInterpreterState_GET();\n            PyObject *list_append = interp->callable_cache.list_append;\n            _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_CALL + 1];\n            bool pop = (next.op.code == POP_TOP);\n            int oparg = instr->op.arg;\n            if ((PyObject *)descr == list_append && oparg == 1 && pop) {\n                instr->op.code = CALL_NO_KW_LIST_APPEND;\n                return 0;\n            }\n            instr->op.code = CALL_NO_KW_METHOD_DESCRIPTOR_O;\n            return 0;\n        }\n        case METH_FASTCALL: {\n            instr->op.code = CALL_NO_KW_METHOD_DESCRIPTOR_FAST;\n            return 0;\n        }\n        case METH_FASTCALL | METH_KEYWORDS: {\n            instr->op.code = CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS;\n            return 0;\n        }\n    }\n    SPECIALIZATION_FAIL(CALL, meth_descr_call_fail_kind(descr->d_method->ml_flags));\n    return -1;\n}\n\nstatic int\nspecialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,\n                   PyObject *kwnames, bool bound_method)\n{\n    _PyCallCache *cache = (_PyCallCache *)(instr + 1);\n    PyCodeObject *code = (PyCodeObject *)func->func_code;\n    int kind = function_kind(code);\n    /* Don't specialize if PEP 523 is active */\n    if (_PyInterpreterState_GET()->eval_frame) {\n        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);\n        return -1;\n    }\n    if (kwnames) {\n        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);\n        return -1;\n    }\n    if (kind != SIMPLE_FUNCTION) {\n        SPECIALIZATION_FAIL(CALL, kind);\n        return -1;\n    }\n    int argcount = code->co_argcount;\n    int defcount = func->func_defaults == NULL ? 0 : (int)PyTuple_GET_SIZE(func->func_defaults);\n    assert(defcount <= argcount);\n    int min_args = argcount-defcount;\n    if (nargs > argcount || nargs < min_args) {\n        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);\n        return -1;\n    }\n    assert(nargs <= argcount && nargs >= min_args);\n    assert(min_args >= 0 && defcount >= 0);\n    assert(defcount == 0 || func->func_defaults != NULL);\n    int version = _PyFunction_GetVersionForCurrentState(func);\n    if (version == 0) {\n        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);\n        return -1;\n    }\n    write_u32(cache->func_version, version);\n    if (argcount == nargs) {\n        instr->op.code = bound_method ? CALL_BOUND_METHOD_EXACT_ARGS : CALL_PY_EXACT_ARGS;\n    }\n    else if (bound_method) {\n        SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);\n        return -1;\n    }\n    else {\n        instr->op.code = CALL_PY_WITH_DEFAULTS;\n    }\n    return 0;\n}\n\nstatic int\nspecialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,\n                  PyObject *kwnames)\n{\n    if (PyCFunction_GET_FUNCTION(callable) == NULL) {\n        return 1;\n    }\n    switch (PyCFunction_GET_FLAGS(callable) &\n        (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |\n        METH_KEYWORDS | METH_METHOD)) {\n        case METH_O: {\n            if (kwnames) {\n                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);\n                return -1;\n            }\n            if (nargs != 1) {\n                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);\n                return 1;\n            }\n            /* len(o) */\n            PyInterpreterState *interp = _PyInterpreterState_GET();\n            if (callable == interp->callable_cache.len) {\n                instr->op.code = CALL_NO_KW_LEN;\n                return 0;\n            }\n            instr->op.code = CALL_NO_KW_BUILTIN_O;\n            return 0;\n        }\n        case METH_FASTCALL: {\n            if (kwnames) {\n                SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);\n                return -1;\n            }\n            if (nargs == 2) {\n                /* isinstance(o1, o2) */\n                PyInterpreterState *interp = _PyInterpreterState_GET();\n                if (callable == interp->callable_cache.isinstance) {\n                    instr->op.code = CALL_NO_KW_ISINSTANCE;\n                    return 0;\n                }\n            }\n            instr->op.code = CALL_NO_KW_BUILTIN_FAST;\n            return 0;\n        }\n        case METH_FASTCALL | METH_KEYWORDS: {\n            instr->op.code = CALL_BUILTIN_FAST_WITH_KEYWORDS;\n            return 0;\n        }\n        default:\n            SPECIALIZATION_FAIL(CALL,\n                builtin_call_fail_kind(PyCFunction_GET_FLAGS(callable)));\n            return 1;\n    }\n}\n\n#ifdef Py_STATS\nstatic int\ncall_fail_kind(PyObject *callable)\n{\n    assert(!PyCFunction_CheckExact(callable));\n    assert(!PyFunction_Check(callable));\n    assert(!PyType_Check(callable));\n    assert(!Py_IS_TYPE(callable, &PyMethodDescr_Type));\n    assert(!PyMethod_Check(callable));\n    if (PyInstanceMethod_Check(callable)) {\n        return SPEC_FAIL_CALL_INSTANCE_METHOD;\n    }\n    // builtin method\n    else if (PyCMethod_Check(callable)) {\n        return SPEC_FAIL_CALL_CMETHOD;\n    }\n    else if (Py_TYPE(callable) == &PyWrapperDescr_Type) {\n        return SPEC_FAIL_CALL_OPERATOR_WRAPPER;\n    }\n    else if (Py_TYPE(callable) == &_PyMethodWrapper_Type) {\n        return SPEC_FAIL_CALL_METHOD_WRAPPER;\n    }\n    return SPEC_FAIL_OTHER;\n}\n#endif\n\n\n/* TODO:\n    - Specialize calling classes.\n*/\nvoid\n_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,\n                    PyObject *kwnames)\n{\n    assert(ENABLE_SPECIALIZATION);\n    assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL);\n    assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL);\n    _PyCallCache *cache = (_PyCallCache *)(instr + 1);\n    int fail;\n    if (PyCFunction_CheckExact(callable)) {\n        fail = specialize_c_call(callable, instr, nargs, kwnames);\n    }\n    else if (PyFunction_Check(callable)) {\n        fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs,\n                                  kwnames, false);\n    }\n    else if (PyType_Check(callable)) {\n        fail = specialize_class_call(callable, instr, nargs, kwnames);\n    }\n    else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {\n        fail = specialize_method_descriptor((PyMethodDescrObject *)callable,\n                                            instr, nargs, kwnames);\n    }\n    else if (PyMethod_Check(callable)) {\n        PyObject *func = ((PyMethodObject *)callable)->im_func;\n        if (PyFunction_Check(func)) {\n            fail = specialize_py_call((PyFunctionObject *)func,\n                                      instr, nargs+1, kwnames, true);\n        } else {\n            SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);\n            fail = -1;\n        }\n    }\n    else {\n        SPECIALIZATION_FAIL(CALL, call_fail_kind(callable));\n        fail = -1;\n    }\n    if (fail) {\n        STAT_INC(CALL, failure);\n        assert(!PyErr_Occurred());\n        instr->op.code = CALL;\n        cache->counter = adaptive_counter_backoff(cache->counter);\n    }\n    else {\n        STAT_INC(CALL, success);\n        assert(!PyErr_Occurred());\n        cache->counter = adaptive_counter_cooldown();\n    }\n}\n\n#ifdef Py_STATS\nstatic int\nbinary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)\n{\n    switch (oparg) {\n        case NB_ADD:\n        case NB_INPLACE_ADD:\n            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {\n                return SPEC_FAIL_BINARY_OP_ADD_DIFFERENT_TYPES;\n            }\n            return SPEC_FAIL_BINARY_OP_ADD_OTHER;\n        case NB_AND:\n        case NB_INPLACE_AND:\n            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {\n                return SPEC_FAIL_BINARY_OP_AND_DIFFERENT_TYPES;\n            }\n            if (PyLong_CheckExact(lhs)) {\n                return SPEC_FAIL_BINARY_OP_AND_INT;\n            }\n            return SPEC_FAIL_BINARY_OP_AND_OTHER;\n        case NB_FLOOR_DIVIDE:\n        case NB_INPLACE_FLOOR_DIVIDE:\n            return SPEC_FAIL_BINARY_OP_FLOOR_DIVIDE;\n        case NB_LSHIFT:\n        case NB_INPLACE_LSHIFT:\n            return SPEC_FAIL_BINARY_OP_LSHIFT;\n        case NB_MATRIX_MULTIPLY:\n        case NB_INPLACE_MATRIX_MULTIPLY:\n            return SPEC_FAIL_BINARY_OP_MATRIX_MULTIPLY;\n        case NB_MULTIPLY:\n        case NB_INPLACE_MULTIPLY:\n            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {\n                return SPEC_FAIL_BINARY_OP_MULTIPLY_DIFFERENT_TYPES;\n            }\n            return SPEC_FAIL_BINARY_OP_MULTIPLY_OTHER;\n        case NB_OR:\n        case NB_INPLACE_OR:\n            return SPEC_FAIL_BINARY_OP_OR;\n        case NB_POWER:\n        case NB_INPLACE_POWER:\n            return SPEC_FAIL_BINARY_OP_POWER;\n        case NB_REMAINDER:\n        case NB_INPLACE_REMAINDER:\n            return SPEC_FAIL_BINARY_OP_REMAINDER;\n        case NB_RSHIFT:\n        case NB_INPLACE_RSHIFT:\n            return SPEC_FAIL_BINARY_OP_RSHIFT;\n        case NB_SUBTRACT:\n        case NB_INPLACE_SUBTRACT:\n            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {\n                return SPEC_FAIL_BINARY_OP_SUBTRACT_DIFFERENT_TYPES;\n            }\n            return SPEC_FAIL_BINARY_OP_SUBTRACT_OTHER;\n        case NB_TRUE_DIVIDE:\n        case NB_INPLACE_TRUE_DIVIDE:\n            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {\n                return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_DIFFERENT_TYPES;\n            }\n            if (PyFloat_CheckExact(lhs)) {\n                return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_FLOAT;\n            }\n            return SPEC_FAIL_BINARY_OP_TRUE_DIVIDE_OTHER;\n        case NB_XOR:\n        case NB_INPLACE_XOR:\n            return SPEC_FAIL_BINARY_OP_XOR;\n    }\n    Py_UNREACHABLE();\n}\n#endif\n\nvoid\n_Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,\n                        int oparg, PyObject **locals)\n{\n    assert(ENABLE_SPECIALIZATION);\n    assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP);\n    _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1);\n    switch (oparg) {\n        case NB_ADD:\n        case NB_INPLACE_ADD:\n            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {\n                break;\n            }\n            if (PyUnicode_CheckExact(lhs)) {\n                _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_BINARY_OP + 1];\n                bool to_store = (next.op.code == STORE_FAST ||\n                                 next.op.code == STORE_FAST__LOAD_FAST);\n                if (to_store && locals[next.op.arg] == lhs) {\n                    instr->op.code = BINARY_OP_INPLACE_ADD_UNICODE;\n                    goto success;\n                }\n                instr->op.code = BINARY_OP_ADD_UNICODE;\n                goto success;\n            }\n            if (PyLong_CheckExact(lhs)) {\n                instr->op.code = BINARY_OP_ADD_INT;\n                goto success;\n            }\n            if (PyFloat_CheckExact(lhs)) {\n                instr->op.code = BINARY_OP_ADD_FLOAT;\n                goto success;\n            }\n            break;\n        case NB_MULTIPLY:\n        case NB_INPLACE_MULTIPLY:\n            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {\n                break;\n            }\n            if (PyLong_CheckExact(lhs)) {\n                instr->op.code = BINARY_OP_MULTIPLY_INT;\n                goto success;\n            }\n            if (PyFloat_CheckExact(lhs)) {\n                instr->op.code = BINARY_OP_MULTIPLY_FLOAT;\n                goto success;\n            }\n            break;\n        case NB_SUBTRACT:\n        case NB_INPLACE_SUBTRACT:\n            if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {\n                break;\n            }\n            if (PyLong_CheckExact(lhs)) {\n                instr->op.code = BINARY_OP_SUBTRACT_INT;\n                goto success;\n            }\n            if (PyFloat_CheckExact(lhs)) {\n                instr->op.code = BINARY_OP_SUBTRACT_FLOAT;\n                goto success;\n            }\n            break;\n    }\n    SPECIALIZATION_FAIL(BINARY_OP, binary_op_fail_kind(oparg, lhs, rhs));\n    STAT_INC(BINARY_OP, failure);\n    instr->op.code = BINARY_OP;\n    cache->counter = adaptive_counter_backoff(cache->counter);\n    return;\nsuccess:\n    STAT_INC(BINARY_OP, success);\n    cache->counter = adaptive_counter_cooldown();\n}\n\n\n#ifdef Py_STATS\nstatic int\ncompare_op_fail_kind(PyObject *lhs, PyObject *rhs)\n{\n    if (Py_TYPE(lhs) != Py_TYPE(rhs)) {\n        if (PyFloat_CheckExact(lhs) && PyLong_CheckExact(rhs)) {\n            return SPEC_FAIL_COMPARE_OP_FLOAT_LONG;\n        }\n        if (PyLong_CheckExact(lhs) && PyFloat_CheckExact(rhs)) {\n            return SPEC_FAIL_COMPARE_OP_LONG_FLOAT;\n        }\n        return SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES;\n    }\n    if (PyBytes_CheckExact(lhs)) {\n        return SPEC_FAIL_COMPARE_OP_BYTES;\n    }\n    if (PyTuple_CheckExact(lhs)) {\n        return SPEC_FAIL_COMPARE_OP_TUPLE;\n    }\n    if (PyList_CheckExact(lhs)) {\n        return SPEC_FAIL_COMPARE_OP_LIST;\n    }\n    if (PySet_CheckExact(lhs) || PyFrozenSet_CheckExact(lhs)) {\n        return SPEC_FAIL_COMPARE_OP_SET;\n    }\n    if (PyBool_Check(lhs)) {\n        return SPEC_FAIL_COMPARE_OP_BOOL;\n    }\n    if (Py_TYPE(lhs)->tp_richcompare == PyBaseObject_Type.tp_richcompare) {\n        return SPEC_FAIL_COMPARE_OP_BASEOBJECT;\n    }\n    return SPEC_FAIL_OTHER;\n}\n#endif\n\nvoid\n_Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,\n                         int oparg)\n{\n    assert(ENABLE_SPECIALIZATION);\n    assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);\n    _PyCompareOpCache *cache = (_PyCompareOpCache *)(instr + 1);\n    if (Py_TYPE(lhs) != Py_TYPE(rhs)) {\n        SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));\n        goto failure;\n    }\n    if (PyFloat_CheckExact(lhs)) {\n        instr->op.code = COMPARE_OP_FLOAT;\n        goto success;\n    }\n    if (PyLong_CheckExact(lhs)) {\n        if (_PyLong_IsCompact((PyLongObject *)lhs) && _PyLong_IsCompact((PyLongObject *)rhs)) {\n            instr->op.code = COMPARE_OP_INT;\n            goto success;\n        }\n        else {\n            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_BIG_INT);\n            goto failure;\n        }\n    }\n    if (PyUnicode_CheckExact(lhs)) {\n        int cmp = oparg >> 4;\n        if (cmp != Py_EQ && cmp != Py_NE) {\n            SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_STRING);\n            goto failure;\n        }\n        else {\n            instr->op.code = COMPARE_OP_STR;\n            goto success;\n        }\n    }\n    SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));\nfailure:\n    STAT_INC(COMPARE_OP, failure);\n    instr->op.code = COMPARE_OP;\n    cache->counter = adaptive_counter_backoff(cache->counter);\n    return;\nsuccess:\n    STAT_INC(COMPARE_OP, success);\n    cache->counter = adaptive_counter_cooldown();\n}\n\n#ifdef Py_STATS\nstatic int\nunpack_sequence_fail_kind(PyObject *seq)\n{\n    if (PySequence_Check(seq)) {\n        return SPEC_FAIL_UNPACK_SEQUENCE_SEQUENCE;\n    }\n    if (PyIter_Check(seq)) {\n        return SPEC_FAIL_UNPACK_SEQUENCE_ITERATOR;\n    }\n    return SPEC_FAIL_OTHER;\n}\n#endif\n\nvoid\n_Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, int oparg)\n{\n    assert(ENABLE_SPECIALIZATION);\n    assert(_PyOpcode_Caches[UNPACK_SEQUENCE] ==\n           INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);\n    _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)(instr + 1);\n    if (PyTuple_CheckExact(seq)) {\n        if (PyTuple_GET_SIZE(seq) != oparg) {\n            SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);\n            goto failure;\n        }\n        if (PyTuple_GET_SIZE(seq) == 2) {\n            instr->op.code = UNPACK_SEQUENCE_TWO_TUPLE;\n            goto success;\n        }\n        instr->op.code = UNPACK_SEQUENCE_TUPLE;\n        goto success;\n    }\n    if (PyList_CheckExact(seq)) {\n        if (PyList_GET_SIZE(seq) != oparg) {\n            SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);\n            goto failure;\n        }\n        instr->op.code = UNPACK_SEQUENCE_LIST;\n        goto success;\n    }\n    SPECIALIZATION_FAIL(UNPACK_SEQUENCE, unpack_sequence_fail_kind(seq));\nfailure:\n    STAT_INC(UNPACK_SEQUENCE, failure);\n    instr->op.code = UNPACK_SEQUENCE;\n    cache->counter = adaptive_counter_backoff(cache->counter);\n    return;\nsuccess:\n    STAT_INC(UNPACK_SEQUENCE, success);\n    cache->counter = adaptive_counter_cooldown();\n}\n\n#ifdef Py_STATS\n\nint\n _PySpecialization_ClassifyIterator(PyObject *iter)\n{\n    if (PyGen_CheckExact(iter)) {\n        return SPEC_FAIL_ITER_GENERATOR;\n    }\n    if (PyCoro_CheckExact(iter)) {\n        return SPEC_FAIL_ITER_COROUTINE;\n    }\n    if (PyAsyncGen_CheckExact(iter)) {\n        return SPEC_FAIL_ITER_ASYNC_GENERATOR;\n    }\n    if (PyAsyncGenASend_CheckExact(iter)) {\n        return SPEC_FAIL_ITER_ASYNC_GENERATOR_SEND;\n    }\n    PyTypeObject *t = Py_TYPE(iter);\n    if (t == &PyListIter_Type) {\n        return SPEC_FAIL_ITER_LIST;\n    }\n    if (t == &PyTupleIter_Type) {\n        return SPEC_FAIL_ITER_TUPLE;\n    }\n    if (t == &PyDictIterKey_Type) {\n        return SPEC_FAIL_ITER_DICT_KEYS;\n    }\n    if (t == &PyDictIterValue_Type) {\n        return SPEC_FAIL_ITER_DICT_VALUES;\n    }\n    if (t == &PyDictIterItem_Type) {\n        return SPEC_FAIL_ITER_DICT_ITEMS;\n    }\n    if (t == &PySetIter_Type) {\n        return SPEC_FAIL_ITER_SET;\n    }\n    if (t == &PyUnicodeIter_Type) {\n        return SPEC_FAIL_ITER_STRING;\n    }\n    if (t == &PyBytesIter_Type) {\n        return SPEC_FAIL_ITER_BYTES;\n    }\n    if (t == &PyRangeIter_Type) {\n        return SPEC_FAIL_ITER_RANGE;\n    }\n    if (t == &PyEnum_Type) {\n        return SPEC_FAIL_ITER_ENUMERATE;\n    }\n    if (t == &PyMap_Type) {\n        return SPEC_FAIL_ITER_MAP;\n    }\n    if (t == &PyZip_Type) {\n        return SPEC_FAIL_ITER_ZIP;\n    }\n    if (t == &PySeqIter_Type) {\n        return SPEC_FAIL_ITER_SEQ_ITER;\n    }\n    if (t == &PyListRevIter_Type) {\n        return SPEC_FAIL_ITER_REVERSED_LIST;\n    }\n    if (t == &_PyUnicodeASCIIIter_Type) {\n        return SPEC_FAIL_ITER_ASCII_STRING;\n    }\n    const char *name = t->tp_name;\n    if (strncmp(name, \"itertools\", 9) == 0) {\n        return SPEC_FAIL_ITER_ITERTOOLS;\n    }\n    if (strncmp(name, \"callable_iterator\", 17) == 0) {\n        return SPEC_FAIL_ITER_CALLABLE;\n    }\n    return SPEC_FAIL_OTHER;\n}\n\n#endif\n\nvoid\n_Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int oparg)\n{\n    assert(ENABLE_SPECIALIZATION);\n    assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);\n    _PyForIterCache *cache = (_PyForIterCache *)(instr + 1);\n    PyTypeObject *tp = Py_TYPE(iter);\n    if (tp == &PyListIter_Type) {\n        instr->op.code = FOR_ITER_LIST;\n        goto success;\n    }\n    else if (tp == &PyTupleIter_Type) {\n        instr->op.code = FOR_ITER_TUPLE;\n        goto success;\n    }\n    else if (tp == &PyRangeIter_Type) {\n        instr->op.code = FOR_ITER_RANGE;\n        goto success;\n    }\n    else if (tp == &PyGen_Type && oparg <= SHRT_MAX) {\n        assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR  ||\n            instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR\n        );\n        if (_PyInterpreterState_GET()->eval_frame) {\n            SPECIALIZATION_FAIL(FOR_ITER, SPEC_FAIL_OTHER);\n            goto failure;\n        }\n        instr->op.code = FOR_ITER_GEN;\n        goto success;\n    }\n    SPECIALIZATION_FAIL(FOR_ITER,\n                        _PySpecialization_ClassifyIterator(iter));\nfailure:\n    STAT_INC(FOR_ITER, failure);\n    instr->op.code = FOR_ITER;\n    cache->counter = adaptive_counter_backoff(cache->counter);\n    return;\nsuccess:\n    STAT_INC(FOR_ITER, success);\n    cache->counter = adaptive_counter_cooldown();\n}\n\nvoid\n_Py_Specialize_Send(PyObject *receiver, _Py_CODEUNIT *instr)\n{\n    assert(ENABLE_SPECIALIZATION);\n    assert(_PyOpcode_Caches[SEND] == INLINE_CACHE_ENTRIES_SEND);\n    _PySendCache *cache = (_PySendCache *)(instr + 1);\n    PyTypeObject *tp = Py_TYPE(receiver);\n    if (tp == &PyGen_Type || tp == &PyCoro_Type) {\n        if (_PyInterpreterState_GET()->eval_frame) {\n            SPECIALIZATION_FAIL(SEND, SPEC_FAIL_OTHER);\n            goto failure;\n        }\n        instr->op.code = SEND_GEN;\n        goto success;\n    }\n    SPECIALIZATION_FAIL(SEND,\n                        _PySpecialization_ClassifyIterator(receiver));\nfailure:\n    STAT_INC(SEND, failure);\n    instr->op.code = SEND;\n    cache->counter = adaptive_counter_backoff(cache->counter);\n    return;\nsuccess:\n    STAT_INC(SEND, success);\n    cache->counter = adaptive_counter_cooldown();\n}\n"
  },
  {
    "path": "Stdlib_Module_Names.h",
    "content": "// Auto-generated by Tools/build/generate_stdlib_module_names.py.\n// List used to create sys.stdlib_module_names.\n\nstatic const char* _Py_stdlib_module_names[] = {\n\"__future__\",\n\"_abc\",\n\"_aix_support\",\n\"_ast\",\n\"_asyncio\",\n\"_bisect\",\n\"_blake2\",\n\"_bz2\",\n\"_codecs\",\n\"_codecs_cn\",\n\"_codecs_hk\",\n\"_codecs_iso2022\",\n\"_codecs_jp\",\n\"_codecs_kr\",\n\"_codecs_tw\",\n\"_collections\",\n\"_collections_abc\",\n\"_compat_pickle\",\n\"_compression\",\n\"_contextvars\",\n\"_csv\",\n\"_ctypes\",\n\"_curses\",\n\"_curses_panel\",\n\"_datetime\",\n\"_dbm\",\n\"_decimal\",\n\"_elementtree\",\n\"_frozen_importlib\",\n\"_frozen_importlib_external\",\n\"_functools\",\n\"_gdbm\",\n\"_hashlib\",\n\"_heapq\",\n\"_imp\",\n\"_io\",\n\"_json\",\n\"_locale\",\n\"_lsprof\",\n\"_lzma\",\n\"_markupbase\",\n\"_md5\",\n\"_multibytecodec\",\n\"_multiprocessing\",\n\"_opcode\",\n\"_operator\",\n\"_osx_support\",\n\"_overlapped\",\n\"_pickle\",\n\"_posixshmem\",\n\"_posixsubprocess\",\n\"_py_abc\",\n\"_pydatetime\",\n\"_pydecimal\",\n\"_pyio\",\n\"_pylong\",\n\"_queue\",\n\"_random\",\n\"_scproxy\",\n\"_sha1\",\n\"_sha2\",\n\"_sha3\",\n\"_signal\",\n\"_sitebuiltins\",\n\"_socket\",\n\"_sqlite3\",\n\"_sre\",\n\"_ssl\",\n\"_stat\",\n\"_statistics\",\n\"_string\",\n\"_strptime\",\n\"_struct\",\n\"_symtable\",\n\"_thread\",\n\"_threading_local\",\n\"_tkinter\",\n\"_tokenize\",\n\"_tracemalloc\",\n\"_typing\",\n\"_uuid\",\n\"_warnings\",\n\"_weakref\",\n\"_weakrefset\",\n\"_winapi\",\n\"_zoneinfo\",\n\"abc\",\n\"antigravity\",\n\"argparse\",\n\"array\",\n\"ast\",\n\"asyncio\",\n\"atexit\",\n\"base64\",\n\"bdb\",\n\"binascii\",\n\"bisect\",\n\"builtins\",\n\"bz2\",\n\"cProfile\",\n\"calendar\",\n\"cmath\",\n\"cmd\",\n\"code\",\n\"codecs\",\n\"codeop\",\n\"collections\",\n\"colorsys\",\n\"compileall\",\n\"concurrent\",\n\"configparser\",\n\"contextlib\",\n\"contextvars\",\n\"copy\",\n\"copyreg\",\n\"csv\",\n\"ctypes\",\n\"curses\",\n\"dataclasses\",\n\"datetime\",\n\"dbm\",\n\"decimal\",\n\"difflib\",\n\"dis\",\n\"doctest\",\n\"email\",\n\"encodings\",\n\"ensurepip\",\n\"enum\",\n\"errno\",\n\"faulthandler\",\n\"fcntl\",\n\"filecmp\",\n\"fileinput\",\n\"fnmatch\",\n\"fractions\",\n\"ftplib\",\n\"functools\",\n\"gc\",\n\"genericpath\",\n\"getopt\",\n\"getpass\",\n\"gettext\",\n\"glob\",\n\"graphlib\",\n\"grp\",\n\"gzip\",\n\"hashlib\",\n\"heapq\",\n\"hmac\",\n\"html\",\n\"http\",\n\"idlelib\",\n\"imaplib\",\n\"importlib\",\n\"inspect\",\n\"io\",\n\"ipaddress\",\n\"itertools\",\n\"json\",\n\"keyword\",\n\"linecache\",\n\"locale\",\n\"logging\",\n\"lzma\",\n\"mailbox\",\n\"marshal\",\n\"math\",\n\"mimetypes\",\n\"mmap\",\n\"modulefinder\",\n\"msvcrt\",\n\"multiprocessing\",\n\"netrc\",\n\"nt\",\n\"ntpath\",\n\"nturl2path\",\n\"numbers\",\n\"opcode\",\n\"operator\",\n\"optparse\",\n\"os\",\n\"pathlib\",\n\"pdb\",\n\"pickle\",\n\"pickletools\",\n\"pkgutil\",\n\"platform\",\n\"plistlib\",\n\"poplib\",\n\"posix\",\n\"posixpath\",\n\"pprint\",\n\"profile\",\n\"pstats\",\n\"pty\",\n\"pwd\",\n\"py_compile\",\n\"pyclbr\",\n\"pydoc\",\n\"pydoc_data\",\n\"pyexpat\",\n\"queue\",\n\"quopri\",\n\"random\",\n\"re\",\n\"readline\",\n\"reprlib\",\n\"resource\",\n\"rlcompleter\",\n\"runpy\",\n\"sched\",\n\"secrets\",\n\"select\",\n\"selectors\",\n\"shelve\",\n\"shlex\",\n\"shutil\",\n\"signal\",\n\"site\",\n\"smtplib\",\n\"socket\",\n\"socketserver\",\n\"sqlite3\",\n\"sre_compile\",\n\"sre_constants\",\n\"sre_parse\",\n\"ssl\",\n\"stat\",\n\"statistics\",\n\"string\",\n\"stringprep\",\n\"struct\",\n\"subprocess\",\n\"symtable\",\n\"sys\",\n\"sysconfig\",\n\"syslog\",\n\"tabnanny\",\n\"tarfile\",\n\"tempfile\",\n\"termios\",\n\"textwrap\",\n\"this\",\n\"threading\",\n\"time\",\n\"timeit\",\n\"tkinter\",\n\"token\",\n\"tokenize\",\n\"tomllib\",\n\"trace\",\n\"traceback\",\n\"tracemalloc\",\n\"tty\",\n\"turtle\",\n\"turtledemo\",\n\"types\",\n\"typing\",\n\"unicodedata\",\n\"unittest\",\n\"urllib\",\n\"uuid\",\n\"venv\",\n\"warnings\",\n\"wave\",\n\"weakref\",\n\"webbrowser\",\n\"winreg\",\n\"winsound\",\n\"wsgiref\",\n\"xml\",\n\"xmlrpc\",\n\"zipapp\",\n\"zipfile\",\n\"zipimport\",\n\"zlib\",\n\"zoneinfo\",\n};\n"
  },
  {
    "path": "StrucMember.c",
    "content": "\n/* Map C struct members to Python object attributes */\n\n#include \"Python.h\"\n#include \"structmember.h\"         // PyMemberDef\n\nPyObject *\nPyMember_GetOne(const char *obj_addr, PyMemberDef *l)\n{\n    PyObject *v;\n    if (l->flags & Py_RELATIVE_OFFSET) {\n        PyErr_SetString(\n            PyExc_SystemError,\n            \"PyMember_GetOne used with Py_RELATIVE_OFFSET\");\n        return NULL;\n    }\n\n    const char* addr = obj_addr + l->offset;\n    switch (l->type) {\n    case T_BOOL:\n        v = PyBool_FromLong(*(char*)addr);\n        break;\n    case T_BYTE:\n        v = PyLong_FromLong(*(char*)addr);\n        break;\n    case T_UBYTE:\n        v = PyLong_FromUnsignedLong(*(unsigned char*)addr);\n        break;\n    case T_SHORT:\n        v = PyLong_FromLong(*(short*)addr);\n        break;\n    case T_USHORT:\n        v = PyLong_FromUnsignedLong(*(unsigned short*)addr);\n        break;\n    case T_INT:\n        v = PyLong_FromLong(*(int*)addr);\n        break;\n    case T_UINT:\n        v = PyLong_FromUnsignedLong(*(unsigned int*)addr);\n        break;\n    case T_LONG:\n        v = PyLong_FromLong(*(long*)addr);\n        break;\n    case T_ULONG:\n        v = PyLong_FromUnsignedLong(*(unsigned long*)addr);\n        break;\n    case T_PYSSIZET:\n        v = PyLong_FromSsize_t(*(Py_ssize_t*)addr);\n        break;\n    case T_FLOAT:\n        v = PyFloat_FromDouble((double)*(float*)addr);\n        break;\n    case T_DOUBLE:\n        v = PyFloat_FromDouble(*(double*)addr);\n        break;\n    case T_STRING:\n        if (*(char**)addr == NULL) {\n            v = Py_NewRef(Py_None);\n        }\n        else\n            v = PyUnicode_FromString(*(char**)addr);\n        break;\n    case T_STRING_INPLACE:\n        v = PyUnicode_FromString((char*)addr);\n        break;\n    case T_CHAR:\n        v = PyUnicode_FromStringAndSize((char*)addr, 1);\n        break;\n    case T_OBJECT:\n        v = *(PyObject **)addr;\n        if (v == NULL)\n            v = Py_None;\n        Py_INCREF(v);\n        break;\n    case T_OBJECT_EX:\n        v = *(PyObject **)addr;\n        if (v == NULL) {\n            PyObject *obj = (PyObject *)obj_addr;\n            PyTypeObject *tp = Py_TYPE(obj);\n            PyErr_Format(PyExc_AttributeError,\n                         \"'%.200s' object has no attribute '%s'\",\n                         tp->tp_name, l->name);\n        }\n        Py_XINCREF(v);\n        break;\n    case T_LONGLONG:\n        v = PyLong_FromLongLong(*(long long *)addr);\n        break;\n    case T_ULONGLONG:\n        v = PyLong_FromUnsignedLongLong(*(unsigned long long *)addr);\n        break;\n    case T_NONE:\n        v = Py_NewRef(Py_None);\n        break;\n    default:\n        PyErr_SetString(PyExc_SystemError, \"bad memberdescr type\");\n        v = NULL;\n    }\n    return v;\n}\n\n#define WARN(msg)                                               \\\n    do {                                                        \\\n    if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0)         \\\n        return -1;                                              \\\n    } while (0)\n\nint\nPyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)\n{\n    PyObject *oldv;\n    if (l->flags & Py_RELATIVE_OFFSET) {\n        PyErr_SetString(\n            PyExc_SystemError,\n            \"PyMember_SetOne used with Py_RELATIVE_OFFSET\");\n        return -1;\n    }\n\n    addr += l->offset;\n\n    if ((l->flags & READONLY))\n    {\n        PyErr_SetString(PyExc_AttributeError, \"readonly attribute\");\n        return -1;\n    }\n    if (v == NULL) {\n        if (l->type == T_OBJECT_EX) {\n            /* Check if the attribute is set. */\n            if (*(PyObject **)addr == NULL) {\n                PyErr_SetString(PyExc_AttributeError, l->name);\n                return -1;\n            }\n        }\n        else if (l->type != T_OBJECT) {\n            PyErr_SetString(PyExc_TypeError,\n                            \"can't delete numeric/char attribute\");\n            return -1;\n        }\n    }\n    switch (l->type) {\n    case T_BOOL:{\n        if (!PyBool_Check(v)) {\n            PyErr_SetString(PyExc_TypeError,\n                            \"attribute value type must be bool\");\n            return -1;\n        }\n        if (v == Py_True)\n            *(char*)addr = (char) 1;\n        else\n            *(char*)addr = (char) 0;\n        break;\n        }\n    case T_BYTE:{\n        long long_val = PyLong_AsLong(v);\n        if ((long_val == -1) && PyErr_Occurred())\n            return -1;\n        *(char*)addr = (char)long_val;\n        /* XXX: For compatibility, only warn about truncations\n           for now. */\n        if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))\n            WARN(\"Truncation of value to char\");\n        break;\n        }\n    case T_UBYTE:{\n        long long_val = PyLong_AsLong(v);\n        if ((long_val == -1) && PyErr_Occurred())\n            return -1;\n        *(unsigned char*)addr = (unsigned char)long_val;\n        if ((long_val > UCHAR_MAX) || (long_val < 0))\n            WARN(\"Truncation of value to unsigned char\");\n        break;\n        }\n    case T_SHORT:{\n        long long_val = PyLong_AsLong(v);\n        if ((long_val == -1) && PyErr_Occurred())\n            return -1;\n        *(short*)addr = (short)long_val;\n        if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))\n            WARN(\"Truncation of value to short\");\n        break;\n        }\n    case T_USHORT:{\n        long long_val = PyLong_AsLong(v);\n        if ((long_val == -1) && PyErr_Occurred())\n            return -1;\n        *(unsigned short*)addr = (unsigned short)long_val;\n        if ((long_val > USHRT_MAX) || (long_val < 0))\n            WARN(\"Truncation of value to unsigned short\");\n        break;\n        }\n    case T_INT:{\n        long long_val = PyLong_AsLong(v);\n        if ((long_val == -1) && PyErr_Occurred())\n            return -1;\n        *(int *)addr = (int)long_val;\n        if ((long_val > INT_MAX) || (long_val < INT_MIN))\n            WARN(\"Truncation of value to int\");\n        break;\n        }\n    case T_UINT:{\n        unsigned long ulong_val = PyLong_AsUnsignedLong(v);\n        if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) {\n            /* XXX: For compatibility, accept negative int values\n               as well. */\n            PyErr_Clear();\n            ulong_val = PyLong_AsLong(v);\n            if ((ulong_val == (unsigned long)-1) &&\n                PyErr_Occurred())\n                return -1;\n            *(unsigned int *)addr = (unsigned int)ulong_val;\n            WARN(\"Writing negative value into unsigned field\");\n        } else\n            *(unsigned int *)addr = (unsigned int)ulong_val;\n        if (ulong_val > UINT_MAX)\n            WARN(\"Truncation of value to unsigned int\");\n        break;\n        }\n    case T_LONG:{\n        *(long*)addr = PyLong_AsLong(v);\n        if ((*(long*)addr == -1) && PyErr_Occurred())\n            return -1;\n        break;\n        }\n    case T_ULONG:{\n        *(unsigned long*)addr = PyLong_AsUnsignedLong(v);\n        if ((*(unsigned long*)addr == (unsigned long)-1)\n            && PyErr_Occurred()) {\n            /* XXX: For compatibility, accept negative int values\n               as well. */\n            PyErr_Clear();\n            *(unsigned long*)addr = PyLong_AsLong(v);\n            if ((*(unsigned long*)addr == (unsigned long)-1)\n                && PyErr_Occurred())\n                return -1;\n            WARN(\"Writing negative value into unsigned field\");\n        }\n        break;\n        }\n    case T_PYSSIZET:{\n        *(Py_ssize_t*)addr = PyLong_AsSsize_t(v);\n        if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)\n            && PyErr_Occurred())\n                        return -1;\n        break;\n        }\n    case T_FLOAT:{\n        double double_val = PyFloat_AsDouble(v);\n        if ((double_val == -1) && PyErr_Occurred())\n            return -1;\n        *(float*)addr = (float)double_val;\n        break;\n        }\n    case T_DOUBLE:\n        *(double*)addr = PyFloat_AsDouble(v);\n        if ((*(double*)addr == -1) && PyErr_Occurred())\n            return -1;\n        break;\n    case T_OBJECT:\n    case T_OBJECT_EX:\n        oldv = *(PyObject **)addr;\n        *(PyObject **)addr = Py_XNewRef(v);\n        Py_XDECREF(oldv);\n        break;\n    case T_CHAR: {\n        const char *string;\n        Py_ssize_t len;\n\n        string = PyUnicode_AsUTF8AndSize(v, &len);\n        if (string == NULL || len != 1) {\n            PyErr_BadArgument();\n            return -1;\n        }\n        *(char*)addr = string[0];\n        break;\n        }\n    case T_STRING:\n    case T_STRING_INPLACE:\n        PyErr_SetString(PyExc_TypeError, \"readonly attribute\");\n        return -1;\n    case T_LONGLONG:{\n        long long value;\n        *(long long*)addr = value = PyLong_AsLongLong(v);\n        if ((value == -1) && PyErr_Occurred())\n            return -1;\n        break;\n        }\n    case T_ULONGLONG:{\n        unsigned long long value;\n        /* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong\n            doesn't ??? */\n        if (PyLong_Check(v))\n            *(unsigned long long*)addr = value = PyLong_AsUnsignedLongLong(v);\n        else\n            *(unsigned long long*)addr = value = PyLong_AsLong(v);\n        if ((value == (unsigned long long)-1) && PyErr_Occurred())\n            return -1;\n        break;\n        }\n    default:\n        PyErr_Format(PyExc_SystemError,\n                     \"bad memberdescr type for %s\", l->name);\n        return -1;\n    }\n    return 0;\n}\n"
  },
  {
    "path": "Suggestions.c",
    "content": "#include \"Python.h\"\n#include \"pycore_frame.h\"\n#include \"pycore_runtime.h\"         // _PyRuntime\n#include \"pycore_global_objects.h\"  // _Py_ID()\n\n#include \"pycore_pyerrors.h\"\n#include \"pycore_code.h\"        // _PyCode_GetVarnames()\n#include \"stdlib_module_names.h\"  // _Py_stdlib_module_names\n\n#define MAX_CANDIDATE_ITEMS 750\n#define MAX_STRING_SIZE 40\n\n#define MOVE_COST 2\n#define CASE_COST 1\n\n#define LEAST_FIVE_BITS(n) ((n) & 31)\n\nstatic inline int\nsubstitution_cost(char a, char b)\n{\n    if (LEAST_FIVE_BITS(a) != LEAST_FIVE_BITS(b)) {\n        // Not the same, not a case flip.\n        return MOVE_COST;\n    }\n    if (a == b) {\n        return 0;\n    }\n    if ('A' <= a && a <= 'Z') {\n        a += ('a' - 'A');\n    }\n    if ('A' <= b && b <= 'Z') {\n        b += ('a' - 'A');\n    }\n    if (a == b) {\n        return CASE_COST;\n    }\n    return MOVE_COST;\n}\n\n/* Calculate the Levenshtein distance between string1 and string2 */\nstatic Py_ssize_t\nlevenshtein_distance(const char *a, size_t a_size,\n                     const char *b, size_t b_size,\n                     size_t max_cost, size_t *buffer)\n{\n    // Both strings are the same (by identity)\n    if (a == b) {\n        return 0;\n    }\n\n    // Trim away common affixes.\n    while (a_size && b_size && a[0] == b[0]) {\n        a++; a_size--;\n        b++; b_size--;\n    }\n    while (a_size && b_size && a[a_size-1] == b[b_size-1]) {\n        a_size--;\n        b_size--;\n    }\n    if (a_size == 0 || b_size == 0) {\n        return (a_size + b_size) * MOVE_COST;\n    }\n    if (a_size > MAX_STRING_SIZE || b_size > MAX_STRING_SIZE) {\n        return max_cost + 1;\n    }\n\n    // Prefer shorter buffer\n    if (b_size < a_size) {\n        const char *t = a; a = b; b = t;\n        size_t t_size = a_size; a_size = b_size; b_size = t_size;\n    }\n\n    // quick fail when a match is impossible.\n    if ((b_size - a_size) * MOVE_COST > max_cost) {\n        return max_cost + 1;\n    }\n\n    // Instead of producing the whole traditional len(a)-by-len(b)\n    // matrix, we can update just one row in place.\n    // Initialize the buffer row\n    size_t tmp = MOVE_COST;\n    for (size_t i = 0; i < a_size; i++) {\n        // cost from b[:0] to a[:i+1]\n        buffer[i] = tmp;\n        tmp += MOVE_COST;\n    }\n\n    size_t result = 0;\n    for (size_t b_index = 0; b_index < b_size; b_index++) {\n        char code = b[b_index];\n        // cost(b[:b_index], a[:0]) == b_index * MOVE_COST\n        size_t distance = result = b_index * MOVE_COST;\n        size_t minimum = SIZE_MAX;\n        for (size_t index = 0; index < a_size; index++) {\n\n            // cost(b[:b_index+1], a[:index+1]) = min(\n            //     // 1) substitute\n            //     cost(b[:b_index], a[:index])\n            //         + substitution_cost(b[b_index], a[index]),\n            //     // 2) delete from b\n            //     cost(b[:b_index], a[:index+1]) + MOVE_COST,\n            //     // 3) delete from a\n            //     cost(b[:b_index+1], a[index]) + MOVE_COST\n            // )\n\n            // 1) Previous distance in this row is cost(b[:b_index], a[:index])\n            size_t substitute = distance + substitution_cost(code, a[index]);\n            // 2) cost(b[:b_index], a[:index+1]) from previous row\n            distance = buffer[index];\n            // 3) existing result is cost(b[:b_index+1], a[index])\n\n            size_t insert_delete = Py_MIN(result, distance) + MOVE_COST;\n            result = Py_MIN(insert_delete, substitute);\n\n            // cost(b[:b_index+1], a[:index+1])\n            buffer[index] = result;\n            if (result < minimum) {\n                minimum = result;\n            }\n        }\n        if (minimum > max_cost) {\n            // Everything in this row is too big, so bail early.\n            return max_cost + 1;\n        }\n    }\n    return result;\n}\n\nstatic inline PyObject *\ncalculate_suggestions(PyObject *dir,\n                      PyObject *name)\n{\n    assert(!PyErr_Occurred());\n    assert(PyList_CheckExact(dir));\n\n    Py_ssize_t dir_size = PyList_GET_SIZE(dir);\n    if (dir_size >= MAX_CANDIDATE_ITEMS) {\n        return NULL;\n    }\n\n    Py_ssize_t suggestion_distance = PY_SSIZE_T_MAX;\n    PyObject *suggestion = NULL;\n    Py_ssize_t name_size;\n    const char *name_str = PyUnicode_AsUTF8AndSize(name, &name_size);\n    if (name_str == NULL) {\n        return NULL;\n    }\n    size_t *buffer = PyMem_New(size_t, MAX_STRING_SIZE);\n    if (buffer == NULL) {\n        return PyErr_NoMemory();\n    }\n    for (int i = 0; i < dir_size; ++i) {\n        PyObject *item = PyList_GET_ITEM(dir, i);\n        Py_ssize_t item_size;\n        const char *item_str = PyUnicode_AsUTF8AndSize(item, &item_size);\n        if (item_str == NULL) {\n            PyMem_Free(buffer);\n            return NULL;\n        }\n        if (PyUnicode_CompareWithASCIIString(name, item_str) == 0) {\n            continue;\n        }\n        // No more than 1/3 of the involved characters should need changed.\n        Py_ssize_t max_distance = (name_size + item_size + 3) * MOVE_COST / 6;\n        // Don't take matches we've already beaten.\n        max_distance = Py_MIN(max_distance, suggestion_distance - 1);\n        Py_ssize_t current_distance =\n            levenshtein_distance(name_str, name_size, item_str,\n                                 item_size, max_distance, buffer);\n        if (current_distance > max_distance) {\n            continue;\n        }\n        if (!suggestion || current_distance < suggestion_distance) {\n            suggestion = item;\n            suggestion_distance = current_distance;\n        }\n    }\n    PyMem_Free(buffer);\n    return Py_XNewRef(suggestion);\n}\n\nstatic PyObject *\nget_suggestions_for_attribute_error(PyAttributeErrorObject *exc)\n{\n    PyObject *name = exc->name; // borrowed reference\n    PyObject *obj = exc->obj; // borrowed reference\n\n    // Abort if we don't have an attribute name or we have an invalid one\n    if (name == NULL || obj == NULL || !PyUnicode_CheckExact(name)) {\n        return NULL;\n    }\n\n    PyObject *dir = PyObject_Dir(obj);\n    if (dir == NULL) {\n        return NULL;\n    }\n\n    PyObject *suggestions = calculate_suggestions(dir, name);\n    Py_DECREF(dir);\n    return suggestions;\n}\n\nstatic PyObject *\noffer_suggestions_for_attribute_error(PyAttributeErrorObject *exc)\n{\n    PyObject* suggestion = get_suggestions_for_attribute_error(exc);\n    if (suggestion == NULL) {\n        return NULL;\n    }\n    // Add a trailer \". Did you mean: (...)?\"\n    PyObject* result = PyUnicode_FromFormat(\". Did you mean: %R?\", suggestion);\n    Py_DECREF(suggestion);\n    return result;\n}\n\nstatic PyObject *\nget_suggestions_for_name_error(PyObject* name, PyFrameObject* frame)\n{\n    PyCodeObject *code = PyFrame_GetCode(frame);\n    assert(code != NULL && code->co_localsplusnames != NULL);\n\n    PyObject *varnames = _PyCode_GetVarnames(code);\n    if (varnames == NULL) {\n        return NULL;\n    }\n    PyObject *dir = PySequence_List(varnames);\n    Py_DECREF(varnames);\n    Py_DECREF(code);\n    if (dir == NULL) {\n        return NULL;\n    }\n\n    // Are we inside a method and the instance has an attribute called 'name'?\n    if (PySequence_Contains(dir, &_Py_ID(self)) > 0) {\n        PyObject* locals = PyFrame_GetLocals(frame);\n        if (!locals) {\n            goto error;\n        }\n        PyObject* self = PyDict_GetItem(locals, &_Py_ID(self)); /* borrowed */\n        Py_DECREF(locals);\n        if (!self) {\n            goto error;\n        }\n\n        if (PyObject_HasAttr(self, name)) {\n            Py_DECREF(dir);\n            return PyUnicode_FromFormat(\"self.%S\", name);\n        }\n    }\n\n    PyObject *suggestions = calculate_suggestions(dir, name);\n    Py_DECREF(dir);\n    if (suggestions != NULL) {\n        return suggestions;\n    }\n\n    dir = PySequence_List(frame->f_frame->f_globals);\n    if (dir == NULL) {\n        return NULL;\n    }\n    suggestions = calculate_suggestions(dir, name);\n    Py_DECREF(dir);\n    if (suggestions != NULL) {\n        return suggestions;\n    }\n\n    dir = PySequence_List(frame->f_frame->f_builtins);\n    if (dir == NULL) {\n        return NULL;\n    }\n    suggestions = calculate_suggestions(dir, name);\n    Py_DECREF(dir);\n\n    return suggestions;\n\nerror:\n    Py_DECREF(dir);\n    return NULL;\n}\n\nstatic bool\nis_name_stdlib_module(PyObject* name)\n{\n    const char* the_name = PyUnicode_AsUTF8(name);\n    Py_ssize_t len = Py_ARRAY_LENGTH(_Py_stdlib_module_names);\n    for (Py_ssize_t i = 0; i < len; i++) {\n        if (strcmp(the_name, _Py_stdlib_module_names[i]) == 0) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\nstatic PyObject *\noffer_suggestions_for_name_error(PyNameErrorObject *exc)\n{\n    PyObject *name = exc->name; // borrowed reference\n    PyTracebackObject *traceback = (PyTracebackObject *) exc->traceback; // borrowed reference\n    // Abort if we don't have a variable name or we have an invalid one\n    // or if we don't have a traceback to work with\n    if (name == NULL || !PyUnicode_CheckExact(name) ||\n        traceback == NULL || !Py_IS_TYPE(traceback, &PyTraceBack_Type)\n    ) {\n        return NULL;\n    }\n\n    // Move to the traceback of the exception\n    while (1) {\n        PyTracebackObject *next = traceback->tb_next;\n        if (next == NULL || !Py_IS_TYPE(next, &PyTraceBack_Type)) {\n            break;\n        }\n        else {\n            traceback = next;\n        }\n    }\n\n    PyFrameObject *frame = traceback->tb_frame;\n    assert(frame != NULL);\n\n    PyObject* suggestion = get_suggestions_for_name_error(name, frame);\n    bool is_stdlib_module = is_name_stdlib_module(name);\n\n    if (suggestion == NULL && !is_stdlib_module) {\n        return NULL;\n    }\n\n    // Add a trailer \". Did you mean: (...)?\"\n    PyObject* result = NULL;\n    if (!is_stdlib_module) {\n        result = PyUnicode_FromFormat(\". Did you mean: %R?\", suggestion);\n    } else if (suggestion == NULL) {\n        result = PyUnicode_FromFormat(\". Did you forget to import %R?\", name);\n    } else {\n        result = PyUnicode_FromFormat(\". Did you mean: %R? Or did you forget to import %R?\", suggestion, name);\n    }\n    Py_XDECREF(suggestion);\n    return result;\n}\n\nstatic PyObject *\noffer_suggestions_for_import_error(PyImportErrorObject *exc)\n{\n    PyObject *mod_name = exc->name; // borrowed reference\n    PyObject *name = exc->name_from; // borrowed reference\n    if (name == NULL || mod_name == NULL || name == Py_None ||\n        !PyUnicode_CheckExact(name) || !PyUnicode_CheckExact(mod_name)) {\n        return NULL;\n    }\n\n    PyObject* mod = PyImport_GetModule(mod_name);\n    if (mod == NULL) {\n        return NULL;\n    }\n\n    PyObject *dir = PyObject_Dir(mod);\n    Py_DECREF(mod);\n    if (dir == NULL) {\n        return NULL;\n    }\n\n    PyObject *suggestion = calculate_suggestions(dir, name);\n    Py_DECREF(dir);\n    if (!suggestion) {\n        return NULL;\n    }\n\n    PyObject* result = PyUnicode_FromFormat(\". Did you mean: %R?\", suggestion);\n    Py_DECREF(suggestion);\n    return result;\n}\n\n// Offer suggestions for a given exception. Returns a python string object containing the\n// suggestions. This function returns NULL if no suggestion was found or if an exception happened,\n// users must call PyErr_Occurred() to disambiguate.\nPyObject *\n_Py_Offer_Suggestions(PyObject *exception)\n{\n    PyObject *result = NULL;\n    assert(!PyErr_Occurred());\n    if (Py_IS_TYPE(exception, (PyTypeObject*)PyExc_AttributeError)) {\n        result = offer_suggestions_for_attribute_error((PyAttributeErrorObject *) exception);\n    } else if (Py_IS_TYPE(exception, (PyTypeObject*)PyExc_NameError)) {\n        result = offer_suggestions_for_name_error((PyNameErrorObject *) exception);\n    } else if (Py_IS_TYPE(exception, (PyTypeObject*)PyExc_ImportError)) {\n        result = offer_suggestions_for_import_error((PyImportErrorObject *) exception);\n    }\n    return result;\n}\n\nPy_ssize_t\n_Py_UTF8_Edit_Cost(PyObject *a, PyObject *b, Py_ssize_t max_cost)\n{\n    assert(PyUnicode_Check(a) && PyUnicode_Check(b));\n    Py_ssize_t size_a, size_b;\n    const char *utf8_a = PyUnicode_AsUTF8AndSize(a, &size_a);\n    if (utf8_a == NULL) {\n        return -1;\n    }\n    const char *utf8_b = PyUnicode_AsUTF8AndSize(b, &size_b);\n    if (utf8_b == NULL) {\n        return -1;\n    }\n    if (max_cost == -1) {\n        max_cost = MOVE_COST * Py_MAX(size_a, size_b);\n    }\n    size_t *buffer = PyMem_New(size_t, MAX_STRING_SIZE);\n    if (buffer == NULL) {\n        PyErr_NoMemory();\n        return -1;\n    }\n    Py_ssize_t res = levenshtein_distance(utf8_a, size_a,\n                                    utf8_b, size_b, max_cost, buffer);\n    PyMem_Free(buffer);\n    return res;\n}\n"
  },
  {
    "path": "SyMTable.c",
    "content": "#include \"Python.h\"\n#include \"pycore_ast.h\"           // identifier, stmt_ty\n#include \"pycore_parser.h\"        // _PyParser_ASTFromString()\n#include \"pycore_pystate.h\"       // _PyThreadState_GET()\n#include \"pycore_symtable.h\"      // PySTEntryObject\n#include \"structmember.h\"         // PyMemberDef\n\n/* error strings used for warnings */\n#define GLOBAL_PARAM \\\n\"name '%U' is parameter and global\"\n\n#define NONLOCAL_PARAM \\\n\"name '%U' is parameter and nonlocal\"\n\n#define GLOBAL_AFTER_ASSIGN \\\n\"name '%U' is assigned to before global declaration\"\n\n#define NONLOCAL_AFTER_ASSIGN \\\n\"name '%U' is assigned to before nonlocal declaration\"\n\n#define GLOBAL_AFTER_USE \\\n\"name '%U' is used prior to global declaration\"\n\n#define NONLOCAL_AFTER_USE \\\n\"name '%U' is used prior to nonlocal declaration\"\n\n#define GLOBAL_ANNOT \\\n\"annotated name '%U' can't be global\"\n\n#define NONLOCAL_ANNOT \\\n\"annotated name '%U' can't be nonlocal\"\n\n#define IMPORT_STAR_WARNING \"import * only allowed at module level\"\n\n#define NAMED_EXPR_COMP_IN_CLASS \\\n\"assignment expression within a comprehension cannot be used in a class body\"\n\n#define NAMED_EXPR_COMP_IN_TYPEVAR_BOUND \\\n\"assignment expression within a comprehension cannot be used in a TypeVar bound\"\n\n#define NAMED_EXPR_COMP_IN_TYPEALIAS \\\n\"assignment expression within a comprehension cannot be used in a type alias\"\n\n#define NAMED_EXPR_COMP_IN_TYPEPARAM \\\n\"assignment expression within a comprehension cannot be used within the definition of a generic\"\n\n#define NAMED_EXPR_COMP_CONFLICT \\\n\"assignment expression cannot rebind comprehension iteration variable '%U'\"\n\n#define NAMED_EXPR_COMP_INNER_LOOP_CONFLICT \\\n\"comprehension inner loop cannot rebind assignment expression target '%U'\"\n\n#define NAMED_EXPR_COMP_ITER_EXPR \\\n\"assignment expression cannot be used in a comprehension iterable expression\"\n\n#define ANNOTATION_NOT_ALLOWED \\\n\"%s cannot be used within an annotation\"\n\n#define TYPEVAR_BOUND_NOT_ALLOWED \\\n\"%s cannot be used within a TypeVar bound\"\n\n#define TYPEALIAS_NOT_ALLOWED \\\n\"%s cannot be used within a type alias\"\n\n#define TYPEPARAM_NOT_ALLOWED \\\n\"%s cannot be used within the definition of a generic\"\n\n#define DUPLICATE_TYPE_PARAM \\\n\"duplicate type parameter '%U'\"\n\n\n#define LOCATION(x) \\\n (x)->lineno, (x)->col_offset, (x)->end_lineno, (x)->end_col_offset\n\n#define ST_LOCATION(x) \\\n (x)->ste_lineno, (x)->ste_col_offset, (x)->ste_end_lineno, (x)->ste_end_col_offset\n\nstatic PySTEntryObject *\nste_new(struct symtable *st, identifier name, _Py_block_ty block,\n        void *key, int lineno, int col_offset,\n        int end_lineno, int end_col_offset)\n{\n    PySTEntryObject *ste = NULL;\n    PyObject *k = NULL;\n\n    k = PyLong_FromVoidPtr(key);\n    if (k == NULL)\n        goto fail;\n    ste = PyObject_New(PySTEntryObject, &PySTEntry_Type);\n    if (ste == NULL) {\n        Py_DECREF(k);\n        goto fail;\n    }\n    ste->ste_table = st;\n    ste->ste_id = k; /* ste owns reference to k */\n\n    ste->ste_name = Py_NewRef(name);\n\n    ste->ste_symbols = NULL;\n    ste->ste_varnames = NULL;\n    ste->ste_children = NULL;\n\n    ste->ste_directives = NULL;\n\n    ste->ste_type = block;\n    ste->ste_nested = 0;\n    ste->ste_free = 0;\n    ste->ste_varargs = 0;\n    ste->ste_varkeywords = 0;\n    ste->ste_opt_lineno = 0;\n    ste->ste_opt_col_offset = 0;\n    ste->ste_lineno = lineno;\n    ste->ste_col_offset = col_offset;\n    ste->ste_end_lineno = end_lineno;\n    ste->ste_end_col_offset = end_col_offset;\n\n    if (st->st_cur != NULL &&\n        (st->st_cur->ste_nested ||\n         _PyST_IsFunctionLike(st->st_cur)))\n        ste->ste_nested = 1;\n    ste->ste_child_free = 0;\n    ste->ste_generator = 0;\n    ste->ste_coroutine = 0;\n    ste->ste_comprehension = NoComprehension;\n    ste->ste_returns_value = 0;\n    ste->ste_needs_class_closure = 0;\n    ste->ste_comp_inlined = 0;\n    ste->ste_comp_iter_target = 0;\n    ste->ste_can_see_class_scope = 0;\n    ste->ste_comp_iter_expr = 0;\n    ste->ste_needs_classdict = 0;\n\n    ste->ste_symbols = PyDict_New();\n    ste->ste_varnames = PyList_New(0);\n    ste->ste_children = PyList_New(0);\n    if (ste->ste_symbols == NULL\n        || ste->ste_varnames == NULL\n        || ste->ste_children == NULL)\n        goto fail;\n\n    if (PyDict_SetItem(st->st_blocks, ste->ste_id, (PyObject *)ste) < 0)\n        goto fail;\n\n    return ste;\n fail:\n    Py_XDECREF(ste);\n    return NULL;\n}\n\nstatic PyObject *\nste_repr(PySTEntryObject *ste)\n{\n    return PyUnicode_FromFormat(\"<symtable entry %U(%ld), line %d>\",\n                                ste->ste_name,\n                                PyLong_AS_LONG(ste->ste_id), ste->ste_lineno);\n}\n\nstatic void\nste_dealloc(PySTEntryObject *ste)\n{\n    ste->ste_table = NULL;\n    Py_XDECREF(ste->ste_id);\n    Py_XDECREF(ste->ste_name);\n    Py_XDECREF(ste->ste_symbols);\n    Py_XDECREF(ste->ste_varnames);\n    Py_XDECREF(ste->ste_children);\n    Py_XDECREF(ste->ste_directives);\n    PyObject_Free(ste);\n}\n\n#define OFF(x) offsetof(PySTEntryObject, x)\n\nstatic PyMemberDef ste_memberlist[] = {\n    {\"id\",       T_OBJECT, OFF(ste_id), READONLY},\n    {\"name\",     T_OBJECT, OFF(ste_name), READONLY},\n    {\"symbols\",  T_OBJECT, OFF(ste_symbols), READONLY},\n    {\"varnames\", T_OBJECT, OFF(ste_varnames), READONLY},\n    {\"children\", T_OBJECT, OFF(ste_children), READONLY},\n    {\"nested\",   T_INT,    OFF(ste_nested), READONLY},\n    {\"type\",     T_INT,    OFF(ste_type), READONLY},\n    {\"lineno\",   T_INT,    OFF(ste_lineno), READONLY},\n    {NULL}\n};\n\nPyTypeObject PySTEntry_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"symtable entry\",\n    sizeof(PySTEntryObject),\n    0,\n    (destructor)ste_dealloc,                /* tp_dealloc */\n    0,                                      /* tp_vectorcall_offset */\n    0,                                         /* tp_getattr */\n    0,                                          /* tp_setattr */\n    0,                                          /* tp_as_async */\n    (reprfunc)ste_repr,                         /* tp_repr */\n    0,                                          /* tp_as_number */\n    0,                                          /* tp_as_sequence */\n    0,                                          /* tp_as_mapping */\n    0,                                          /* tp_hash */\n    0,                                          /* tp_call */\n    0,                                          /* tp_str */\n    PyObject_GenericGetAttr,                    /* tp_getattro */\n    0,                                          /* tp_setattro */\n    0,                                          /* tp_as_buffer */\n    Py_TPFLAGS_DEFAULT,                         /* tp_flags */\n    0,                                          /* tp_doc */\n    0,                                          /* tp_traverse */\n    0,                                          /* tp_clear */\n    0,                                          /* tp_richcompare */\n    0,                                          /* tp_weaklistoffset */\n    0,                                          /* tp_iter */\n    0,                                          /* tp_iternext */\n    0,                                          /* tp_methods */\n    ste_memberlist,                             /* tp_members */\n    0,                                          /* tp_getset */\n    0,                                          /* tp_base */\n    0,                                          /* tp_dict */\n    0,                                          /* tp_descr_get */\n    0,                                          /* tp_descr_set */\n    0,                                          /* tp_dictoffset */\n    0,                                          /* tp_init */\n    0,                                          /* tp_alloc */\n    0,                                          /* tp_new */\n};\n\nstatic int symtable_analyze(struct symtable *st);\nstatic int symtable_enter_block(struct symtable *st, identifier name,\n                                _Py_block_ty block, void *ast,\n                                int lineno, int col_offset,\n                                int end_lineno, int end_col_offset);\nstatic int symtable_exit_block(struct symtable *st);\nstatic int symtable_visit_stmt(struct symtable *st, stmt_ty s);\nstatic int symtable_visit_expr(struct symtable *st, expr_ty s);\nstatic int symtable_visit_type_param(struct symtable *st, type_param_ty s);\nstatic int symtable_visit_genexp(struct symtable *st, expr_ty s);\nstatic int symtable_visit_listcomp(struct symtable *st, expr_ty s);\nstatic int symtable_visit_setcomp(struct symtable *st, expr_ty s);\nstatic int symtable_visit_dictcomp(struct symtable *st, expr_ty s);\nstatic int symtable_visit_arguments(struct symtable *st, arguments_ty);\nstatic int symtable_visit_excepthandler(struct symtable *st, excepthandler_ty);\nstatic int symtable_visit_alias(struct symtable *st, alias_ty);\nstatic int symtable_visit_comprehension(struct symtable *st, comprehension_ty);\nstatic int symtable_visit_keyword(struct symtable *st, keyword_ty);\nstatic int symtable_visit_params(struct symtable *st, asdl_arg_seq *args);\nstatic int symtable_visit_annotation(struct symtable *st, expr_ty annotation);\nstatic int symtable_visit_argannotations(struct symtable *st, asdl_arg_seq *args);\nstatic int symtable_implicit_arg(struct symtable *st, int pos);\nstatic int symtable_visit_annotations(struct symtable *st, stmt_ty, arguments_ty, expr_ty);\nstatic int symtable_visit_withitem(struct symtable *st, withitem_ty item);\nstatic int symtable_visit_match_case(struct symtable *st, match_case_ty m);\nstatic int symtable_visit_pattern(struct symtable *st, pattern_ty s);\nstatic int symtable_raise_if_annotation_block(struct symtable *st, const char *, expr_ty);\nstatic int symtable_raise_if_comprehension_block(struct symtable *st, expr_ty);\n\n\n#define DUPLICATE_ARGUMENT \\\n\"duplicate argument '%U' in function definition\"\n\nstatic struct symtable *\nsymtable_new(void)\n{\n    struct symtable *st;\n\n    st = (struct symtable *)PyMem_Malloc(sizeof(struct symtable));\n    if (st == NULL) {\n        PyErr_NoMemory();\n        return NULL;\n    }\n\n    st->st_filename = NULL;\n    st->st_blocks = NULL;\n\n    if ((st->st_stack = PyList_New(0)) == NULL)\n        goto fail;\n    if ((st->st_blocks = PyDict_New()) == NULL)\n        goto fail;\n    st->st_cur = NULL;\n    st->st_private = NULL;\n    return st;\n fail:\n    _PySymtable_Free(st);\n    return NULL;\n}\n\n/* When compiling the use of C stack is probably going to be a lot\n   lighter than when executing Python code but still can overflow\n   and causing a Python crash if not checked (e.g. eval(\"()\"*300000)).\n   Using the current recursion limit for the compiler seems too\n   restrictive (it caused at least one test to fail) so a factor is\n   used to allow deeper recursion when compiling an expression.\n\n   Using a scaling factor means this should automatically adjust when\n   the recursion limit is adjusted for small or large C stack allocations.\n*/\n#define COMPILER_STACK_FRAME_SCALE 3\n\nstruct symtable *\n_PySymtable_Build(mod_ty mod, PyObject *filename, PyFutureFeatures *future)\n{\n    struct symtable *st = symtable_new();\n    asdl_stmt_seq *seq;\n    int i;\n    PyThreadState *tstate;\n    int starting_recursion_depth;\n\n    if (st == NULL)\n        return NULL;\n    if (filename == NULL) {\n        _PySymtable_Free(st);\n        return NULL;\n    }\n    st->st_filename = Py_NewRef(filename);\n    st->st_future = future;\n\n    /* Setup recursion depth check counters */\n    tstate = _PyThreadState_GET();\n    if (!tstate) {\n        _PySymtable_Free(st);\n        return NULL;\n    }\n    /* Be careful here to prevent overflow. */\n    int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;\n    starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;\n    st->recursion_depth = starting_recursion_depth;\n    st->recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;\n\n    /* Make the initial symbol information gathering pass */\n    if (!symtable_enter_block(st, &_Py_ID(top), ModuleBlock, (void *)mod, 0, 0, 0, 0)) {\n        _PySymtable_Free(st);\n        return NULL;\n    }\n\n    st->st_top = st->st_cur;\n    switch (mod->kind) {\n    case Module_kind:\n        seq = mod->v.Module.body;\n        for (i = 0; i < asdl_seq_LEN(seq); i++)\n            if (!symtable_visit_stmt(st,\n                        (stmt_ty)asdl_seq_GET(seq, i)))\n                goto error;\n        break;\n    case Expression_kind:\n        if (!symtable_visit_expr(st, mod->v.Expression.body))\n            goto error;\n        break;\n    case Interactive_kind:\n        seq = mod->v.Interactive.body;\n        for (i = 0; i < asdl_seq_LEN(seq); i++)\n            if (!symtable_visit_stmt(st,\n                        (stmt_ty)asdl_seq_GET(seq, i)))\n                goto error;\n        break;\n    case FunctionType_kind:\n        PyErr_SetString(PyExc_RuntimeError,\n                        \"this compiler does not handle FunctionTypes\");\n        goto error;\n    }\n    if (!symtable_exit_block(st)) {\n        _PySymtable_Free(st);\n        return NULL;\n    }\n    /* Check that the recursion depth counting balanced correctly */\n    if (st->recursion_depth != starting_recursion_depth) {\n        PyErr_Format(PyExc_SystemError,\n            \"symtable analysis recursion depth mismatch (before=%d, after=%d)\",\n            starting_recursion_depth, st->recursion_depth);\n        _PySymtable_Free(st);\n        return NULL;\n    }\n    /* Make the second symbol analysis pass */\n    if (symtable_analyze(st))\n        return st;\n    _PySymtable_Free(st);\n    return NULL;\n error:\n    (void) symtable_exit_block(st);\n    _PySymtable_Free(st);\n    return NULL;\n}\n\n\nvoid\n_PySymtable_Free(struct symtable *st)\n{\n    Py_XDECREF(st->st_filename);\n    Py_XDECREF(st->st_blocks);\n    Py_XDECREF(st->st_stack);\n    PyMem_Free((void *)st);\n}\n\nPySTEntryObject *\nPySymtable_Lookup(struct symtable *st, void *key)\n{\n    PyObject *k, *v;\n\n    k = PyLong_FromVoidPtr(key);\n    if (k == NULL)\n        return NULL;\n    v = PyDict_GetItemWithError(st->st_blocks, k);\n    Py_DECREF(k);\n\n    if (v) {\n        assert(PySTEntry_Check(v));\n    }\n    else if (!PyErr_Occurred()) {\n        PyErr_SetString(PyExc_KeyError,\n                        \"unknown symbol table entry\");\n    }\n\n    return (PySTEntryObject *)Py_XNewRef(v);\n}\n\nlong\n_PyST_GetSymbol(PySTEntryObject *ste, PyObject *name)\n{\n    PyObject *v = PyDict_GetItemWithError(ste->ste_symbols, name);\n    if (!v)\n        return 0;\n    assert(PyLong_Check(v));\n    return PyLong_AS_LONG(v);\n}\n\nint\n_PyST_GetScope(PySTEntryObject *ste, PyObject *name)\n{\n    long symbol = _PyST_GetSymbol(ste, name);\n    return (symbol >> SCOPE_OFFSET) & SCOPE_MASK;\n}\n\nint\n_PyST_IsFunctionLike(PySTEntryObject *ste)\n{\n    return ste->ste_type == FunctionBlock\n        || ste->ste_type == TypeVarBoundBlock\n        || ste->ste_type == TypeAliasBlock\n        || ste->ste_type == TypeParamBlock;\n}\n\nstatic int\nerror_at_directive(PySTEntryObject *ste, PyObject *name)\n{\n    Py_ssize_t i;\n    PyObject *data;\n    assert(ste->ste_directives);\n    for (i = 0; i < PyList_GET_SIZE(ste->ste_directives); i++) {\n        data = PyList_GET_ITEM(ste->ste_directives, i);\n        assert(PyTuple_CheckExact(data));\n        assert(PyUnicode_CheckExact(PyTuple_GET_ITEM(data, 0)));\n        if (PyUnicode_Compare(PyTuple_GET_ITEM(data, 0), name) == 0) {\n            PyErr_RangedSyntaxLocationObject(ste->ste_table->st_filename,\n                                             PyLong_AsLong(PyTuple_GET_ITEM(data, 1)),\n                                             PyLong_AsLong(PyTuple_GET_ITEM(data, 2)) + 1,\n                                             PyLong_AsLong(PyTuple_GET_ITEM(data, 3)),\n                                             PyLong_AsLong(PyTuple_GET_ITEM(data, 4)) + 1);\n\n            return 0;\n        }\n    }\n    PyErr_SetString(PyExc_RuntimeError,\n                    \"BUG: internal directive bookkeeping broken\");\n    return 0;\n}\n\n\n/* Analyze raw symbol information to determine scope of each name.\n\n   The next several functions are helpers for symtable_analyze(),\n   which determines whether a name is local, global, or free.  In addition,\n   it determines which local variables are cell variables; they provide\n   bindings that are used for free variables in enclosed blocks.\n\n   There are also two kinds of global variables, implicit and explicit.  An\n   explicit global is declared with the global statement.  An implicit\n   global is a free variable for which the compiler has found no binding\n   in an enclosing function scope.  The implicit global is either a global\n   or a builtin.  Python's module and class blocks use the xxx_NAME opcodes\n   to handle these names to implement slightly odd semantics.  In such a\n   block, the name is treated as global until it is assigned to; then it\n   is treated as a local.\n\n   The symbol table requires two passes to determine the scope of each name.\n   The first pass collects raw facts from the AST via the symtable_visit_*\n   functions: the name is a parameter here, the name is used but not defined\n   here, etc.  The second pass analyzes these facts during a pass over the\n   PySTEntryObjects created during pass 1.\n\n   When a function is entered during the second pass, the parent passes\n   the set of all name bindings visible to its children.  These bindings\n   are used to determine if non-local variables are free or implicit globals.\n   Names which are explicitly declared nonlocal must exist in this set of\n   visible names - if they do not, a syntax error is raised. After doing\n   the local analysis, it analyzes each of its child blocks using an\n   updated set of name bindings.\n\n   The children update the free variable set.  If a local variable is added to\n   the free variable set by the child, the variable is marked as a cell.  The\n   function object being defined must provide runtime storage for the variable\n   that may outlive the function's frame.  Cell variables are removed from the\n   free set before the analyze function returns to its parent.\n\n   During analysis, the names are:\n      symbols: dict mapping from symbol names to flag values (including offset scope values)\n      scopes: dict mapping from symbol names to scope values (no offset)\n      local: set of all symbol names local to the current scope\n      bound: set of all symbol names local to a containing function scope\n      free: set of all symbol names referenced but not bound in child scopes\n      global: set of all symbol names explicitly declared as global\n*/\n\n#define SET_SCOPE(DICT, NAME, I) { \\\n    PyObject *o = PyLong_FromLong(I); \\\n    if (!o) \\\n        return 0; \\\n    if (PyDict_SetItem((DICT), (NAME), o) < 0) { \\\n        Py_DECREF(o); \\\n        return 0; \\\n    } \\\n    Py_DECREF(o); \\\n}\n\n/* Decide on scope of name, given flags.\n\n   The namespace dictionaries may be modified to record information\n   about the new name.  For example, a new global will add an entry to\n   global.  A name that was global can be changed to local.\n*/\n\nstatic int\nanalyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags,\n             PyObject *bound, PyObject *local, PyObject *free,\n             PyObject *global, PyObject *type_params, PySTEntryObject *class_entry)\n{\n    if (flags & DEF_GLOBAL) {\n        if (flags & DEF_NONLOCAL) {\n            PyErr_Format(PyExc_SyntaxError,\n                         \"name '%U' is nonlocal and global\",\n                         name);\n            return error_at_directive(ste, name);\n        }\n        SET_SCOPE(scopes, name, GLOBAL_EXPLICIT);\n        if (PySet_Add(global, name) < 0)\n            return 0;\n        if (bound && (PySet_Discard(bound, name) < 0))\n            return 0;\n        return 1;\n    }\n    if (flags & DEF_NONLOCAL) {\n        if (!bound) {\n            PyErr_Format(PyExc_SyntaxError,\n                         \"nonlocal declaration not allowed at module level\");\n            return error_at_directive(ste, name);\n        }\n        if (!PySet_Contains(bound, name)) {\n            PyErr_Format(PyExc_SyntaxError,\n                         \"no binding for nonlocal '%U' found\",\n                         name);\n\n            return error_at_directive(ste, name);\n        }\n        if (PySet_Contains(type_params, name)) {\n            PyErr_Format(PyExc_SyntaxError,\n                         \"nonlocal binding not allowed for type parameter '%U'\",\n                         name);\n            return error_at_directive(ste, name);\n        }\n        SET_SCOPE(scopes, name, FREE);\n        ste->ste_free = 1;\n        return PySet_Add(free, name) >= 0;\n    }\n    if (flags & DEF_BOUND) {\n        SET_SCOPE(scopes, name, LOCAL);\n        if (PySet_Add(local, name) < 0)\n            return 0;\n        if (PySet_Discard(global, name) < 0)\n            return 0;\n        if (flags & DEF_TYPE_PARAM) {\n            if (PySet_Add(type_params, name) < 0)\n                return 0;\n        }\n        else {\n            if (PySet_Discard(type_params, name) < 0)\n                return 0;\n        }\n        return 1;\n    }\n    // If we were passed class_entry (i.e., we're in an ste_can_see_class_scope scope)\n    // and the bound name is in that set, then the name is potentially bound both by\n    // the immediately enclosing class namespace, and also by an outer function namespace.\n    // In that case, we want the runtime name resolution to look at only the class\n    // namespace and the globals (not the namespace providing the bound).\n    // Similarly, if the name is explicitly global in the class namespace (through the\n    // global statement), we want to also treat it as a global in this scope.\n    if (class_entry != NULL) {\n        long class_flags = _PyST_GetSymbol(class_entry, name);\n        if (class_flags & DEF_GLOBAL) {\n            SET_SCOPE(scopes, name, GLOBAL_EXPLICIT);\n            return 1;\n        }\n        else if (class_flags & DEF_BOUND && !(class_flags & DEF_NONLOCAL)) {\n            SET_SCOPE(scopes, name, GLOBAL_IMPLICIT);\n            return 1;\n        }\n    }\n    /* If an enclosing block has a binding for this name, it\n       is a free variable rather than a global variable.\n       Note that having a non-NULL bound implies that the block\n       is nested.\n    */\n    if (bound && PySet_Contains(bound, name)) {\n        SET_SCOPE(scopes, name, FREE);\n        ste->ste_free = 1;\n        return PySet_Add(free, name) >= 0;\n    }\n    /* If a parent has a global statement, then call it global\n       explicit?  It could also be global implicit.\n     */\n    if (global && PySet_Contains(global, name)) {\n        SET_SCOPE(scopes, name, GLOBAL_IMPLICIT);\n        return 1;\n    }\n    if (ste->ste_nested)\n        ste->ste_free = 1;\n    SET_SCOPE(scopes, name, GLOBAL_IMPLICIT);\n    return 1;\n}\n\nstatic int\nis_free_in_any_child(PySTEntryObject *entry, PyObject *key)\n{\n    for (Py_ssize_t i = 0; i < PyList_GET_SIZE(entry->ste_children); i++) {\n        PySTEntryObject *child_ste = (PySTEntryObject *)PyList_GET_ITEM(\n            entry->ste_children, i);\n        long scope = _PyST_GetScope(child_ste, key);\n        if (scope == FREE) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\nstatic int\ninline_comprehension(PySTEntryObject *ste, PySTEntryObject *comp,\n                     PyObject *scopes, PyObject *comp_free,\n                     PyObject *inlined_cells)\n{\n    PyObject *k, *v;\n    Py_ssize_t pos = 0;\n    while (PyDict_Next(comp->ste_symbols, &pos, &k, &v)) {\n        // skip comprehension parameter\n        long comp_flags = PyLong_AS_LONG(v);\n        if (comp_flags & DEF_PARAM) {\n            assert(_PyUnicode_EqualToASCIIString(k, \".0\"));\n            continue;\n        }\n        int scope = (comp_flags >> SCOPE_OFFSET) & SCOPE_MASK;\n        int only_flags = comp_flags & ((1 << SCOPE_OFFSET) - 1);\n        if (scope == CELL || only_flags & DEF_COMP_CELL) {\n            if (PySet_Add(inlined_cells, k) < 0) {\n                return 0;\n            }\n        }\n        PyObject *existing = PyDict_GetItemWithError(ste->ste_symbols, k);\n        if (existing == NULL && PyErr_Occurred()) {\n            return 0;\n        }\n        if (!existing) {\n            // name does not exist in scope, copy from comprehension\n            assert(scope != FREE || PySet_Contains(comp_free, k) == 1);\n            PyObject *v_flags = PyLong_FromLong(only_flags);\n            if (v_flags == NULL) {\n                return 0;\n            }\n            int ok = PyDict_SetItem(ste->ste_symbols, k, v_flags);\n            Py_DECREF(v_flags);\n            if (ok < 0) {\n                return 0;\n            }\n            SET_SCOPE(scopes, k, scope);\n        }\n        else {\n            if (PyLong_AsLong(existing) & DEF_BOUND) {\n                // free vars in comprehension that are locals in outer scope can\n                // now simply be locals, unless they are free in comp children,\n                // or if the outer scope is a class block\n                if (!is_free_in_any_child(comp, k) && ste->ste_type != ClassBlock) {\n                    if (PySet_Discard(comp_free, k) < 0) {\n                        return 0;\n                    }\n                }\n            }\n        }\n    }\n    return 1;\n}\n\n#undef SET_SCOPE\n\n/* If a name is defined in free and also in locals, then this block\n   provides the binding for the free variable.  The name should be\n   marked CELL in this block and removed from the free list.\n\n   Note that the current block's free variables are included in free.\n   That's safe because no name can be free and local in the same scope.\n*/\n\nstatic int\nanalyze_cells(PyObject *scopes, PyObject *free, PyObject *inlined_cells)\n{\n    PyObject *name, *v, *v_cell;\n    int success = 0;\n    Py_ssize_t pos = 0;\n\n    v_cell = PyLong_FromLong(CELL);\n    if (!v_cell)\n        return 0;\n    while (PyDict_Next(scopes, &pos, &name, &v)) {\n        long scope;\n        assert(PyLong_Check(v));\n        scope = PyLong_AS_LONG(v);\n        if (scope != LOCAL)\n            continue;\n        if (!PySet_Contains(free, name) && !PySet_Contains(inlined_cells, name))\n            continue;\n        /* Replace LOCAL with CELL for this name, and remove\n           from free. It is safe to replace the value of name\n           in the dict, because it will not cause a resize.\n         */\n        if (PyDict_SetItem(scopes, name, v_cell) < 0)\n            goto error;\n        if (PySet_Discard(free, name) < 0)\n            goto error;\n    }\n    success = 1;\n error:\n    Py_DECREF(v_cell);\n    return success;\n}\n\nstatic int\ndrop_class_free(PySTEntryObject *ste, PyObject *free)\n{\n    int res;\n    res = PySet_Discard(free, &_Py_ID(__class__));\n    if (res < 0)\n        return 0;\n    if (res)\n        ste->ste_needs_class_closure = 1;\n    res = PySet_Discard(free, &_Py_ID(__classdict__));\n    if (res < 0)\n        return 0;\n    if (res)\n        ste->ste_needs_classdict = 1;\n    return 1;\n}\n\n/* Enter the final scope information into the ste_symbols dict.\n *\n * All arguments are dicts.  Modifies symbols, others are read-only.\n*/\nstatic int\nupdate_symbols(PyObject *symbols, PyObject *scopes,\n               PyObject *bound, PyObject *free,\n               PyObject *inlined_cells, int classflag)\n{\n    PyObject *name = NULL, *itr = NULL;\n    PyObject *v = NULL, *v_scope = NULL, *v_new = NULL, *v_free = NULL;\n    Py_ssize_t pos = 0;\n\n    /* Update scope information for all symbols in this scope */\n    while (PyDict_Next(symbols, &pos, &name, &v)) {\n        long scope, flags;\n        assert(PyLong_Check(v));\n        flags = PyLong_AS_LONG(v);\n        if (PySet_Contains(inlined_cells, name)) {\n            flags |= DEF_COMP_CELL;\n        }\n        v_scope = PyDict_GetItemWithError(scopes, name);\n        assert(v_scope && PyLong_Check(v_scope));\n        scope = PyLong_AS_LONG(v_scope);\n        flags |= (scope << SCOPE_OFFSET);\n        v_new = PyLong_FromLong(flags);\n        if (!v_new)\n            return 0;\n        if (PyDict_SetItem(symbols, name, v_new) < 0) {\n            Py_DECREF(v_new);\n            return 0;\n        }\n        Py_DECREF(v_new);\n    }\n\n    /* Record not yet resolved free variables from children (if any) */\n    v_free = PyLong_FromLong(FREE << SCOPE_OFFSET);\n    if (!v_free)\n        return 0;\n\n    itr = PyObject_GetIter(free);\n    if (itr == NULL) {\n        Py_DECREF(v_free);\n        return 0;\n    }\n\n    while ((name = PyIter_Next(itr))) {\n        v = PyDict_GetItemWithError(symbols, name);\n\n        /* Handle symbol that already exists in this scope */\n        if (v) {\n            /* Handle a free variable in a method of\n               the class that has the same name as a local\n               or global in the class scope.\n            */\n            if  (classflag &&\n                 PyLong_AS_LONG(v) & (DEF_BOUND | DEF_GLOBAL)) {\n                long flags = PyLong_AS_LONG(v) | DEF_FREE_CLASS;\n                v_new = PyLong_FromLong(flags);\n                if (!v_new) {\n                    goto error;\n                }\n                if (PyDict_SetItem(symbols, name, v_new) < 0) {\n                    Py_DECREF(v_new);\n                    goto error;\n                }\n                Py_DECREF(v_new);\n            }\n            /* It's a cell, or already free in this scope */\n            Py_DECREF(name);\n            continue;\n        }\n        else if (PyErr_Occurred()) {\n            goto error;\n        }\n        /* Handle global symbol */\n        if (bound && !PySet_Contains(bound, name)) {\n            Py_DECREF(name);\n            continue;       /* it's a global */\n        }\n        /* Propagate new free symbol up the lexical stack */\n        if (PyDict_SetItem(symbols, name, v_free) < 0) {\n            goto error;\n        }\n        Py_DECREF(name);\n    }\n    Py_DECREF(itr);\n    Py_DECREF(v_free);\n    return 1;\nerror:\n    Py_XDECREF(v_free);\n    Py_XDECREF(itr);\n    Py_XDECREF(name);\n    return 0;\n}\n\n/* Make final symbol table decisions for block of ste.\n\n   Arguments:\n   ste -- current symtable entry (input/output)\n   bound -- set of variables bound in enclosing scopes (input).  bound\n       is NULL for module blocks.\n   free -- set of free variables in enclosed scopes (output)\n   globals -- set of declared global variables in enclosing scopes (input)\n\n   The implementation uses two mutually recursive functions,\n   analyze_block() and analyze_child_block().  analyze_block() is\n   responsible for analyzing the individual names defined in a block.\n   analyze_child_block() prepares temporary namespace dictionaries\n   used to evaluated nested blocks.\n\n   The two functions exist because a child block should see the name\n   bindings of its enclosing blocks, but those bindings should not\n   propagate back to a parent block.\n*/\n\nstatic int\nanalyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free,\n                    PyObject *global, PyObject *type_params,\n                    PySTEntryObject *class_entry, PyObject **child_free);\n\nstatic int\nanalyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free,\n              PyObject *global, PyObject *type_params,\n              PySTEntryObject *class_entry)\n{\n    PyObject *name, *v, *local = NULL, *scopes = NULL, *newbound = NULL;\n    PyObject *newglobal = NULL, *newfree = NULL, *inlined_cells = NULL;\n    PyObject *temp;\n    int success = 0;\n    Py_ssize_t i, pos = 0;\n\n    local = PySet_New(NULL);  /* collect new names bound in block */\n    if (!local)\n        goto error;\n    scopes = PyDict_New();  /* collect scopes defined for each name */\n    if (!scopes)\n        goto error;\n\n    /* Allocate new global, bound and free variable sets.  These\n       sets hold the names visible in nested blocks.  For\n       ClassBlocks, the bound and global names are initialized\n       before analyzing names, because class bindings aren't\n       visible in methods.  For other blocks, they are initialized\n       after names are analyzed.\n     */\n\n    /* TODO(jhylton): Package these dicts in a struct so that we\n       can write reasonable helper functions?\n    */\n    newglobal = PySet_New(NULL);\n    if (!newglobal)\n        goto error;\n    newfree = PySet_New(NULL);\n    if (!newfree)\n        goto error;\n    newbound = PySet_New(NULL);\n    if (!newbound)\n        goto error;\n    inlined_cells = PySet_New(NULL);\n    if (!inlined_cells)\n        goto error;\n\n    /* Class namespace has no effect on names visible in\n       nested functions, so populate the global and bound\n       sets to be passed to child blocks before analyzing\n       this one.\n     */\n    if (ste->ste_type == ClassBlock) {\n        /* Pass down known globals */\n        temp = PyNumber_InPlaceOr(newglobal, global);\n        if (!temp)\n            goto error;\n        Py_DECREF(temp);\n        /* Pass down previously bound symbols */\n        if (bound) {\n            temp = PyNumber_InPlaceOr(newbound, bound);\n            if (!temp)\n                goto error;\n            Py_DECREF(temp);\n        }\n    }\n\n    while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) {\n        long flags = PyLong_AS_LONG(v);\n        if (!analyze_name(ste, scopes, name, flags,\n                          bound, local, free, global, type_params, class_entry))\n            goto error;\n    }\n\n    /* Populate global and bound sets to be passed to children. */\n    if (ste->ste_type != ClassBlock) {\n        /* Add function locals to bound set */\n        if (_PyST_IsFunctionLike(ste)) {\n            temp = PyNumber_InPlaceOr(newbound, local);\n            if (!temp)\n                goto error;\n            Py_DECREF(temp);\n        }\n        /* Pass down previously bound symbols */\n        if (bound) {\n            temp = PyNumber_InPlaceOr(newbound, bound);\n            if (!temp)\n                goto error;\n            Py_DECREF(temp);\n        }\n        /* Pass down known globals */\n        temp = PyNumber_InPlaceOr(newglobal, global);\n        if (!temp)\n            goto error;\n        Py_DECREF(temp);\n    }\n    else {\n        /* Special-case __class__ and __classdict__ */\n        if (PySet_Add(newbound, &_Py_ID(__class__)) < 0)\n            goto error;\n        if (PySet_Add(newbound, &_Py_ID(__classdict__)) < 0)\n            goto error;\n    }\n\n    /* Recursively call analyze_child_block() on each child block.\n\n       newbound, newglobal now contain the names visible in\n       nested blocks.  The free variables in the children will\n       be added to newfree.\n    */\n    for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) {\n        PyObject *child_free = NULL;\n        PyObject *c = PyList_GET_ITEM(ste->ste_children, i);\n        PySTEntryObject* entry;\n        assert(c && PySTEntry_Check(c));\n        entry = (PySTEntryObject*)c;\n\n        PySTEntryObject *new_class_entry = NULL;\n        if (entry->ste_can_see_class_scope) {\n            if (ste->ste_type == ClassBlock) {\n                new_class_entry = ste;\n            }\n            else if (class_entry) {\n                new_class_entry = class_entry;\n            }\n        }\n\n        // we inline all non-generator-expression comprehensions\n        int inline_comp =\n            entry->ste_comprehension &&\n            !entry->ste_generator;\n\n        if (!analyze_child_block(entry, newbound, newfree, newglobal,\n                                 type_params, new_class_entry, &child_free))\n        {\n            goto error;\n        }\n        if (inline_comp) {\n            if (!inline_comprehension(ste, entry, scopes, child_free, inlined_cells)) {\n                Py_DECREF(child_free);\n                goto error;\n            }\n            entry->ste_comp_inlined = 1;\n        }\n        temp = PyNumber_InPlaceOr(newfree, child_free);\n        Py_DECREF(child_free);\n        if (!temp)\n            goto error;\n        Py_DECREF(temp);\n        /* Check if any children have free variables */\n        if (entry->ste_free || entry->ste_child_free)\n            ste->ste_child_free = 1;\n    }\n\n    /* Splice children of inlined comprehensions into our children list */\n    for (i = PyList_GET_SIZE(ste->ste_children) - 1; i >= 0; --i) {\n        PyObject* c = PyList_GET_ITEM(ste->ste_children, i);\n        PySTEntryObject* entry;\n        assert(c && PySTEntry_Check(c));\n        entry = (PySTEntryObject*)c;\n        if (entry->ste_comp_inlined &&\n            PyList_SetSlice(ste->ste_children, i, i + 1,\n                            entry->ste_children) < 0)\n        {\n            goto error;\n        }\n    }\n\n    /* Check if any local variables must be converted to cell variables */\n    if (_PyST_IsFunctionLike(ste) && !analyze_cells(scopes, newfree, inlined_cells))\n        goto error;\n    else if (ste->ste_type == ClassBlock && !drop_class_free(ste, newfree))\n        goto error;\n    /* Records the results of the analysis in the symbol table entry */\n    if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, inlined_cells,\n                        ste->ste_type == ClassBlock))\n        goto error;\n\n    temp = PyNumber_InPlaceOr(free, newfree);\n    if (!temp)\n        goto error;\n    Py_DECREF(temp);\n    success = 1;\n error:\n    Py_XDECREF(scopes);\n    Py_XDECREF(local);\n    Py_XDECREF(newbound);\n    Py_XDECREF(newglobal);\n    Py_XDECREF(newfree);\n    Py_XDECREF(inlined_cells);\n    if (!success)\n        assert(PyErr_Occurred());\n    return success;\n}\n\nstatic int\nanalyze_child_block(PySTEntryObject *entry, PyObject *bound, PyObject *free,\n                    PyObject *global, PyObject *type_params,\n                    PySTEntryObject *class_entry, PyObject** child_free)\n{\n    PyObject *temp_bound = NULL, *temp_global = NULL, *temp_free = NULL;\n    PyObject *temp_type_params = NULL;\n\n    /* Copy the bound/global/free sets.\n\n       These sets are used by all blocks enclosed by the\n       current block.  The analyze_block() call modifies these\n       sets.\n\n    */\n    temp_bound = PySet_New(bound);\n    if (!temp_bound)\n        goto error;\n    temp_free = PySet_New(free);\n    if (!temp_free)\n        goto error;\n    temp_global = PySet_New(global);\n    if (!temp_global)\n        goto error;\n    temp_type_params = PySet_New(type_params);\n    if (!temp_type_params)\n        goto error;\n\n    if (!analyze_block(entry, temp_bound, temp_free, temp_global,\n                       temp_type_params, class_entry))\n        goto error;\n    *child_free = temp_free;\n    Py_DECREF(temp_bound);\n    Py_DECREF(temp_global);\n    Py_DECREF(temp_type_params);\n    return 1;\n error:\n    Py_XDECREF(temp_bound);\n    Py_XDECREF(temp_free);\n    Py_XDECREF(temp_global);\n    Py_XDECREF(temp_type_params);\n    return 0;\n}\n\nstatic int\nsymtable_analyze(struct symtable *st)\n{\n    PyObject *free, *global, *type_params;\n    int r;\n\n    free = PySet_New(NULL);\n    if (!free)\n        return 0;\n    global = PySet_New(NULL);\n    if (!global) {\n        Py_DECREF(free);\n        return 0;\n    }\n    type_params = PySet_New(NULL);\n    if (!type_params) {\n        Py_DECREF(free);\n        Py_DECREF(global);\n        return 0;\n    }\n    r = analyze_block(st->st_top, NULL, free, global, type_params, NULL);\n    Py_DECREF(free);\n    Py_DECREF(global);\n    Py_DECREF(type_params);\n    return r;\n}\n\n/* symtable_enter_block() gets a reference via ste_new.\n   This reference is released when the block is exited, via the DECREF\n   in symtable_exit_block().\n*/\n\nstatic int\nsymtable_exit_block(struct symtable *st)\n{\n    Py_ssize_t size;\n\n    st->st_cur = NULL;\n    size = PyList_GET_SIZE(st->st_stack);\n    if (size) {\n        if (PyList_SetSlice(st->st_stack, size - 1, size, NULL) < 0)\n            return 0;\n        if (--size)\n            st->st_cur = (PySTEntryObject *)PyList_GET_ITEM(st->st_stack, size - 1);\n    }\n    return 1;\n}\n\nstatic int\nsymtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,\n                     void *ast, int lineno, int col_offset,\n                     int end_lineno, int end_col_offset)\n{\n    PySTEntryObject *prev = NULL, *ste;\n\n    ste = ste_new(st, name, block, ast, lineno, col_offset, end_lineno, end_col_offset);\n    if (ste == NULL)\n        return 0;\n    if (PyList_Append(st->st_stack, (PyObject *)ste) < 0) {\n        Py_DECREF(ste);\n        return 0;\n    }\n    prev = st->st_cur;\n    /* bpo-37757: For now, disallow *all* assignment expressions in the\n     * outermost iterator expression of a comprehension, even those inside\n     * a nested comprehension or a lambda expression.\n     */\n    if (prev) {\n        ste->ste_comp_iter_expr = prev->ste_comp_iter_expr;\n    }\n    /* The entry is owned by the stack. Borrow it for st_cur. */\n    Py_DECREF(ste);\n    st->st_cur = ste;\n\n    /* Annotation blocks shouldn't have any affect on the symbol table since in\n     * the compilation stage, they will all be transformed to strings. They are\n     * only created if future 'annotations' feature is activated. */\n    if (block == AnnotationBlock) {\n        return 1;\n    }\n\n    if (block == ModuleBlock)\n        st->st_global = st->st_cur->ste_symbols;\n\n    if (prev) {\n        if (PyList_Append(prev->ste_children, (PyObject *)ste) < 0) {\n            return 0;\n        }\n    }\n    return 1;\n}\n\nstatic long\nsymtable_lookup(struct symtable *st, PyObject *name)\n{\n    PyObject *mangled = _Py_Mangle(st->st_private, name);\n    if (!mangled)\n        return 0;\n    long ret = _PyST_GetSymbol(st->st_cur, mangled);\n    Py_DECREF(mangled);\n    return ret;\n}\n\nstatic int\nsymtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _symtable_entry *ste,\n                        int lineno, int col_offset, int end_lineno, int end_col_offset)\n{\n    PyObject *o;\n    PyObject *dict;\n    long val;\n    PyObject *mangled = _Py_Mangle(st->st_private, name);\n\n\n    if (!mangled)\n        return 0;\n    dict = ste->ste_symbols;\n    if ((o = PyDict_GetItemWithError(dict, mangled))) {\n        val = PyLong_AS_LONG(o);\n        if ((flag & DEF_PARAM) && (val & DEF_PARAM)) {\n            /* Is it better to use 'mangled' or 'name' here? */\n            PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, name);\n            PyErr_RangedSyntaxLocationObject(st->st_filename,\n                                             lineno, col_offset + 1,\n                                             end_lineno, end_col_offset + 1);\n            goto error;\n        }\n        if ((flag & DEF_TYPE_PARAM) && (val & DEF_TYPE_PARAM)) {\n            PyErr_Format(PyExc_SyntaxError, DUPLICATE_TYPE_PARAM, name);\n            PyErr_RangedSyntaxLocationObject(st->st_filename,\n                                             lineno, col_offset + 1,\n                                             end_lineno, end_col_offset + 1);\n            goto error;\n        }\n        val |= flag;\n    }\n    else if (PyErr_Occurred()) {\n        goto error;\n    }\n    else {\n        val = flag;\n    }\n    if (ste->ste_comp_iter_target) {\n        /* This name is an iteration variable in a comprehension,\n         * so check for a binding conflict with any named expressions.\n         * Otherwise, mark it as an iteration variable so subsequent\n         * named expressions can check for conflicts.\n         */\n        if (val & (DEF_GLOBAL | DEF_NONLOCAL)) {\n            PyErr_Format(PyExc_SyntaxError,\n                NAMED_EXPR_COMP_INNER_LOOP_CONFLICT, name);\n            PyErr_RangedSyntaxLocationObject(st->st_filename,\n                                             lineno, col_offset + 1,\n                                             end_lineno, end_col_offset + 1);\n            goto error;\n        }\n        val |= DEF_COMP_ITER;\n    }\n    o = PyLong_FromLong(val);\n    if (o == NULL)\n        goto error;\n    if (PyDict_SetItem(dict, mangled, o) < 0) {\n        Py_DECREF(o);\n        goto error;\n    }\n    Py_DECREF(o);\n\n    if (flag & DEF_PARAM) {\n        if (PyList_Append(ste->ste_varnames, mangled) < 0)\n            goto error;\n    } else      if (flag & DEF_GLOBAL) {\n        /* XXX need to update DEF_GLOBAL for other flags too;\n           perhaps only DEF_FREE_GLOBAL */\n        val = flag;\n        if ((o = PyDict_GetItemWithError(st->st_global, mangled))) {\n            val |= PyLong_AS_LONG(o);\n        }\n        else if (PyErr_Occurred()) {\n            goto error;\n        }\n        o = PyLong_FromLong(val);\n        if (o == NULL)\n            goto error;\n        if (PyDict_SetItem(st->st_global, mangled, o) < 0) {\n            Py_DECREF(o);\n            goto error;\n        }\n        Py_DECREF(o);\n    }\n    Py_DECREF(mangled);\n    return 1;\n\nerror:\n    Py_DECREF(mangled);\n    return 0;\n}\n\nstatic int\nsymtable_add_def(struct symtable *st, PyObject *name, int flag,\n                 int lineno, int col_offset, int end_lineno, int end_col_offset)\n{\n    return symtable_add_def_helper(st, name, flag, st->st_cur,\n                        lineno, col_offset, end_lineno, end_col_offset);\n}\n\nstatic int\nsymtable_enter_type_param_block(struct symtable *st, identifier name,\n                               void *ast, int has_defaults, int has_kwdefaults,\n                               enum _stmt_kind kind,\n                               int lineno, int col_offset,\n                               int end_lineno, int end_col_offset)\n{\n    _Py_block_ty current_type = st->st_cur->ste_type;\n    if(!symtable_enter_block(st, name, TypeParamBlock, ast, lineno,\n                             col_offset, end_lineno, end_col_offset)) {\n        return 0;\n    }\n    if (current_type == ClassBlock) {\n        st->st_cur->ste_can_see_class_scope = 1;\n        if (!symtable_add_def(st, &_Py_ID(__classdict__), USE, lineno, col_offset, end_lineno, end_col_offset)) {\n            return 0;\n        }\n    }\n    if (kind == ClassDef_kind) {\n        _Py_DECLARE_STR(type_params, \".type_params\");\n        // It gets \"set\" when we create the type params tuple and\n        // \"used\" when we build up the bases.\n        if (!symtable_add_def(st, &_Py_STR(type_params), DEF_LOCAL,\n                              lineno, col_offset, end_lineno, end_col_offset)) {\n            return 0;\n        }\n        if (!symtable_add_def(st, &_Py_STR(type_params), USE,\n                              lineno, col_offset, end_lineno, end_col_offset)) {\n            return 0;\n        }\n        st->st_private = name;\n        // This is used for setting the generic base\n        _Py_DECLARE_STR(generic_base, \".generic_base\");\n        if (!symtable_add_def(st, &_Py_STR(generic_base), DEF_LOCAL,\n                              lineno, col_offset, end_lineno, end_col_offset)) {\n            return 0;\n        }\n        if (!symtable_add_def(st, &_Py_STR(generic_base), USE,\n                              lineno, col_offset, end_lineno, end_col_offset)) {\n            return 0;\n        }\n    }\n    if (has_defaults) {\n        _Py_DECLARE_STR(defaults, \".defaults\");\n        if (!symtable_add_def(st, &_Py_STR(defaults), DEF_PARAM,\n                              lineno, col_offset, end_lineno, end_col_offset)) {\n            return 0;\n        }\n    }\n    if (has_kwdefaults) {\n        _Py_DECLARE_STR(kwdefaults, \".kwdefaults\");\n        if (!symtable_add_def(st, &_Py_STR(kwdefaults), DEF_PARAM,\n                              lineno, col_offset, end_lineno, end_col_offset)) {\n            return 0;\n        }\n    }\n    return 1;\n}\n\n/* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument.\n   They use the ASDL name to synthesize the name of the C type and the visit\n   function.\n\n   VISIT_SEQ_TAIL permits the start of an ASDL sequence to be skipped, which is\n   useful if the first node in the sequence requires special treatment.\n\n   VISIT_QUIT macro returns the specified value exiting from the function but\n   first adjusts current recursion counter depth.\n*/\n\n#define VISIT_QUIT(ST, X) \\\n    return --(ST)->recursion_depth,(X)\n\n#define VISIT(ST, TYPE, V) \\\n    if (!symtable_visit_ ## TYPE((ST), (V))) \\\n        VISIT_QUIT((ST), 0);\n\n#define VISIT_SEQ(ST, TYPE, SEQ) { \\\n    int i; \\\n    asdl_ ## TYPE ## _seq *seq = (SEQ); /* avoid variable capture */ \\\n    for (i = 0; i < asdl_seq_LEN(seq); i++) { \\\n        TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \\\n        if (!symtable_visit_ ## TYPE((ST), elt)) \\\n            VISIT_QUIT((ST), 0);                 \\\n    } \\\n}\n\n#define VISIT_SEQ_TAIL(ST, TYPE, SEQ, START) { \\\n    int i; \\\n    asdl_ ## TYPE ## _seq *seq = (SEQ); /* avoid variable capture */ \\\n    for (i = (START); i < asdl_seq_LEN(seq); i++) { \\\n        TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \\\n        if (!symtable_visit_ ## TYPE((ST), elt)) \\\n            VISIT_QUIT((ST), 0);                 \\\n    } \\\n}\n\n#define VISIT_SEQ_WITH_NULL(ST, TYPE, SEQ) {     \\\n    int i = 0; \\\n    asdl_ ## TYPE ## _seq *seq = (SEQ); /* avoid variable capture */ \\\n    for (i = 0; i < asdl_seq_LEN(seq); i++) { \\\n        TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \\\n        if (!elt) continue; /* can be NULL */ \\\n        if (!symtable_visit_ ## TYPE((ST), elt)) \\\n            VISIT_QUIT((ST), 0);             \\\n    } \\\n}\n\nstatic int\nsymtable_record_directive(struct symtable *st, identifier name, int lineno,\n                          int col_offset, int end_lineno, int end_col_offset)\n{\n    PyObject *data, *mangled;\n    int res;\n    if (!st->st_cur->ste_directives) {\n        st->st_cur->ste_directives = PyList_New(0);\n        if (!st->st_cur->ste_directives)\n            return 0;\n    }\n    mangled = _Py_Mangle(st->st_private, name);\n    if (!mangled)\n        return 0;\n    data = Py_BuildValue(\"(Niiii)\", mangled, lineno, col_offset, end_lineno, end_col_offset);\n    if (!data)\n        return 0;\n    res = PyList_Append(st->st_cur->ste_directives, data);\n    Py_DECREF(data);\n    return res == 0;\n}\n\nstatic int\nhas_kwonlydefaults(asdl_arg_seq *kwonlyargs, asdl_expr_seq *kw_defaults)\n{\n    for (int i = 0; i < asdl_seq_LEN(kwonlyargs); i++) {\n        expr_ty default_ = asdl_seq_GET(kw_defaults, i);\n        if (default_) {\n            return 1;\n        }\n    }\n    return 0;\n}\n\nstatic int\nsymtable_visit_stmt(struct symtable *st, stmt_ty s)\n{\n    if (++st->recursion_depth > st->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n                        \"maximum recursion depth exceeded during compilation\");\n        VISIT_QUIT(st, 0);\n    }\n    switch (s->kind) {\n    case FunctionDef_kind:\n        if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL, LOCATION(s)))\n            VISIT_QUIT(st, 0);\n        if (s->v.FunctionDef.args->defaults)\n            VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults);\n        if (s->v.FunctionDef.args->kw_defaults)\n            VISIT_SEQ_WITH_NULL(st, expr, s->v.FunctionDef.args->kw_defaults);\n        if (s->v.FunctionDef.decorator_list)\n            VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list);\n        if (asdl_seq_LEN(s->v.FunctionDef.type_params) > 0) {\n            if (!symtable_enter_type_param_block(\n                    st, s->v.FunctionDef.name,\n                    (void *)s->v.FunctionDef.type_params,\n                    s->v.FunctionDef.args->defaults != NULL,\n                    has_kwonlydefaults(s->v.FunctionDef.args->kwonlyargs,\n                                       s->v.FunctionDef.args->kw_defaults),\n                    s->kind,\n                    LOCATION(s))) {\n                VISIT_QUIT(st, 0);\n            }\n            VISIT_SEQ(st, type_param, s->v.FunctionDef.type_params);\n        }\n        if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args,\n                                        s->v.FunctionDef.returns))\n            VISIT_QUIT(st, 0);\n        if (!symtable_enter_block(st, s->v.FunctionDef.name,\n                                  FunctionBlock, (void *)s,\n                                  LOCATION(s)))\n            VISIT_QUIT(st, 0);\n        VISIT(st, arguments, s->v.FunctionDef.args);\n        VISIT_SEQ(st, stmt, s->v.FunctionDef.body);\n        if (!symtable_exit_block(st))\n            VISIT_QUIT(st, 0);\n        if (asdl_seq_LEN(s->v.FunctionDef.type_params) > 0) {\n            if (!symtable_exit_block(st))\n                VISIT_QUIT(st, 0);\n        }\n        break;\n    case ClassDef_kind: {\n        PyObject *tmp;\n        if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL, LOCATION(s)))\n            VISIT_QUIT(st, 0);\n        if (s->v.ClassDef.decorator_list)\n            VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list);\n        if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {\n            if (!symtable_enter_type_param_block(st, s->v.ClassDef.name,\n                                                (void *)s->v.ClassDef.type_params,\n                                                false, false, s->kind,\n                                                LOCATION(s))) {\n                VISIT_QUIT(st, 0);\n            }\n            VISIT_SEQ(st, type_param, s->v.ClassDef.type_params);\n        }\n        VISIT_SEQ(st, expr, s->v.ClassDef.bases);\n        VISIT_SEQ(st, keyword, s->v.ClassDef.keywords);\n        if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock,\n                                  (void *)s, s->lineno, s->col_offset,\n                                  s->end_lineno, s->end_col_offset))\n            VISIT_QUIT(st, 0);\n        tmp = st->st_private;\n        st->st_private = s->v.ClassDef.name;\n        if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {\n            if (!symtable_add_def(st, &_Py_ID(__type_params__),\n                                  DEF_LOCAL, LOCATION(s))) {\n                VISIT_QUIT(st, 0);\n            }\n            _Py_DECLARE_STR(type_params, \".type_params\");\n            if (!symtable_add_def(st, &_Py_STR(type_params),\n                                  USE, LOCATION(s))) {\n                VISIT_QUIT(st, 0);\n            }\n        }\n        VISIT_SEQ(st, stmt, s->v.ClassDef.body);\n        st->st_private = tmp;\n        if (!symtable_exit_block(st))\n            VISIT_QUIT(st, 0);\n        if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {\n            if (!symtable_exit_block(st))\n                VISIT_QUIT(st, 0);\n        }\n        break;\n    }\n    case TypeAlias_kind: {\n        VISIT(st, expr, s->v.TypeAlias.name);\n        assert(s->v.TypeAlias.name->kind == Name_kind);\n        PyObject *name = s->v.TypeAlias.name->v.Name.id;\n        int is_in_class = st->st_cur->ste_type == ClassBlock;\n        int is_generic = asdl_seq_LEN(s->v.TypeAlias.type_params) > 0;\n        if (is_generic) {\n            if (!symtable_enter_type_param_block(\n                    st, name,\n                    (void *)s->v.TypeAlias.type_params,\n                    false, false, s->kind,\n                    LOCATION(s))) {\n                VISIT_QUIT(st, 0);\n            }\n            VISIT_SEQ(st, type_param, s->v.TypeAlias.type_params);\n        }\n        if (!symtable_enter_block(st, name, TypeAliasBlock,\n                                  (void *)s, LOCATION(s)))\n            VISIT_QUIT(st, 0);\n        st->st_cur->ste_can_see_class_scope = is_in_class;\n        if (is_in_class && !symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(s->v.TypeAlias.value))) {\n            VISIT_QUIT(st, 0);\n        }\n        VISIT(st, expr, s->v.TypeAlias.value);\n        if (!symtable_exit_block(st))\n            VISIT_QUIT(st, 0);\n        if (is_generic) {\n            if (!symtable_exit_block(st))\n                VISIT_QUIT(st, 0);\n        }\n        break;\n    }\n    case Return_kind:\n        if (s->v.Return.value) {\n            VISIT(st, expr, s->v.Return.value);\n            st->st_cur->ste_returns_value = 1;\n        }\n        break;\n    case Delete_kind:\n        VISIT_SEQ(st, expr, s->v.Delete.targets);\n        break;\n    case Assign_kind:\n        VISIT_SEQ(st, expr, s->v.Assign.targets);\n        VISIT(st, expr, s->v.Assign.value);\n        break;\n    case AnnAssign_kind:\n        if (s->v.AnnAssign.target->kind == Name_kind) {\n            expr_ty e_name = s->v.AnnAssign.target;\n            long cur = symtable_lookup(st, e_name->v.Name.id);\n            if (cur < 0) {\n                VISIT_QUIT(st, 0);\n            }\n            if ((cur & (DEF_GLOBAL | DEF_NONLOCAL))\n                && (st->st_cur->ste_symbols != st->st_global)\n                && s->v.AnnAssign.simple) {\n                PyErr_Format(PyExc_SyntaxError,\n                             cur & DEF_GLOBAL ? GLOBAL_ANNOT : NONLOCAL_ANNOT,\n                             e_name->v.Name.id);\n                PyErr_RangedSyntaxLocationObject(st->st_filename,\n                                                 s->lineno,\n                                                 s->col_offset + 1,\n                                                 s->end_lineno,\n                                                 s->end_col_offset + 1);\n                VISIT_QUIT(st, 0);\n            }\n            if (s->v.AnnAssign.simple &&\n                !symtable_add_def(st, e_name->v.Name.id,\n                                  DEF_ANNOT | DEF_LOCAL, LOCATION(e_name))) {\n                VISIT_QUIT(st, 0);\n            }\n            else {\n                if (s->v.AnnAssign.value\n                    && !symtable_add_def(st, e_name->v.Name.id, DEF_LOCAL, LOCATION(e_name))) {\n                    VISIT_QUIT(st, 0);\n                }\n            }\n        }\n        else {\n            VISIT(st, expr, s->v.AnnAssign.target);\n        }\n        if (!symtable_visit_annotation(st, s->v.AnnAssign.annotation)) {\n            VISIT_QUIT(st, 0);\n        }\n\n        if (s->v.AnnAssign.value) {\n            VISIT(st, expr, s->v.AnnAssign.value);\n        }\n        break;\n    case AugAssign_kind:\n        VISIT(st, expr, s->v.AugAssign.target);\n        VISIT(st, expr, s->v.AugAssign.value);\n        break;\n    case For_kind:\n        VISIT(st, expr, s->v.For.target);\n        VISIT(st, expr, s->v.For.iter);\n        VISIT_SEQ(st, stmt, s->v.For.body);\n        if (s->v.For.orelse)\n            VISIT_SEQ(st, stmt, s->v.For.orelse);\n        break;\n    case While_kind:\n        VISIT(st, expr, s->v.While.test);\n        VISIT_SEQ(st, stmt, s->v.While.body);\n        if (s->v.While.orelse)\n            VISIT_SEQ(st, stmt, s->v.While.orelse);\n        break;\n    case If_kind:\n        /* XXX if 0: and lookup_yield() hacks */\n        VISIT(st, expr, s->v.If.test);\n        VISIT_SEQ(st, stmt, s->v.If.body);\n        if (s->v.If.orelse)\n            VISIT_SEQ(st, stmt, s->v.If.orelse);\n        break;\n    case Match_kind:\n        VISIT(st, expr, s->v.Match.subject);\n        VISIT_SEQ(st, match_case, s->v.Match.cases);\n        break;\n    case Raise_kind:\n        if (s->v.Raise.exc) {\n            VISIT(st, expr, s->v.Raise.exc);\n            if (s->v.Raise.cause) {\n                VISIT(st, expr, s->v.Raise.cause);\n            }\n        }\n        break;\n    case Try_kind:\n        VISIT_SEQ(st, stmt, s->v.Try.body);\n        VISIT_SEQ(st, stmt, s->v.Try.orelse);\n        VISIT_SEQ(st, excepthandler, s->v.Try.handlers);\n        VISIT_SEQ(st, stmt, s->v.Try.finalbody);\n        break;\n    case TryStar_kind:\n        VISIT_SEQ(st, stmt, s->v.TryStar.body);\n        VISIT_SEQ(st, stmt, s->v.TryStar.orelse);\n        VISIT_SEQ(st, excepthandler, s->v.TryStar.handlers);\n        VISIT_SEQ(st, stmt, s->v.TryStar.finalbody);\n        break;\n    case Assert_kind:\n        VISIT(st, expr, s->v.Assert.test);\n        if (s->v.Assert.msg)\n            VISIT(st, expr, s->v.Assert.msg);\n        break;\n    case Import_kind:\n        VISIT_SEQ(st, alias, s->v.Import.names);\n        break;\n    case ImportFrom_kind:\n        VISIT_SEQ(st, alias, s->v.ImportFrom.names);\n        break;\n    case Global_kind: {\n        int i;\n        asdl_identifier_seq *seq = s->v.Global.names;\n        for (i = 0; i < asdl_seq_LEN(seq); i++) {\n            identifier name = (identifier)asdl_seq_GET(seq, i);\n            long cur = symtable_lookup(st, name);\n            if (cur < 0)\n                VISIT_QUIT(st, 0);\n            if (cur & (DEF_PARAM | DEF_LOCAL | USE | DEF_ANNOT)) {\n                const char* msg;\n                if (cur & DEF_PARAM) {\n                    msg = GLOBAL_PARAM;\n                } else if (cur & USE) {\n                    msg = GLOBAL_AFTER_USE;\n                } else if (cur & DEF_ANNOT) {\n                    msg = GLOBAL_ANNOT;\n                } else {  /* DEF_LOCAL */\n                    msg = GLOBAL_AFTER_ASSIGN;\n                }\n                PyErr_Format(PyExc_SyntaxError,\n                             msg, name);\n                PyErr_RangedSyntaxLocationObject(st->st_filename,\n                                                 s->lineno,\n                                                 s->col_offset + 1,\n                                                 s->end_lineno,\n                                                 s->end_col_offset + 1);\n                VISIT_QUIT(st, 0);\n            }\n            if (!symtable_add_def(st, name, DEF_GLOBAL, LOCATION(s)))\n                VISIT_QUIT(st, 0);\n            if (!symtable_record_directive(st, name, s->lineno, s->col_offset,\n                                           s->end_lineno, s->end_col_offset))\n                VISIT_QUIT(st, 0);\n        }\n        break;\n    }\n    case Nonlocal_kind: {\n        int i;\n        asdl_identifier_seq *seq = s->v.Nonlocal.names;\n        for (i = 0; i < asdl_seq_LEN(seq); i++) {\n            identifier name = (identifier)asdl_seq_GET(seq, i);\n            long cur = symtable_lookup(st, name);\n            if (cur < 0)\n                VISIT_QUIT(st, 0);\n            if (cur & (DEF_PARAM | DEF_LOCAL | USE | DEF_ANNOT)) {\n                const char* msg;\n                if (cur & DEF_PARAM) {\n                    msg = NONLOCAL_PARAM;\n                } else if (cur & USE) {\n                    msg = NONLOCAL_AFTER_USE;\n                } else if (cur & DEF_ANNOT) {\n                    msg = NONLOCAL_ANNOT;\n                } else {  /* DEF_LOCAL */\n                    msg = NONLOCAL_AFTER_ASSIGN;\n                }\n                PyErr_Format(PyExc_SyntaxError, msg, name);\n                PyErr_RangedSyntaxLocationObject(st->st_filename,\n                                                 s->lineno,\n                                                 s->col_offset + 1,\n                                                 s->end_lineno,\n                                                 s->end_col_offset + 1);\n                VISIT_QUIT(st, 0);\n            }\n            if (!symtable_add_def(st, name, DEF_NONLOCAL, LOCATION(s)))\n                VISIT_QUIT(st, 0);\n            if (!symtable_record_directive(st, name, s->lineno, s->col_offset,\n                                           s->end_lineno, s->end_col_offset))\n                VISIT_QUIT(st, 0);\n        }\n        break;\n    }\n    case Expr_kind:\n        VISIT(st, expr, s->v.Expr.value);\n        break;\n    case Pass_kind:\n    case Break_kind:\n    case Continue_kind:\n        /* nothing to do here */\n        break;\n    case With_kind:\n        VISIT_SEQ(st, withitem, s->v.With.items);\n        VISIT_SEQ(st, stmt, s->v.With.body);\n        break;\n    case AsyncFunctionDef_kind:\n        if (!symtable_add_def(st, s->v.AsyncFunctionDef.name, DEF_LOCAL, LOCATION(s)))\n            VISIT_QUIT(st, 0);\n        if (s->v.AsyncFunctionDef.args->defaults)\n            VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.args->defaults);\n        if (s->v.AsyncFunctionDef.args->kw_defaults)\n            VISIT_SEQ_WITH_NULL(st, expr,\n                                s->v.AsyncFunctionDef.args->kw_defaults);\n        if (s->v.AsyncFunctionDef.decorator_list)\n            VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.decorator_list);\n        if (asdl_seq_LEN(s->v.AsyncFunctionDef.type_params) > 0) {\n            if (!symtable_enter_type_param_block(\n                    st, s->v.AsyncFunctionDef.name,\n                    (void *)s->v.AsyncFunctionDef.type_params,\n                    s->v.AsyncFunctionDef.args->defaults != NULL,\n                    has_kwonlydefaults(s->v.AsyncFunctionDef.args->kwonlyargs,\n                                       s->v.AsyncFunctionDef.args->kw_defaults),\n                    s->kind,\n                    LOCATION(s))) {\n                VISIT_QUIT(st, 0);\n            }\n            VISIT_SEQ(st, type_param, s->v.AsyncFunctionDef.type_params);\n        }\n        if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args,\n                                        s->v.AsyncFunctionDef.returns))\n            VISIT_QUIT(st, 0);\n        if (!symtable_enter_block(st, s->v.AsyncFunctionDef.name,\n                                  FunctionBlock, (void *)s,\n                                  s->lineno, s->col_offset,\n                                  s->end_lineno, s->end_col_offset))\n            VISIT_QUIT(st, 0);\n        st->st_cur->ste_coroutine = 1;\n        VISIT(st, arguments, s->v.AsyncFunctionDef.args);\n        VISIT_SEQ(st, stmt, s->v.AsyncFunctionDef.body);\n        if (!symtable_exit_block(st))\n            VISIT_QUIT(st, 0);\n        if (asdl_seq_LEN(s->v.AsyncFunctionDef.type_params) > 0) {\n            if (!symtable_exit_block(st))\n                VISIT_QUIT(st, 0);\n        }\n        break;\n    case AsyncWith_kind:\n        VISIT_SEQ(st, withitem, s->v.AsyncWith.items);\n        VISIT_SEQ(st, stmt, s->v.AsyncWith.body);\n        break;\n    case AsyncFor_kind:\n        VISIT(st, expr, s->v.AsyncFor.target);\n        VISIT(st, expr, s->v.AsyncFor.iter);\n        VISIT_SEQ(st, stmt, s->v.AsyncFor.body);\n        if (s->v.AsyncFor.orelse)\n            VISIT_SEQ(st, stmt, s->v.AsyncFor.orelse);\n        break;\n    }\n    VISIT_QUIT(st, 1);\n}\n\nstatic int\nsymtable_extend_namedexpr_scope(struct symtable *st, expr_ty e)\n{\n    assert(st->st_stack);\n    assert(e->kind == Name_kind);\n\n    PyObject *target_name = e->v.Name.id;\n    Py_ssize_t i, size;\n    struct _symtable_entry *ste;\n    size = PyList_GET_SIZE(st->st_stack);\n    assert(size);\n\n    /* Iterate over the stack in reverse and add to the nearest adequate scope */\n    for (i = size - 1; i >= 0; i--) {\n        ste = (struct _symtable_entry *) PyList_GET_ITEM(st->st_stack, i);\n\n        /* If we find a comprehension scope, check for a target\n         * binding conflict with iteration variables, otherwise skip it\n         */\n        if (ste->ste_comprehension) {\n            long target_in_scope = _PyST_GetSymbol(ste, target_name);\n            if ((target_in_scope & DEF_COMP_ITER) &&\n                (target_in_scope & DEF_LOCAL)) {\n                PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_CONFLICT, target_name);\n                PyErr_RangedSyntaxLocationObject(st->st_filename,\n                                                  e->lineno,\n                                                  e->col_offset + 1,\n                                                  e->end_lineno,\n                                                  e->end_col_offset + 1);\n                VISIT_QUIT(st, 0);\n            }\n            continue;\n        }\n\n        /* If we find a FunctionBlock entry, add as GLOBAL/LOCAL or NONLOCAL/LOCAL */\n        if (ste->ste_type == FunctionBlock) {\n            long target_in_scope = _PyST_GetSymbol(ste, target_name);\n            if (target_in_scope & DEF_GLOBAL) {\n                if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e)))\n                    VISIT_QUIT(st, 0);\n            } else {\n                if (!symtable_add_def(st, target_name, DEF_NONLOCAL, LOCATION(e)))\n                    VISIT_QUIT(st, 0);\n            }\n            if (!symtable_record_directive(st, target_name, LOCATION(e)))\n                VISIT_QUIT(st, 0);\n\n            return symtable_add_def_helper(st, target_name, DEF_LOCAL, ste, LOCATION(e));\n        }\n        /* If we find a ModuleBlock entry, add as GLOBAL */\n        if (ste->ste_type == ModuleBlock) {\n            if (!symtable_add_def(st, target_name, DEF_GLOBAL, LOCATION(e)))\n                VISIT_QUIT(st, 0);\n            if (!symtable_record_directive(st, target_name, LOCATION(e)))\n                VISIT_QUIT(st, 0);\n\n            return symtable_add_def_helper(st, target_name, DEF_GLOBAL, ste, LOCATION(e));\n        }\n        /* Disallow usage in ClassBlock and type scopes */\n        if (ste->ste_type == ClassBlock ||\n            ste->ste_type == TypeParamBlock ||\n            ste->ste_type == TypeAliasBlock ||\n            ste->ste_type == TypeVarBoundBlock) {\n            switch (ste->ste_type) {\n                case ClassBlock:\n                    PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_CLASS);\n                    break;\n                case TypeParamBlock:\n                    PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_TYPEPARAM);\n                    break;\n                case TypeAliasBlock:\n                    PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_TYPEALIAS);\n                    break;\n                case TypeVarBoundBlock:\n                    PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_IN_TYPEVAR_BOUND);\n                    break;\n                default:\n                    Py_UNREACHABLE();\n            }\n            PyErr_RangedSyntaxLocationObject(st->st_filename,\n                                              e->lineno,\n                                              e->col_offset + 1,\n                                              e->end_lineno,\n                                              e->end_col_offset + 1);\n            VISIT_QUIT(st, 0);\n        }\n    }\n\n    /* We should always find either a function-like block, ModuleBlock or ClassBlock\n       and should never fall to this case\n    */\n    Py_UNREACHABLE();\n    return 0;\n}\n\nstatic int\nsymtable_handle_namedexpr(struct symtable *st, expr_ty e)\n{\n    if (st->st_cur->ste_comp_iter_expr > 0) {\n        /* Assignment isn't allowed in a comprehension iterable expression */\n        PyErr_Format(PyExc_SyntaxError, NAMED_EXPR_COMP_ITER_EXPR);\n        PyErr_RangedSyntaxLocationObject(st->st_filename,\n                                          e->lineno,\n                                          e->col_offset + 1,\n                                          e->end_lineno,\n                                          e->end_col_offset + 1);\n        return 0;\n    }\n    if (st->st_cur->ste_comprehension) {\n        /* Inside a comprehension body, so find the right target scope */\n        if (!symtable_extend_namedexpr_scope(st, e->v.NamedExpr.target))\n            return 0;\n    }\n    VISIT(st, expr, e->v.NamedExpr.value);\n    VISIT(st, expr, e->v.NamedExpr.target);\n    return 1;\n}\n\nstatic int\nsymtable_visit_expr(struct symtable *st, expr_ty e)\n{\n    if (++st->recursion_depth > st->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n                        \"maximum recursion depth exceeded during compilation\");\n        VISIT_QUIT(st, 0);\n    }\n    switch (e->kind) {\n    case NamedExpr_kind:\n        if (!symtable_raise_if_annotation_block(st, \"named expression\", e)) {\n            VISIT_QUIT(st, 0);\n        }\n        if(!symtable_handle_namedexpr(st, e))\n            VISIT_QUIT(st, 0);\n        break;\n    case BoolOp_kind:\n        VISIT_SEQ(st, expr, e->v.BoolOp.values);\n        break;\n    case BinOp_kind:\n        VISIT(st, expr, e->v.BinOp.left);\n        VISIT(st, expr, e->v.BinOp.right);\n        break;\n    case UnaryOp_kind:\n        VISIT(st, expr, e->v.UnaryOp.operand);\n        break;\n    case Lambda_kind: {\n        if (e->v.Lambda.args->defaults)\n            VISIT_SEQ(st, expr, e->v.Lambda.args->defaults);\n        if (e->v.Lambda.args->kw_defaults)\n            VISIT_SEQ_WITH_NULL(st, expr, e->v.Lambda.args->kw_defaults);\n        if (!symtable_enter_block(st, &_Py_ID(lambda),\n                                  FunctionBlock, (void *)e,\n                                  e->lineno, e->col_offset,\n                                  e->end_lineno, e->end_col_offset))\n            VISIT_QUIT(st, 0);\n        VISIT(st, arguments, e->v.Lambda.args);\n        VISIT(st, expr, e->v.Lambda.body);\n        if (!symtable_exit_block(st))\n            VISIT_QUIT(st, 0);\n        break;\n    }\n    case IfExp_kind:\n        VISIT(st, expr, e->v.IfExp.test);\n        VISIT(st, expr, e->v.IfExp.body);\n        VISIT(st, expr, e->v.IfExp.orelse);\n        break;\n    case Dict_kind:\n        VISIT_SEQ_WITH_NULL(st, expr, e->v.Dict.keys);\n        VISIT_SEQ(st, expr, e->v.Dict.values);\n        break;\n    case Set_kind:\n        VISIT_SEQ(st, expr, e->v.Set.elts);\n        break;\n    case GeneratorExp_kind:\n        if (!symtable_visit_genexp(st, e))\n            VISIT_QUIT(st, 0);\n        break;\n    case ListComp_kind:\n        if (!symtable_visit_listcomp(st, e))\n            VISIT_QUIT(st, 0);\n        break;\n    case SetComp_kind:\n        if (!symtable_visit_setcomp(st, e))\n            VISIT_QUIT(st, 0);\n        break;\n    case DictComp_kind:\n        if (!symtable_visit_dictcomp(st, e))\n            VISIT_QUIT(st, 0);\n        break;\n    case Yield_kind:\n        if (!symtable_raise_if_annotation_block(st, \"yield expression\", e)) {\n            VISIT_QUIT(st, 0);\n        }\n        if (e->v.Yield.value)\n            VISIT(st, expr, e->v.Yield.value);\n        st->st_cur->ste_generator = 1;\n        if (st->st_cur->ste_comprehension) {\n            return symtable_raise_if_comprehension_block(st, e);\n        }\n        break;\n    case YieldFrom_kind:\n        if (!symtable_raise_if_annotation_block(st, \"yield expression\", e)) {\n            VISIT_QUIT(st, 0);\n        }\n        VISIT(st, expr, e->v.YieldFrom.value);\n        st->st_cur->ste_generator = 1;\n        if (st->st_cur->ste_comprehension) {\n            return symtable_raise_if_comprehension_block(st, e);\n        }\n        break;\n    case Await_kind:\n        if (!symtable_raise_if_annotation_block(st, \"await expression\", e)) {\n            VISIT_QUIT(st, 0);\n        }\n        VISIT(st, expr, e->v.Await.value);\n        st->st_cur->ste_coroutine = 1;\n        break;\n    case Compare_kind:\n        VISIT(st, expr, e->v.Compare.left);\n        VISIT_SEQ(st, expr, e->v.Compare.comparators);\n        break;\n    case Call_kind:\n        VISIT(st, expr, e->v.Call.func);\n        VISIT_SEQ(st, expr, e->v.Call.args);\n        VISIT_SEQ_WITH_NULL(st, keyword, e->v.Call.keywords);\n        break;\n    case FormattedValue_kind:\n        VISIT(st, expr, e->v.FormattedValue.value);\n        if (e->v.FormattedValue.format_spec)\n            VISIT(st, expr, e->v.FormattedValue.format_spec);\n        break;\n    case JoinedStr_kind:\n        VISIT_SEQ(st, expr, e->v.JoinedStr.values);\n        break;\n    case Constant_kind:\n        /* Nothing to do here. */\n        break;\n    /* The following exprs can be assignment targets. */\n    case Attribute_kind:\n        VISIT(st, expr, e->v.Attribute.value);\n        break;\n    case Subscript_kind:\n        VISIT(st, expr, e->v.Subscript.value);\n        VISIT(st, expr, e->v.Subscript.slice);\n        break;\n    case Starred_kind:\n        VISIT(st, expr, e->v.Starred.value);\n        break;\n    case Slice_kind:\n        if (e->v.Slice.lower)\n            VISIT(st, expr, e->v.Slice.lower)\n        if (e->v.Slice.upper)\n            VISIT(st, expr, e->v.Slice.upper)\n        if (e->v.Slice.step)\n            VISIT(st, expr, e->v.Slice.step)\n        break;\n    case Name_kind:\n        if (!symtable_add_def(st, e->v.Name.id,\n                              e->v.Name.ctx == Load ? USE : DEF_LOCAL, LOCATION(e)))\n            VISIT_QUIT(st, 0);\n        /* Special-case super: it counts as a use of __class__ */\n        if (e->v.Name.ctx == Load &&\n            _PyST_IsFunctionLike(st->st_cur) &&\n            _PyUnicode_EqualToASCIIString(e->v.Name.id, \"super\")) {\n            if (!symtable_add_def(st, &_Py_ID(__class__), USE, LOCATION(e)))\n                VISIT_QUIT(st, 0);\n        }\n        break;\n    /* child nodes of List and Tuple will have expr_context set */\n    case List_kind:\n        VISIT_SEQ(st, expr, e->v.List.elts);\n        break;\n    case Tuple_kind:\n        VISIT_SEQ(st, expr, e->v.Tuple.elts);\n        break;\n    }\n    VISIT_QUIT(st, 1);\n}\n\nstatic int\nsymtable_visit_type_param(struct symtable *st, type_param_ty tp)\n{\n    if (++st->recursion_depth > st->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n                        \"maximum recursion depth exceeded during compilation\");\n        VISIT_QUIT(st, 0);\n    }\n    switch(tp->kind) {\n    case TypeVar_kind:\n        if (!symtable_add_def(st, tp->v.TypeVar.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))\n            VISIT_QUIT(st, 0);\n        if (tp->v.TypeVar.bound) {\n            int is_in_class = st->st_cur->ste_can_see_class_scope;\n            if (!symtable_enter_block(st, tp->v.TypeVar.name,\n                                      TypeVarBoundBlock, (void *)tp,\n                                      LOCATION(tp)))\n                VISIT_QUIT(st, 0);\n            st->st_cur->ste_can_see_class_scope = is_in_class;\n            if (is_in_class && !symtable_add_def(st, &_Py_ID(__classdict__), USE, LOCATION(tp->v.TypeVar.bound))) {\n                VISIT_QUIT(st, 0);\n            }\n            VISIT(st, expr, tp->v.TypeVar.bound);\n            if (!symtable_exit_block(st))\n                VISIT_QUIT(st, 0);\n        }\n        break;\n    case TypeVarTuple_kind:\n        if (!symtable_add_def(st, tp->v.TypeVarTuple.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))\n            VISIT_QUIT(st, 0);\n        break;\n    case ParamSpec_kind:\n        if (!symtable_add_def(st, tp->v.ParamSpec.name, DEF_TYPE_PARAM | DEF_LOCAL, LOCATION(tp)))\n            VISIT_QUIT(st, 0);\n        break;\n    }\n    VISIT_QUIT(st, 1);\n}\n\nstatic int\nsymtable_visit_pattern(struct symtable *st, pattern_ty p)\n{\n    if (++st->recursion_depth > st->recursion_limit) {\n        PyErr_SetString(PyExc_RecursionError,\n                        \"maximum recursion depth exceeded during compilation\");\n        VISIT_QUIT(st, 0);\n    }\n    switch (p->kind) {\n    case MatchValue_kind:\n        VISIT(st, expr, p->v.MatchValue.value);\n        break;\n    case MatchSingleton_kind:\n        /* Nothing to do here. */\n        break;\n    case MatchSequence_kind:\n        VISIT_SEQ(st, pattern, p->v.MatchSequence.patterns);\n        break;\n    case MatchStar_kind:\n        if (p->v.MatchStar.name) {\n            symtable_add_def(st, p->v.MatchStar.name, DEF_LOCAL, LOCATION(p));\n        }\n        break;\n    case MatchMapping_kind:\n        VISIT_SEQ(st, expr, p->v.MatchMapping.keys);\n        VISIT_SEQ(st, pattern, p->v.MatchMapping.patterns);\n        if (p->v.MatchMapping.rest) {\n            symtable_add_def(st, p->v.MatchMapping.rest, DEF_LOCAL, LOCATION(p));\n        }\n        break;\n    case MatchClass_kind:\n        VISIT(st, expr, p->v.MatchClass.cls);\n        VISIT_SEQ(st, pattern, p->v.MatchClass.patterns);\n        VISIT_SEQ(st, pattern, p->v.MatchClass.kwd_patterns);\n        break;\n    case MatchAs_kind:\n        if (p->v.MatchAs.pattern) {\n            VISIT(st, pattern, p->v.MatchAs.pattern);\n        }\n        if (p->v.MatchAs.name) {\n            symtable_add_def(st, p->v.MatchAs.name, DEF_LOCAL, LOCATION(p));\n        }\n        break;\n    case MatchOr_kind:\n        VISIT_SEQ(st, pattern, p->v.MatchOr.patterns);\n        break;\n    }\n    VISIT_QUIT(st, 1);\n}\n\nstatic int\nsymtable_implicit_arg(struct symtable *st, int pos)\n{\n    PyObject *id = PyUnicode_FromFormat(\".%d\", pos);\n    if (id == NULL)\n        return 0;\n    if (!symtable_add_def(st, id, DEF_PARAM, ST_LOCATION(st->st_cur))) {\n        Py_DECREF(id);\n        return 0;\n    }\n    Py_DECREF(id);\n    return 1;\n}\n\nstatic int\nsymtable_visit_params(struct symtable *st, asdl_arg_seq *args)\n{\n    int i;\n\n    if (!args)\n        return -1;\n\n    for (i = 0; i < asdl_seq_LEN(args); i++) {\n        arg_ty arg = (arg_ty)asdl_seq_GET(args, i);\n        if (!symtable_add_def(st, arg->arg, DEF_PARAM, LOCATION(arg)))\n            return 0;\n    }\n\n    return 1;\n}\n\nstatic int\nsymtable_visit_annotation(struct symtable *st, expr_ty annotation)\n{\n    int future_annotations = st->st_future->ff_features & CO_FUTURE_ANNOTATIONS;\n    if (future_annotations &&\n        !symtable_enter_block(st, &_Py_ID(_annotation), AnnotationBlock,\n                              (void *)annotation, annotation->lineno,\n                              annotation->col_offset, annotation->end_lineno,\n                              annotation->end_col_offset)) {\n        VISIT_QUIT(st, 0);\n    }\n    VISIT(st, expr, annotation);\n    if (future_annotations && !symtable_exit_block(st)) {\n        VISIT_QUIT(st, 0);\n    }\n    return 1;\n}\n\nstatic int\nsymtable_visit_argannotations(struct symtable *st, asdl_arg_seq *args)\n{\n    int i;\n\n    if (!args)\n        return -1;\n\n    for (i = 0; i < asdl_seq_LEN(args); i++) {\n        arg_ty arg = (arg_ty)asdl_seq_GET(args, i);\n        if (arg->annotation)\n            VISIT(st, expr, arg->annotation);\n    }\n\n    return 1;\n}\n\nstatic int\nsymtable_visit_annotations(struct symtable *st, stmt_ty o, arguments_ty a, expr_ty returns)\n{\n    int future_annotations = st->st_future->ff_features & CO_FUTURE_ANNOTATIONS;\n    if (future_annotations &&\n        !symtable_enter_block(st, &_Py_ID(_annotation), AnnotationBlock,\n                              (void *)o, o->lineno, o->col_offset, o->end_lineno,\n                              o->end_col_offset)) {\n        VISIT_QUIT(st, 0);\n    }\n    if (a->posonlyargs && !symtable_visit_argannotations(st, a->posonlyargs))\n        return 0;\n    if (a->args && !symtable_visit_argannotations(st, a->args))\n        return 0;\n    if (a->vararg && a->vararg->annotation)\n        VISIT(st, expr, a->vararg->annotation);\n    if (a->kwarg && a->kwarg->annotation)\n        VISIT(st, expr, a->kwarg->annotation);\n    if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs))\n        return 0;\n    if (future_annotations && !symtable_exit_block(st)) {\n        VISIT_QUIT(st, 0);\n    }\n    if (returns && !symtable_visit_annotation(st, returns)) {\n        VISIT_QUIT(st, 0);\n    }\n    return 1;\n}\n\nstatic int\nsymtable_visit_arguments(struct symtable *st, arguments_ty a)\n{\n    /* skip default arguments inside function block\n       XXX should ast be different?\n    */\n    if (a->posonlyargs && !symtable_visit_params(st, a->posonlyargs))\n        return 0;\n    if (a->args && !symtable_visit_params(st, a->args))\n        return 0;\n    if (a->kwonlyargs && !symtable_visit_params(st, a->kwonlyargs))\n        return 0;\n    if (a->vararg) {\n        if (!symtable_add_def(st, a->vararg->arg, DEF_PARAM, LOCATION(a->vararg)))\n            return 0;\n        st->st_cur->ste_varargs = 1;\n    }\n    if (a->kwarg) {\n        if (!symtable_add_def(st, a->kwarg->arg, DEF_PARAM, LOCATION(a->kwarg)))\n            return 0;\n        st->st_cur->ste_varkeywords = 1;\n    }\n    return 1;\n}\n\n\nstatic int\nsymtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh)\n{\n    if (eh->v.ExceptHandler.type)\n        VISIT(st, expr, eh->v.ExceptHandler.type);\n    if (eh->v.ExceptHandler.name)\n        if (!symtable_add_def(st, eh->v.ExceptHandler.name, DEF_LOCAL, LOCATION(eh)))\n            return 0;\n    VISIT_SEQ(st, stmt, eh->v.ExceptHandler.body);\n    return 1;\n}\n\nstatic int\nsymtable_visit_withitem(struct symtable *st, withitem_ty item)\n{\n    VISIT(st, expr, item->context_expr);\n    if (item->optional_vars) {\n        VISIT(st, expr, item->optional_vars);\n    }\n    return 1;\n}\n\nstatic int\nsymtable_visit_match_case(struct symtable *st, match_case_ty m)\n{\n    VISIT(st, pattern, m->pattern);\n    if (m->guard) {\n        VISIT(st, expr, m->guard);\n    }\n    VISIT_SEQ(st, stmt, m->body);\n    return 1;\n}\n\nstatic int\nsymtable_visit_alias(struct symtable *st, alias_ty a)\n{\n    /* Compute store_name, the name actually bound by the import\n       operation.  It is different than a->name when a->name is a\n       dotted package name (e.g. spam.eggs)\n    */\n    PyObject *store_name;\n    PyObject *name = (a->asname == NULL) ? a->name : a->asname;\n    Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0,\n                                        PyUnicode_GET_LENGTH(name), 1);\n    if (dot != -1) {\n        store_name = PyUnicode_Substring(name, 0, dot);\n        if (!store_name)\n            return 0;\n    }\n    else {\n        store_name = Py_NewRef(name);\n    }\n    if (!_PyUnicode_EqualToASCIIString(name, \"*\")) {\n        int r = symtable_add_def(st, store_name, DEF_IMPORT, LOCATION(a));\n        Py_DECREF(store_name);\n        return r;\n    }\n    else {\n        if (st->st_cur->ste_type != ModuleBlock) {\n            int lineno = a->lineno;\n            int col_offset = a->col_offset;\n            int end_lineno = a->end_lineno;\n            int end_col_offset = a->end_col_offset;\n            PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING);\n            PyErr_RangedSyntaxLocationObject(st->st_filename,\n                                             lineno, col_offset + 1,\n                                             end_lineno, end_col_offset + 1);\n            Py_DECREF(store_name);\n            return 0;\n        }\n        Py_DECREF(store_name);\n        return 1;\n    }\n}\n\n\nstatic int\nsymtable_visit_comprehension(struct symtable *st, comprehension_ty lc)\n{\n    st->st_cur->ste_comp_iter_target = 1;\n    VISIT(st, expr, lc->target);\n    st->st_cur->ste_comp_iter_target = 0;\n    st->st_cur->ste_comp_iter_expr++;\n    VISIT(st, expr, lc->iter);\n    st->st_cur->ste_comp_iter_expr--;\n    VISIT_SEQ(st, expr, lc->ifs);\n    if (lc->is_async) {\n        st->st_cur->ste_coroutine = 1;\n    }\n    return 1;\n}\n\n\nstatic int\nsymtable_visit_keyword(struct symtable *st, keyword_ty k)\n{\n    VISIT(st, expr, k->value);\n    return 1;\n}\n\n\nstatic int\nsymtable_handle_comprehension(struct symtable *st, expr_ty e,\n                              identifier scope_name, asdl_comprehension_seq *generators,\n                              expr_ty elt, expr_ty value)\n{\n    int is_generator = (e->kind == GeneratorExp_kind);\n    comprehension_ty outermost = ((comprehension_ty)\n                                    asdl_seq_GET(generators, 0));\n    /* Outermost iterator is evaluated in current scope */\n    st->st_cur->ste_comp_iter_expr++;\n    VISIT(st, expr, outermost->iter);\n    st->st_cur->ste_comp_iter_expr--;\n    /* Create comprehension scope for the rest */\n    if (!scope_name ||\n        !symtable_enter_block(st, scope_name, FunctionBlock, (void *)e,\n                              e->lineno, e->col_offset,\n                              e->end_lineno, e->end_col_offset)) {\n        return 0;\n    }\n    switch(e->kind) {\n        case ListComp_kind:\n            st->st_cur->ste_comprehension = ListComprehension;\n            break;\n        case SetComp_kind:\n            st->st_cur->ste_comprehension = SetComprehension;\n            break;\n        case DictComp_kind:\n            st->st_cur->ste_comprehension = DictComprehension;\n            break;\n        default:\n            st->st_cur->ste_comprehension = GeneratorExpression;\n            break;\n    }\n    if (outermost->is_async) {\n        st->st_cur->ste_coroutine = 1;\n    }\n\n    /* Outermost iter is received as an argument */\n    if (!symtable_implicit_arg(st, 0)) {\n        symtable_exit_block(st);\n        return 0;\n    }\n    /* Visit iteration variable target, and mark them as such */\n    st->st_cur->ste_comp_iter_target = 1;\n    VISIT(st, expr, outermost->target);\n    st->st_cur->ste_comp_iter_target = 0;\n    /* Visit the rest of the comprehension body */\n    VISIT_SEQ(st, expr, outermost->ifs);\n    VISIT_SEQ_TAIL(st, comprehension, generators, 1);\n    if (value)\n        VISIT(st, expr, value);\n    VISIT(st, expr, elt);\n    st->st_cur->ste_generator = is_generator;\n    int is_async = st->st_cur->ste_coroutine && !is_generator;\n    if (!symtable_exit_block(st)) {\n        return 0;\n    }\n    if (is_async) {\n        st->st_cur->ste_coroutine = 1;\n    }\n    return 1;\n}\n\nstatic int\nsymtable_visit_genexp(struct symtable *st, expr_ty e)\n{\n    return symtable_handle_comprehension(st, e, &_Py_ID(genexpr),\n                                         e->v.GeneratorExp.generators,\n                                         e->v.GeneratorExp.elt, NULL);\n}\n\nstatic int\nsymtable_visit_listcomp(struct symtable *st, expr_ty e)\n{\n    return symtable_handle_comprehension(st, e, &_Py_ID(listcomp),\n                                         e->v.ListComp.generators,\n                                         e->v.ListComp.elt, NULL);\n}\n\nstatic int\nsymtable_visit_setcomp(struct symtable *st, expr_ty e)\n{\n    return symtable_handle_comprehension(st, e, &_Py_ID(setcomp),\n                                         e->v.SetComp.generators,\n                                         e->v.SetComp.elt, NULL);\n}\n\nstatic int\nsymtable_visit_dictcomp(struct symtable *st, expr_ty e)\n{\n    return symtable_handle_comprehension(st, e, &_Py_ID(dictcomp),\n                                         e->v.DictComp.generators,\n                                         e->v.DictComp.key,\n                                         e->v.DictComp.value);\n}\n\nstatic int\nsymtable_raise_if_annotation_block(struct symtable *st, const char *name, expr_ty e)\n{\n    enum _block_type type = st->st_cur->ste_type;\n    if (type == AnnotationBlock)\n        PyErr_Format(PyExc_SyntaxError, ANNOTATION_NOT_ALLOWED, name);\n    else if (type == TypeVarBoundBlock)\n        PyErr_Format(PyExc_SyntaxError, TYPEVAR_BOUND_NOT_ALLOWED, name);\n    else if (type == TypeAliasBlock)\n        PyErr_Format(PyExc_SyntaxError, TYPEALIAS_NOT_ALLOWED, name);\n    else if (type == TypeParamBlock)\n        PyErr_Format(PyExc_SyntaxError, TYPEPARAM_NOT_ALLOWED, name);\n    else\n        return 1;\n\n    PyErr_RangedSyntaxLocationObject(st->st_filename,\n                                     e->lineno,\n                                     e->col_offset + 1,\n                                     e->end_lineno,\n                                     e->end_col_offset + 1);\n    return 0;\n}\n\nstatic int\nsymtable_raise_if_comprehension_block(struct symtable *st, expr_ty e) {\n    _Py_comprehension_ty type = st->st_cur->ste_comprehension;\n    PyErr_SetString(PyExc_SyntaxError,\n            (type == ListComprehension) ? \"'yield' inside list comprehension\" :\n            (type == SetComprehension) ? \"'yield' inside set comprehension\" :\n            (type == DictComprehension) ? \"'yield' inside dict comprehension\" :\n            \"'yield' inside generator expression\");\n    PyErr_RangedSyntaxLocationObject(st->st_filename,\n                                     e->lineno, e->col_offset + 1,\n                                     e->end_lineno, e->end_col_offset + 1);\n    VISIT_QUIT(st, 0);\n}\n\nstruct symtable *\n_Py_SymtableStringObjectFlags(const char *str, PyObject *filename,\n                              int start, PyCompilerFlags *flags)\n{\n    struct symtable *st;\n    mod_ty mod;\n    PyArena *arena;\n\n    arena = _PyArena_New();\n    if (arena == NULL)\n        return NULL;\n\n    mod = _PyParser_ASTFromString(str, filename, start, flags, arena);\n    if (mod == NULL) {\n        _PyArena_Free(arena);\n        return NULL;\n    }\n    PyFutureFeatures future;\n    if (!_PyFuture_FromAST(mod, filename, &future)) {\n        _PyArena_Free(arena);\n        return NULL;\n    }\n    future.ff_features |= flags->cf_flags;\n    st = _PySymtable_Build(mod, filename, &future);\n    _PyArena_Free(arena);\n    return st;\n}\n\nPyObject *\n_Py_Mangle(PyObject *privateobj, PyObject *ident)\n{\n    /* Name mangling: __private becomes _classname__private.\n       This is independent from how the name is used. */\n    if (privateobj == NULL || !PyUnicode_Check(privateobj) ||\n        PyUnicode_READ_CHAR(ident, 0) != '_' ||\n        PyUnicode_READ_CHAR(ident, 1) != '_') {\n        return Py_NewRef(ident);\n    }\n    size_t nlen = PyUnicode_GET_LENGTH(ident);\n    size_t plen = PyUnicode_GET_LENGTH(privateobj);\n    /* Don't mangle __id__ or names with dots.\n\n       The only time a name with a dot can occur is when\n       we are compiling an import statement that has a\n       package name.\n\n       TODO(jhylton): Decide whether we want to support\n       mangling of the module name, e.g. __M.X.\n    */\n    if ((PyUnicode_READ_CHAR(ident, nlen-1) == '_' &&\n         PyUnicode_READ_CHAR(ident, nlen-2) == '_') ||\n        PyUnicode_FindChar(ident, '.', 0, nlen, 1) != -1) {\n        return Py_NewRef(ident); /* Don't mangle __whatever__ */\n    }\n    /* Strip leading underscores from class name */\n    size_t ipriv = 0;\n    while (PyUnicode_READ_CHAR(privateobj, ipriv) == '_') {\n        ipriv++;\n    }\n    if (ipriv == plen) {\n        return Py_NewRef(ident); /* Don't mangle if class is just underscores */\n    }\n    plen -= ipriv;\n\n    if (plen + nlen >= PY_SSIZE_T_MAX - 1) {\n        PyErr_SetString(PyExc_OverflowError,\n                        \"private identifier too large to be mangled\");\n        return NULL;\n    }\n\n    Py_UCS4 maxchar = PyUnicode_MAX_CHAR_VALUE(ident);\n    if (PyUnicode_MAX_CHAR_VALUE(privateobj) > maxchar) {\n        maxchar = PyUnicode_MAX_CHAR_VALUE(privateobj);\n    }\n\n    PyObject *result = PyUnicode_New(1 + nlen + plen, maxchar);\n    if (!result) {\n        return NULL;\n    }\n    /* ident = \"_\" + priv[ipriv:] + ident # i.e. 1+plen+nlen bytes */\n    PyUnicode_WRITE(PyUnicode_KIND(result), PyUnicode_DATA(result), 0, '_');\n    if (PyUnicode_CopyCharacters(result, 1, privateobj, ipriv, plen) < 0) {\n        Py_DECREF(result);\n        return NULL;\n    }\n    if (PyUnicode_CopyCharacters(result, plen+1, ident, 0, nlen) < 0) {\n        Py_DECREF(result);\n        return NULL;\n    }\n    assert(_PyUnicode_CheckConsistency(result, 1));\n    return result;\n}\n"
  },
  {
    "path": "SySModule.c",
    "content": "\n/* System module */\n\n/*\nVarious bits of information used by the interpreter are collected in\nmodule 'sys'.\nFunction member:\n- exit(sts): raise SystemExit\nData members:\n- stdin, stdout, stderr: standard file objects\n- modules: the table of modules (dictionary)\n- path: module search path (list of strings)\n- argv: script arguments (list of strings)\n- ps1, ps2: optional primary and secondary prompts (strings)\n*/\n\n#include \"Python.h\"\n#include \"pycore_call.h\"          // _PyObject_CallNoArgs()\n#include \"pycore_ceval.h\"         // _PyEval_SetAsyncGenFinalizer()\n#include \"pycore_frame.h\"         // _PyInterpreterFrame\n#include \"pycore_initconfig.h\"    // _PyStatus_EXCEPTION()\n#include \"pycore_long.h\"          // _PY_LONG_MAX_STR_DIGITS_THRESHOLD\n#include \"pycore_namespace.h\"     // _PyNamespace_New()\n#include \"pycore_object.h\"        // _PyObject_IS_GC()\n#include \"pycore_pathconfig.h\"    // _PyPathConfig_ComputeSysPath0()\n#include \"pycore_pyerrors.h\"      // _PyErr_GetRaisedException()\n#include \"pycore_pylifecycle.h\"   // _PyErr_WriteUnraisableDefaultHook()\n#include \"pycore_pymath.h\"        // _PY_SHORT_FLOAT_REPR\n#include \"pycore_pymem.h\"         // _PyMem_SetDefaultAllocator()\n#include \"pycore_pystate.h\"       // _PyThreadState_GET()\n#include \"pycore_structseq.h\"     // _PyStructSequence_InitBuiltinWithFlags()\n#include \"pycore_tuple.h\"         // _PyTuple_FromArray()\n\n#include \"frameobject.h\"          // PyFrame_FastToLocalsWithError()\n#include \"pydtrace.h\"\n#include \"osdefs.h\"               // DELIM\n#include \"stdlib_module_names.h\"  // _Py_stdlib_module_names\n#include <locale.h>\n\n#ifdef MS_WINDOWS\n#define WIN32_LEAN_AND_MEAN\n#include <windows.h>\n#endif /* MS_WINDOWS */\n\n#ifdef MS_COREDLL\nextern void *PyWin_DLLhModule;\n/* A string loaded from the DLL at startup: */\nextern const char *PyWin_DLLVersionString;\n#endif\n\n#ifdef __EMSCRIPTEN__\n#include <emscripten.h>\n#endif\n\n#ifdef HAVE_FCNTL_H\n#include <fcntl.h>\n#endif\n\n/*[clinic input]\nmodule sys\n[clinic start generated code]*/\n/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3726b388feee8cea]*/\n\n#include \"clinic/sysmodule.c.h\"\n\nPyObject *\n_PySys_GetAttr(PyThreadState *tstate, PyObject *name)\n{\n    PyObject *sd = tstate->interp->sysdict;\n    if (sd == NULL) {\n        return NULL;\n    }\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    /* XXX Suppress a new exception if it was raised and restore\n     * the old one. */\n    PyObject *value = _PyDict_GetItemWithError(sd, name);\n    _PyErr_SetRaisedException(tstate, exc);\n    return value;\n}\n\nstatic PyObject *\n_PySys_GetObject(PyInterpreterState *interp, const char *name)\n{\n    PyObject *sysdict = interp->sysdict;\n    if (sysdict == NULL) {\n        return NULL;\n    }\n    return _PyDict_GetItemStringWithError(sysdict, name);\n}\n\nPyObject *\nPySys_GetObject(const char *name)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    PyObject *value = _PySys_GetObject(tstate->interp, name);\n    /* XXX Suppress a new exception if it was raised and restore\n     * the old one. */\n    _PyErr_SetRaisedException(tstate, exc);\n    return value;\n}\n\nstatic int\nsys_set_object(PyInterpreterState *interp, PyObject *key, PyObject *v)\n{\n    if (key == NULL) {\n        return -1;\n    }\n    PyObject *sd = interp->sysdict;\n    if (v == NULL) {\n        v = _PyDict_Pop(sd, key, Py_None);\n        if (v == NULL) {\n            return -1;\n        }\n        Py_DECREF(v);\n        return 0;\n    }\n    else {\n        return PyDict_SetItem(sd, key, v);\n    }\n}\n\nint\n_PySys_SetAttr(PyObject *key, PyObject *v)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    return sys_set_object(interp, key, v);\n}\n\nstatic int\nsys_set_object_str(PyInterpreterState *interp, const char *name, PyObject *v)\n{\n    PyObject *key = v ? PyUnicode_InternFromString(name)\n                      : PyUnicode_FromString(name);\n    int r = sys_set_object(interp, key, v);\n    Py_XDECREF(key);\n    return r;\n}\n\nint\nPySys_SetObject(const char *name, PyObject *v)\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    return sys_set_object_str(interp, name, v);\n}\n\nint\n_PySys_ClearAttrString(PyInterpreterState *interp,\n                       const char *name, int verbose)\n{\n    if (verbose) {\n        PySys_WriteStderr(\"# clear sys.%s\\n\", name);\n    }\n    /* To play it safe, we set the attr to None instead of deleting it. */\n    if (PyDict_SetItemString(interp->sysdict, name, Py_None) < 0) {\n        return -1;\n    }\n    return 0;\n}\n\n\nstatic int\nshould_audit(PyInterpreterState *interp)\n{\n    /* interp must not be NULL, but test it just in case for extra safety */\n    assert(interp != NULL);\n    if (!interp) {\n        return 0;\n    }\n    return (interp->runtime->audit_hook_head\n            || interp->audit_hooks\n            || PyDTrace_AUDIT_ENABLED());\n}\n\n\nstatic int\nsys_audit_tstate(PyThreadState *ts, const char *event,\n                 const char *argFormat, va_list vargs)\n{\n    /* N format is inappropriate, because you do not know\n       whether the reference is consumed by the call.\n       Assert rather than exception for perf reasons */\n    assert(!argFormat || !strchr(argFormat, 'N'));\n\n    if (!ts) {\n        /* Audit hooks cannot be called with a NULL thread state */\n        return 0;\n    }\n\n    /* The current implementation cannot be called if tstate is not\n       the current Python thread state. */\n    assert(ts == _PyThreadState_GET());\n\n    /* Early exit when no hooks are registered */\n    PyInterpreterState *is = ts->interp;\n    if (!should_audit(is)) {\n        return 0;\n    }\n\n    PyObject *eventName = NULL;\n    PyObject *eventArgs = NULL;\n    PyObject *hooks = NULL;\n    PyObject *hook = NULL;\n    int res = -1;\n\n    int dtrace = PyDTrace_AUDIT_ENABLED();\n\n\n    PyObject *exc = _PyErr_GetRaisedException(ts);\n\n    /* Initialize event args now */\n    if (argFormat && argFormat[0]) {\n        eventArgs = Py_VaBuildValue(argFormat, vargs);\n        if (eventArgs && !PyTuple_Check(eventArgs)) {\n            PyObject *argTuple = PyTuple_Pack(1, eventArgs);\n            Py_SETREF(eventArgs, argTuple);\n        }\n    }\n    else {\n        eventArgs = PyTuple_New(0);\n    }\n    if (!eventArgs) {\n        goto exit;\n    }\n\n    /* Call global hooks */\n    _Py_AuditHookEntry *e = is->runtime->audit_hook_head;\n    for (; e; e = e->next) {\n        if (e->hookCFunction(event, eventArgs, e->userData) < 0) {\n            goto exit;\n        }\n    }\n\n    /* Dtrace USDT point */\n    if (dtrace) {\n        PyDTrace_AUDIT(event, (void *)eventArgs);\n    }\n\n    /* Call interpreter hooks */\n    if (is->audit_hooks) {\n        eventName = PyUnicode_FromString(event);\n        if (!eventName) {\n            goto exit;\n        }\n\n        hooks = PyObject_GetIter(is->audit_hooks);\n        if (!hooks) {\n            goto exit;\n        }\n\n        /* Disallow tracing in hooks unless explicitly enabled */\n        PyThreadState_EnterTracing(ts);\n        while ((hook = PyIter_Next(hooks)) != NULL) {\n            PyObject *o;\n            int canTrace = _PyObject_LookupAttr(hook, &_Py_ID(__cantrace__), &o);\n            if (o) {\n                canTrace = PyObject_IsTrue(o);\n                Py_DECREF(o);\n            }\n            if (canTrace < 0) {\n                break;\n            }\n            if (canTrace) {\n                PyThreadState_LeaveTracing(ts);\n            }\n            PyObject* args[2] = {eventName, eventArgs};\n            o = _PyObject_FastCallTstate(ts, hook, args, 2);\n            if (canTrace) {\n                PyThreadState_EnterTracing(ts);\n            }\n            if (!o) {\n                break;\n            }\n            Py_DECREF(o);\n            Py_CLEAR(hook);\n        }\n        PyThreadState_LeaveTracing(ts);\n        if (_PyErr_Occurred(ts)) {\n            goto exit;\n        }\n    }\n\n    res = 0;\n\nexit:\n    Py_XDECREF(hook);\n    Py_XDECREF(hooks);\n    Py_XDECREF(eventName);\n    Py_XDECREF(eventArgs);\n\n    if (!res) {\n        _PyErr_SetRaisedException(ts, exc);\n    }\n    else {\n        assert(_PyErr_Occurred(ts));\n        Py_XDECREF(exc);\n    }\n\n    return res;\n}\n\nint\n_PySys_Audit(PyThreadState *tstate, const char *event,\n             const char *argFormat, ...)\n{\n    va_list vargs;\n    va_start(vargs, argFormat);\n    int res = sys_audit_tstate(tstate, event, argFormat, vargs);\n    va_end(vargs);\n    return res;\n}\n\nint\nPySys_Audit(const char *event, const char *argFormat, ...)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    va_list vargs;\n    va_start(vargs, argFormat);\n    int res = sys_audit_tstate(tstate, event, argFormat, vargs);\n    va_end(vargs);\n    return res;\n}\n\n/* We expose this function primarily for our own cleanup during\n * finalization. In general, it should not need to be called,\n * and as such the function is not exported.\n *\n * Must be finalizing to clear hooks */\nvoid\n_PySys_ClearAuditHooks(PyThreadState *ts)\n{\n    assert(ts != NULL);\n    if (!ts) {\n        return;\n    }\n\n    _PyRuntimeState *runtime = ts->interp->runtime;\n    /* The hooks are global so we have to check for runtime finalization. */\n    PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime);\n    assert(finalizing == ts);\n    if (finalizing != ts) {\n        return;\n    }\n\n    const PyConfig *config = _PyInterpreterState_GetConfig(ts->interp);\n    if (config->verbose) {\n        PySys_WriteStderr(\"# clear sys.audit hooks\\n\");\n    }\n\n    /* Hooks can abort later hooks for this event, but cannot\n       abort the clear operation itself. */\n    _PySys_Audit(ts, \"cpython._PySys_ClearAuditHooks\", NULL);\n    _PyErr_Clear(ts);\n\n    _Py_AuditHookEntry *e = runtime->audit_hook_head, *n;\n    runtime->audit_hook_head = NULL;\n    while (e) {\n        n = e->next;\n        PyMem_RawFree(e);\n        e = n;\n    }\n}\n\nint\nPySys_AddAuditHook(Py_AuditHookFunction hook, void *userData)\n{\n    /* tstate can be NULL, so access directly _PyRuntime:\n       PySys_AddAuditHook() can be called before Python is initialized. */\n    _PyRuntimeState *runtime = &_PyRuntime;\n    PyThreadState *tstate;\n    if (runtime->initialized) {\n        tstate = _PyThreadState_GET();\n    }\n    else {\n        tstate = NULL;\n    }\n\n    /* Invoke existing audit hooks to allow them an opportunity to abort. */\n    /* Cannot invoke hooks until we are initialized */\n    if (tstate != NULL) {\n        if (_PySys_Audit(tstate, \"sys.addaudithook\", NULL) < 0) {\n            if (_PyErr_ExceptionMatches(tstate, PyExc_RuntimeError)) {\n                /* We do not report errors derived from RuntimeError */\n                _PyErr_Clear(tstate);\n                return 0;\n            }\n            return -1;\n        }\n    }\n\n    _Py_AuditHookEntry *e = runtime->audit_hook_head;\n    if (!e) {\n        e = (_Py_AuditHookEntry*)PyMem_RawMalloc(sizeof(_Py_AuditHookEntry));\n        runtime->audit_hook_head = e;\n    } else {\n        while (e->next) {\n            e = e->next;\n        }\n        e = e->next = (_Py_AuditHookEntry*)PyMem_RawMalloc(\n            sizeof(_Py_AuditHookEntry));\n    }\n\n    if (!e) {\n        if (tstate != NULL) {\n            _PyErr_NoMemory(tstate);\n        }\n        return -1;\n    }\n\n    e->next = NULL;\n    e->hookCFunction = (Py_AuditHookFunction)hook;\n    e->userData = userData;\n\n    return 0;\n}\n\n/*[clinic input]\nsys.addaudithook\n\n    hook: object\n\nAdds a new audit hook callback.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_addaudithook_impl(PyObject *module, PyObject *hook)\n/*[clinic end generated code: output=4f9c17aaeb02f44e input=0f3e191217a45e34]*/\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    /* Invoke existing audit hooks to allow them an opportunity to abort. */\n    if (_PySys_Audit(tstate, \"sys.addaudithook\", NULL) < 0) {\n        if (_PyErr_ExceptionMatches(tstate, PyExc_Exception)) {\n            /* We do not report errors derived from Exception */\n            _PyErr_Clear(tstate);\n            Py_RETURN_NONE;\n        }\n        return NULL;\n    }\n\n    PyInterpreterState *interp = tstate->interp;\n    if (interp->audit_hooks == NULL) {\n        interp->audit_hooks = PyList_New(0);\n        if (interp->audit_hooks == NULL) {\n            return NULL;\n        }\n        /* Avoid having our list of hooks show up in the GC module */\n        PyObject_GC_UnTrack(interp->audit_hooks);\n    }\n\n    if (PyList_Append(interp->audit_hooks, hook) < 0) {\n        return NULL;\n    }\n\n    Py_RETURN_NONE;\n}\n\nPyDoc_STRVAR(audit_doc,\n\"audit(event, *args)\\n\\\n\\n\\\nPasses the event to any audit hooks that are attached.\");\n\nstatic PyObject *\nsys_audit(PyObject *self, PyObject *const *args, Py_ssize_t argc)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _Py_EnsureTstateNotNULL(tstate);\n\n    if (argc == 0) {\n        _PyErr_SetString(tstate, PyExc_TypeError,\n                         \"audit() missing 1 required positional argument: \"\n                         \"'event'\");\n        return NULL;\n    }\n\n    if (!should_audit(tstate->interp)) {\n        Py_RETURN_NONE;\n    }\n\n    PyObject *auditEvent = args[0];\n    if (!auditEvent) {\n        _PyErr_SetString(tstate, PyExc_TypeError,\n                         \"expected str for argument 'event'\");\n        return NULL;\n    }\n    if (!PyUnicode_Check(auditEvent)) {\n        _PyErr_Format(tstate, PyExc_TypeError,\n                      \"expected str for argument 'event', not %.200s\",\n                      Py_TYPE(auditEvent)->tp_name);\n        return NULL;\n    }\n    const char *event = PyUnicode_AsUTF8(auditEvent);\n    if (!event) {\n        return NULL;\n    }\n\n    PyObject *auditArgs = _PyTuple_FromArray(args + 1, argc - 1);\n    if (!auditArgs) {\n        return NULL;\n    }\n\n    int res = _PySys_Audit(tstate, event, \"O\", auditArgs);\n    Py_DECREF(auditArgs);\n\n    if (res < 0) {\n        return NULL;\n    }\n\n    Py_RETURN_NONE;\n}\n\n\nstatic PyObject *\nsys_breakpointhook(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    assert(!_PyErr_Occurred(tstate));\n    char *envar = Py_GETENV(\"PYTHONBREAKPOINT\");\n\n    if (envar == NULL || strlen(envar) == 0) {\n        envar = \"pdb.set_trace\";\n    }\n    else if (!strcmp(envar, \"0\")) {\n        /* The breakpoint is explicitly no-op'd. */\n        Py_RETURN_NONE;\n    }\n    /* According to POSIX the string returned by getenv() might be invalidated\n     * or the string content might be overwritten by a subsequent call to\n     * getenv().  Since importing a module can performs the getenv() calls,\n     * we need to save a copy of envar. */\n    envar = _PyMem_RawStrdup(envar);\n    if (envar == NULL) {\n        _PyErr_NoMemory(tstate);\n        return NULL;\n    }\n    const char *last_dot = strrchr(envar, '.');\n    const char *attrname = NULL;\n    PyObject *modulepath = NULL;\n\n    if (last_dot == NULL) {\n        /* The breakpoint is a built-in, e.g. PYTHONBREAKPOINT=int */\n        modulepath = PyUnicode_FromString(\"builtins\");\n        attrname = envar;\n    }\n    else if (last_dot != envar) {\n        /* Split on the last dot; */\n        modulepath = PyUnicode_FromStringAndSize(envar, last_dot - envar);\n        attrname = last_dot + 1;\n    }\n    else {\n        goto warn;\n    }\n    if (modulepath == NULL) {\n        PyMem_RawFree(envar);\n        return NULL;\n    }\n\n    PyObject *module = PyImport_Import(modulepath);\n    Py_DECREF(modulepath);\n\n    if (module == NULL) {\n        if (_PyErr_ExceptionMatches(tstate, PyExc_ImportError)) {\n            goto warn;\n        }\n        PyMem_RawFree(envar);\n        return NULL;\n    }\n\n    PyObject *hook = PyObject_GetAttrString(module, attrname);\n    Py_DECREF(module);\n\n    if (hook == NULL) {\n        if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {\n            goto warn;\n        }\n        PyMem_RawFree(envar);\n        return NULL;\n    }\n    PyMem_RawFree(envar);\n    PyObject *retval = PyObject_Vectorcall(hook, args, nargs, keywords);\n    Py_DECREF(hook);\n    return retval;\n\n  warn:\n    /* If any of the imports went wrong, then warn and ignore. */\n    _PyErr_Clear(tstate);\n    int status = PyErr_WarnFormat(\n        PyExc_RuntimeWarning, 0,\n        \"Ignoring unimportable $PYTHONBREAKPOINT: \\\"%s\\\"\", envar);\n    PyMem_RawFree(envar);\n    if (status < 0) {\n        /* Printing the warning raised an exception. */\n        return NULL;\n    }\n    /* The warning was (probably) issued. */\n    Py_RETURN_NONE;\n}\n\nPyDoc_STRVAR(breakpointhook_doc,\n\"breakpointhook(*args, **kws)\\n\"\n\"\\n\"\n\"This hook function is called by built-in breakpoint().\\n\"\n);\n\n/* Write repr(o) to sys.stdout using sys.stdout.encoding and 'backslashreplace'\n   error handler. If sys.stdout has a buffer attribute, use\n   sys.stdout.buffer.write(encoded), otherwise redecode the string and use\n   sys.stdout.write(redecoded).\n\n   Helper function for sys_displayhook(). */\nstatic int\nsys_displayhook_unencodable(PyObject *outf, PyObject *o)\n{\n    PyObject *stdout_encoding = NULL;\n    PyObject *encoded, *escaped_str, *repr_str, *buffer, *result;\n    const char *stdout_encoding_str;\n    int ret;\n\n    stdout_encoding = PyObject_GetAttr(outf, &_Py_ID(encoding));\n    if (stdout_encoding == NULL)\n        goto error;\n    stdout_encoding_str = PyUnicode_AsUTF8(stdout_encoding);\n    if (stdout_encoding_str == NULL)\n        goto error;\n\n    repr_str = PyObject_Repr(o);\n    if (repr_str == NULL)\n        goto error;\n    encoded = PyUnicode_AsEncodedString(repr_str,\n                                        stdout_encoding_str,\n                                        \"backslashreplace\");\n    Py_DECREF(repr_str);\n    if (encoded == NULL)\n        goto error;\n\n    if (_PyObject_LookupAttr(outf, &_Py_ID(buffer), &buffer) < 0) {\n        Py_DECREF(encoded);\n        goto error;\n    }\n    if (buffer) {\n        result = PyObject_CallMethodOneArg(buffer, &_Py_ID(write), encoded);\n        Py_DECREF(buffer);\n        Py_DECREF(encoded);\n        if (result == NULL)\n            goto error;\n        Py_DECREF(result);\n    }\n    else {\n        escaped_str = PyUnicode_FromEncodedObject(encoded,\n                                                  stdout_encoding_str,\n                                                  \"strict\");\n        Py_DECREF(encoded);\n        if (PyFile_WriteObject(escaped_str, outf, Py_PRINT_RAW) != 0) {\n            Py_DECREF(escaped_str);\n            goto error;\n        }\n        Py_DECREF(escaped_str);\n    }\n    ret = 0;\n    goto finally;\n\nerror:\n    ret = -1;\nfinally:\n    Py_XDECREF(stdout_encoding);\n    return ret;\n}\n\n/*[clinic input]\nsys.displayhook\n\n    object as o: object\n    /\n\nPrint an object to sys.stdout and also save it in builtins._\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_displayhook(PyObject *module, PyObject *o)\n/*[clinic end generated code: output=347477d006df92ed input=08ba730166d7ef72]*/\n{\n    PyObject *outf;\n    PyObject *builtins;\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    builtins = PyImport_GetModule(&_Py_ID(builtins));\n    if (builtins == NULL) {\n        if (!_PyErr_Occurred(tstate)) {\n            _PyErr_SetString(tstate, PyExc_RuntimeError,\n                             \"lost builtins module\");\n        }\n        return NULL;\n    }\n    Py_DECREF(builtins);\n\n    /* Print value except if None */\n    /* After printing, also assign to '_' */\n    /* Before, set '_' to None to avoid recursion */\n    if (o == Py_None) {\n        Py_RETURN_NONE;\n    }\n    if (PyObject_SetAttr(builtins, &_Py_ID(_), Py_None) != 0)\n        return NULL;\n    outf = _PySys_GetAttr(tstate, &_Py_ID(stdout));\n    if (outf == NULL || outf == Py_None) {\n        _PyErr_SetString(tstate, PyExc_RuntimeError, \"lost sys.stdout\");\n        return NULL;\n    }\n    if (PyFile_WriteObject(o, outf, 0) != 0) {\n        if (_PyErr_ExceptionMatches(tstate, PyExc_UnicodeEncodeError)) {\n            int err;\n            /* repr(o) is not encodable to sys.stdout.encoding with\n             * sys.stdout.errors error handler (which is probably 'strict') */\n            _PyErr_Clear(tstate);\n            err = sys_displayhook_unencodable(outf, o);\n            if (err) {\n                return NULL;\n            }\n        }\n        else {\n            return NULL;\n        }\n    }\n    _Py_DECLARE_STR(newline, \"\\n\");\n    if (PyFile_WriteObject(&_Py_STR(newline), outf, Py_PRINT_RAW) != 0)\n        return NULL;\n    if (PyObject_SetAttr(builtins, &_Py_ID(_), o) != 0)\n        return NULL;\n    Py_RETURN_NONE;\n}\n\n\n/*[clinic input]\nsys.excepthook\n\n    exctype:   object\n    value:     object\n    traceback: object\n    /\n\nHandle an exception by displaying it with a traceback on sys.stderr.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_excepthook_impl(PyObject *module, PyObject *exctype, PyObject *value,\n                    PyObject *traceback)\n/*[clinic end generated code: output=18d99fdda21b6b5e input=ecf606fa826f19d9]*/\n{\n    PyErr_Display(NULL, value, traceback);\n    Py_RETURN_NONE;\n}\n\n\n/*[clinic input]\nsys.exception\n\nReturn the current exception.\n\nReturn the most recent exception caught by an except clause\nin the current stack frame or in an older stack frame, or None\nif no such exception exists.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_exception_impl(PyObject *module)\n/*[clinic end generated code: output=2381ee2f25953e40 input=c88fbb94b6287431]*/\n{\n    _PyErr_StackItem *err_info = _PyErr_GetTopmostException(_PyThreadState_GET());\n    if (err_info->exc_value != NULL) {\n        return Py_NewRef(err_info->exc_value);\n    }\n    Py_RETURN_NONE;\n}\n\n\n/*[clinic input]\nsys.exc_info\n\nReturn current exception information: (type, value, traceback).\n\nReturn information about the most recent exception caught by an except\nclause in the current stack frame or in an older stack frame.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_exc_info_impl(PyObject *module)\n/*[clinic end generated code: output=3afd0940cf3a4d30 input=b5c5bf077788a3e5]*/\n{\n    _PyErr_StackItem *err_info = _PyErr_GetTopmostException(_PyThreadState_GET());\n    return _PyErr_StackItemToExcInfoTuple(err_info);\n}\n\n\n/*[clinic input]\nsys.unraisablehook\n\n    unraisable: object\n    /\n\nHandle an unraisable exception.\n\nThe unraisable argument has the following attributes:\n\n* exc_type: Exception type.\n* exc_value: Exception value, can be None.\n* exc_traceback: Exception traceback, can be None.\n* err_msg: Error message, can be None.\n* object: Object causing the exception, can be None.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_unraisablehook(PyObject *module, PyObject *unraisable)\n/*[clinic end generated code: output=bb92838b32abaa14 input=ec3af148294af8d3]*/\n{\n    return _PyErr_WriteUnraisableDefaultHook(unraisable);\n}\n\n\n/*[clinic input]\nsys.exit\n\n    status: object = None\n    /\n\nExit the interpreter by raising SystemExit(status).\n\nIf the status is omitted or None, it defaults to zero (i.e., success).\nIf the status is an integer, it will be used as the system exit status.\nIf it is another kind of object, it will be printed and the system\nexit status will be one (i.e., failure).\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_exit_impl(PyObject *module, PyObject *status)\n/*[clinic end generated code: output=13870986c1ab2ec0 input=b86ca9497baa94f2]*/\n{\n    /* Raise SystemExit so callers may catch it or clean up. */\n    PyErr_SetObject(PyExc_SystemExit, status);\n    return NULL;\n}\n\n\n\n/*[clinic input]\nsys.getdefaultencoding\n\nReturn the current default encoding used by the Unicode implementation.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_getdefaultencoding_impl(PyObject *module)\n/*[clinic end generated code: output=256d19dfcc0711e6 input=d416856ddbef6909]*/\n{\n    _Py_DECLARE_STR(utf_8, \"utf-8\");\n    PyObject *ret = &_Py_STR(utf_8);\n    return Py_NewRef(ret);\n}\n\n/*[clinic input]\nsys.getfilesystemencoding\n\nReturn the encoding used to convert Unicode filenames to OS filenames.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_getfilesystemencoding_impl(PyObject *module)\n/*[clinic end generated code: output=1dc4bdbe9be44aa7 input=8475f8649b8c7d8c]*/\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    const PyConfig *config = _PyInterpreterState_GetConfig(interp);\n    return PyUnicode_FromWideChar(config->filesystem_encoding, -1);\n}\n\n/*[clinic input]\nsys.getfilesystemencodeerrors\n\nReturn the error mode used Unicode to OS filename conversion.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_getfilesystemencodeerrors_impl(PyObject *module)\n/*[clinic end generated code: output=ba77b36bbf7c96f5 input=22a1e8365566f1e5]*/\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    const PyConfig *config = _PyInterpreterState_GetConfig(interp);\n    return PyUnicode_FromWideChar(config->filesystem_errors, -1);\n}\n\n/*[clinic input]\nsys.intern\n\n    string as s: unicode\n    /\n\n``Intern'' the given string.\n\nThis enters the string in the (global) table of interned strings whose\npurpose is to speed up dictionary lookups. Return the string itself or\nthe previously interned string object with the same value.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_intern_impl(PyObject *module, PyObject *s)\n/*[clinic end generated code: output=be680c24f5c9e5d6 input=849483c006924e2f]*/\n{\n    if (PyUnicode_CheckExact(s)) {\n        Py_INCREF(s);\n        PyUnicode_InternInPlace(&s);\n        return s;\n    }\n    else {\n        PyErr_Format(PyExc_TypeError,\n                     \"can't intern %.400s\", Py_TYPE(s)->tp_name);\n        return NULL;\n    }\n}\n\n\n/*\n * Cached interned string objects used for calling the profile and\n * trace functions.\n */\nstatic PyObject *whatstrings[8] = {\n   &_Py_ID(call),\n   &_Py_ID(exception),\n   &_Py_ID(line),\n   &_Py_ID(return),\n   &_Py_ID(c_call),\n   &_Py_ID(c_exception),\n   &_Py_ID(c_return),\n   &_Py_ID(opcode),\n};\n\n\nstatic PyObject *\ncall_trampoline(PyThreadState *tstate, PyObject* callback,\n                PyFrameObject *frame, int what, PyObject *arg)\n{\n\n    PyObject *stack[3];\n    stack[0] = (PyObject *)frame;\n    stack[1] = whatstrings[what];\n    stack[2] = (arg != NULL) ? arg : Py_None;\n\n    /* Discard any previous modifications the frame's fast locals */\n    if (frame->f_fast_as_locals) {\n        if (PyFrame_FastToLocalsWithError(frame) < 0) {\n            return NULL;\n        }\n    }\n\n    /* call the Python-level function */\n    PyObject *result = _PyObject_FastCallTstate(tstate, callback, stack, 3);\n\n    PyFrame_LocalsToFast(frame, 1);\n    return result;\n}\n\nstatic int\nprofile_trampoline(PyObject *self, PyFrameObject *frame,\n                   int what, PyObject *arg)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *result = call_trampoline(tstate, self, frame, what, arg);\n    if (result == NULL) {\n        _PyEval_SetProfile(tstate, NULL, NULL);\n        return -1;\n    }\n\n    Py_DECREF(result);\n    return 0;\n}\n\nstatic int\ntrace_trampoline(PyObject *self, PyFrameObject *frame,\n                 int what, PyObject *arg)\n{\n    PyObject *callback;\n    if (what == PyTrace_CALL) {\n        callback = self;\n    }\n    else {\n        callback = frame->f_trace;\n    }\n    if (callback == NULL) {\n        return 0;\n    }\n\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *result = call_trampoline(tstate, callback, frame, what, arg);\n    if (result == NULL) {\n        _PyEval_SetTrace(tstate, NULL, NULL);\n        Py_CLEAR(frame->f_trace);\n        return -1;\n    }\n\n    if (result != Py_None) {\n        Py_XSETREF(frame->f_trace, result);\n    }\n    else {\n        Py_DECREF(result);\n    }\n    return 0;\n}\n\nstatic PyObject *\nsys_settrace(PyObject *self, PyObject *args)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (args == Py_None) {\n        if (_PyEval_SetTrace(tstate, NULL, NULL) < 0) {\n            return NULL;\n        }\n    }\n    else {\n        if (_PyEval_SetTrace(tstate, trace_trampoline, args) < 0) {\n            return NULL;\n        }\n    }\n    Py_RETURN_NONE;\n}\n\nPyDoc_STRVAR(settrace_doc,\n\"settrace(function)\\n\\\n\\n\\\nSet the global debug tracing function.  It will be called on each\\n\\\nfunction call.  See the debugger chapter in the library manual.\"\n);\n\n/*[clinic input]\nsys._settraceallthreads\n\n    arg: object\n    /\n\nSet the global debug tracing function in all running threads belonging to the current interpreter.\n\nIt will be called on each function call. See the debugger chapter\nin the library manual.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__settraceallthreads(PyObject *module, PyObject *arg)\n/*[clinic end generated code: output=161cca30207bf3ca input=5906aa1485a50289]*/\n{\n    PyObject* argument = NULL;\n    Py_tracefunc func = NULL;\n\n    if (arg != Py_None) {\n        func = trace_trampoline;\n        argument = arg;\n    }\n\n\n    PyEval_SetTraceAllThreads(func, argument);\n\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nsys.gettrace\n\nReturn the global debug tracing function set with sys.settrace.\n\nSee the debugger chapter in the library manual.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_gettrace_impl(PyObject *module)\n/*[clinic end generated code: output=e97e3a4d8c971b6e input=373b51bb2147f4d8]*/\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *temp = tstate->c_traceobj;\n\n    if (temp == NULL)\n        temp = Py_None;\n    return Py_NewRef(temp);\n}\n\nstatic PyObject *\nsys_setprofile(PyObject *self, PyObject *args)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (args == Py_None) {\n        if (_PyEval_SetProfile(tstate, NULL, NULL) < 0) {\n            return NULL;\n        }\n    }\n    else {\n        if (_PyEval_SetProfile(tstate, profile_trampoline, args) < 0) {\n            return NULL;\n        }\n    }\n    Py_RETURN_NONE;\n}\n\nPyDoc_STRVAR(setprofile_doc,\n\"setprofile(function)\\n\\\n\\n\\\nSet the profiling function.  It will be called on each function call\\n\\\nand return.  See the profiler chapter in the library manual.\"\n);\n\n/*[clinic input]\nsys._setprofileallthreads\n\n    arg: object\n    /\n\nSet the profiling function in all running threads belonging to the current interpreter.\n\nIt will be called on each function call and return.  See the profiler chapter\nin the library manual.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__setprofileallthreads(PyObject *module, PyObject *arg)\n/*[clinic end generated code: output=2d61319e27b309fe input=d1a356d3f4f9060a]*/\n{\n    PyObject* argument = NULL;\n    Py_tracefunc func = NULL;\n\n    if (arg != Py_None) {\n        func = profile_trampoline;\n        argument = arg;\n    }\n\n    PyEval_SetProfileAllThreads(func, argument);\n\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nsys.getprofile\n\nReturn the profiling function set with sys.setprofile.\n\nSee the profiler chapter in the library manual.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_getprofile_impl(PyObject *module)\n/*[clinic end generated code: output=579b96b373448188 input=1b3209d89a32965d]*/\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *temp = tstate->c_profileobj;\n\n    if (temp == NULL)\n        temp = Py_None;\n    return Py_NewRef(temp);\n}\n\n\n/*[clinic input]\nsys.setswitchinterval\n\n    interval: double\n    /\n\nSet the ideal thread switching delay inside the Python interpreter.\n\nThe actual frequency of switching threads can be lower if the\ninterpreter executes long sequences of uninterruptible code\n(this is implementation-specific and workload-dependent).\n\nThe parameter must represent the desired switching delay in seconds\nA typical value is 0.005 (5 milliseconds).\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_setswitchinterval_impl(PyObject *module, double interval)\n/*[clinic end generated code: output=65a19629e5153983 input=561b477134df91d9]*/\n{\n    if (interval <= 0.0) {\n        PyErr_SetString(PyExc_ValueError,\n                        \"switch interval must be strictly positive\");\n        return NULL;\n    }\n    _PyEval_SetSwitchInterval((unsigned long) (1e6 * interval));\n    Py_RETURN_NONE;\n}\n\n\n/*[clinic input]\nsys.getswitchinterval -> double\n\nReturn the current thread switch interval; see sys.setswitchinterval().\n[clinic start generated code]*/\n\nstatic double\nsys_getswitchinterval_impl(PyObject *module)\n/*[clinic end generated code: output=a38c277c85b5096d input=bdf9d39c0ebbbb6f]*/\n{\n    return 1e-6 * _PyEval_GetSwitchInterval();\n}\n\n/*[clinic input]\nsys.setrecursionlimit\n\n    limit as new_limit: int\n    /\n\nSet the maximum depth of the Python interpreter stack to n.\n\nThis limit prevents infinite recursion from causing an overflow of the C\nstack and crashing Python.  The highest possible limit is platform-\ndependent.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_setrecursionlimit_impl(PyObject *module, int new_limit)\n/*[clinic end generated code: output=35e1c64754800ace input=b0f7a23393924af3]*/\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    if (new_limit < 1) {\n        _PyErr_SetString(tstate, PyExc_ValueError,\n                         \"recursion limit must be greater or equal than 1\");\n        return NULL;\n    }\n\n    /* Reject too low new limit if the current recursion depth is higher than\n       the new low-water mark. */\n    int depth = tstate->py_recursion_limit - tstate->py_recursion_remaining;\n    if (depth >= new_limit) {\n        _PyErr_Format(tstate, PyExc_RecursionError,\n                      \"cannot set the recursion limit to %i at \"\n                      \"the recursion depth %i: the limit is too low\",\n                      new_limit, depth);\n        return NULL;\n    }\n\n    Py_SetRecursionLimit(new_limit);\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nsys.set_coroutine_origin_tracking_depth\n\n  depth: int\n\nEnable or disable origin tracking for coroutine objects in this thread.\n\nCoroutine objects will track 'depth' frames of traceback information\nabout where they came from, available in their cr_origin attribute.\n\nSet a depth of 0 to disable.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_set_coroutine_origin_tracking_depth_impl(PyObject *module, int depth)\n/*[clinic end generated code: output=0a2123c1cc6759c5 input=a1d0a05f89d2c426]*/\n{\n    if (_PyEval_SetCoroutineOriginTrackingDepth(depth) < 0) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nsys.get_coroutine_origin_tracking_depth -> int\n\nCheck status of origin tracking for coroutine objects in this thread.\n[clinic start generated code]*/\n\nstatic int\nsys_get_coroutine_origin_tracking_depth_impl(PyObject *module)\n/*[clinic end generated code: output=3699f7be95a3afb8 input=335266a71205b61a]*/\n{\n    return _PyEval_GetCoroutineOriginTrackingDepth();\n}\n\nstatic PyTypeObject AsyncGenHooksType;\n\nPyDoc_STRVAR(asyncgen_hooks_doc,\n\"asyncgen_hooks\\n\\\n\\n\\\nA named tuple providing information about asynchronous\\n\\\ngenerators hooks.  The attributes are read only.\");\n\nstatic PyStructSequence_Field asyncgen_hooks_fields[] = {\n    {\"firstiter\", \"Hook to intercept first iteration\"},\n    {\"finalizer\", \"Hook to intercept finalization\"},\n    {0}\n};\n\nstatic PyStructSequence_Desc asyncgen_hooks_desc = {\n    \"asyncgen_hooks\",          /* name */\n    asyncgen_hooks_doc,        /* doc */\n    asyncgen_hooks_fields ,    /* fields */\n    2\n};\n\nstatic PyObject *\nsys_set_asyncgen_hooks(PyObject *self, PyObject *args, PyObject *kw)\n{\n    static char *keywords[] = {\"firstiter\", \"finalizer\", NULL};\n    PyObject *firstiter = NULL;\n    PyObject *finalizer = NULL;\n\n    if (!PyArg_ParseTupleAndKeywords(\n            args, kw, \"|OO\", keywords,\n            &firstiter, &finalizer)) {\n        return NULL;\n    }\n\n    if (finalizer && finalizer != Py_None) {\n        if (!PyCallable_Check(finalizer)) {\n            PyErr_Format(PyExc_TypeError,\n                         \"callable finalizer expected, got %.50s\",\n                         Py_TYPE(finalizer)->tp_name);\n            return NULL;\n        }\n        if (_PyEval_SetAsyncGenFinalizer(finalizer) < 0) {\n            return NULL;\n        }\n    }\n    else if (finalizer == Py_None && _PyEval_SetAsyncGenFinalizer(NULL) < 0) {\n        return NULL;\n    }\n\n    if (firstiter && firstiter != Py_None) {\n        if (!PyCallable_Check(firstiter)) {\n            PyErr_Format(PyExc_TypeError,\n                         \"callable firstiter expected, got %.50s\",\n                         Py_TYPE(firstiter)->tp_name);\n            return NULL;\n        }\n        if (_PyEval_SetAsyncGenFirstiter(firstiter) < 0) {\n            return NULL;\n        }\n    }\n    else if (firstiter == Py_None && _PyEval_SetAsyncGenFirstiter(NULL) < 0) {\n        return NULL;\n    }\n\n    Py_RETURN_NONE;\n}\n\nPyDoc_STRVAR(set_asyncgen_hooks_doc,\n\"set_asyncgen_hooks(* [, firstiter] [, finalizer])\\n\\\n\\n\\\nSet a finalizer for async generators objects.\"\n);\n\n/*[clinic input]\nsys.get_asyncgen_hooks\n\nReturn the installed asynchronous generators hooks.\n\nThis returns a namedtuple of the form (firstiter, finalizer).\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_get_asyncgen_hooks_impl(PyObject *module)\n/*[clinic end generated code: output=53a253707146f6cf input=3676b9ea62b14625]*/\n{\n    PyObject *res;\n    PyObject *firstiter = _PyEval_GetAsyncGenFirstiter();\n    PyObject *finalizer = _PyEval_GetAsyncGenFinalizer();\n\n    res = PyStructSequence_New(&AsyncGenHooksType);\n    if (res == NULL) {\n        return NULL;\n    }\n\n    if (firstiter == NULL) {\n        firstiter = Py_None;\n    }\n\n    if (finalizer == NULL) {\n        finalizer = Py_None;\n    }\n\n    PyStructSequence_SET_ITEM(res, 0, Py_NewRef(firstiter));\n    PyStructSequence_SET_ITEM(res, 1, Py_NewRef(finalizer));\n\n    return res;\n}\n\n\nstatic PyTypeObject Hash_InfoType;\n\nPyDoc_STRVAR(hash_info_doc,\n\"hash_info\\n\\\n\\n\\\nA named tuple providing parameters used for computing\\n\\\nhashes. The attributes are read only.\");\n\nstatic PyStructSequence_Field hash_info_fields[] = {\n    {\"width\", \"width of the type used for hashing, in bits\"},\n    {\"modulus\", \"prime number giving the modulus on which the hash \"\n                \"function is based\"},\n    {\"inf\", \"value to be used for hash of a positive infinity\"},\n    {\"nan\", \"value to be used for hash of a nan\"},\n    {\"imag\", \"multiplier used for the imaginary part of a complex number\"},\n    {\"algorithm\", \"name of the algorithm for hashing of str, bytes and \"\n                  \"memoryviews\"},\n    {\"hash_bits\", \"internal output size of hash algorithm\"},\n    {\"seed_bits\", \"seed size of hash algorithm\"},\n    {\"cutoff\", \"small string optimization cutoff\"},\n    {NULL, NULL}\n};\n\nstatic PyStructSequence_Desc hash_info_desc = {\n    \"sys.hash_info\",\n    hash_info_doc,\n    hash_info_fields,\n    9,\n};\n\nstatic PyObject *\nget_hash_info(PyThreadState *tstate)\n{\n    PyObject *hash_info;\n    int field = 0;\n    PyHash_FuncDef *hashfunc;\n    hash_info = PyStructSequence_New(&Hash_InfoType);\n    if (hash_info == NULL)\n        return NULL;\n    hashfunc = PyHash_GetFuncDef();\n    PyStructSequence_SET_ITEM(hash_info, field++,\n                              PyLong_FromLong(8*sizeof(Py_hash_t)));\n    PyStructSequence_SET_ITEM(hash_info, field++,\n                              PyLong_FromSsize_t(_PyHASH_MODULUS));\n    PyStructSequence_SET_ITEM(hash_info, field++,\n                              PyLong_FromLong(_PyHASH_INF));\n    PyStructSequence_SET_ITEM(hash_info, field++,\n                              PyLong_FromLong(0));  // This is no longer used\n    PyStructSequence_SET_ITEM(hash_info, field++,\n                              PyLong_FromLong(_PyHASH_IMAG));\n    PyStructSequence_SET_ITEM(hash_info, field++,\n                              PyUnicode_FromString(hashfunc->name));\n    PyStructSequence_SET_ITEM(hash_info, field++,\n                              PyLong_FromLong(hashfunc->hash_bits));\n    PyStructSequence_SET_ITEM(hash_info, field++,\n                              PyLong_FromLong(hashfunc->seed_bits));\n    PyStructSequence_SET_ITEM(hash_info, field++,\n                              PyLong_FromLong(Py_HASH_CUTOFF));\n    if (_PyErr_Occurred(tstate)) {\n        Py_CLEAR(hash_info);\n        return NULL;\n    }\n    return hash_info;\n}\n/*[clinic input]\nsys.getrecursionlimit\n\nReturn the current value of the recursion limit.\n\nThe recursion limit is the maximum depth of the Python interpreter\nstack.  This limit prevents infinite recursion from causing an overflow\nof the C stack and crashing Python.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_getrecursionlimit_impl(PyObject *module)\n/*[clinic end generated code: output=d571fb6b4549ef2e input=1c6129fd2efaeea8]*/\n{\n    return PyLong_FromLong(Py_GetRecursionLimit());\n}\n\n#ifdef MS_WINDOWS\n\nstatic PyTypeObject WindowsVersionType = {0, 0, 0, 0, 0, 0};\n\nstatic PyStructSequence_Field windows_version_fields[] = {\n    {\"major\", \"Major version number\"},\n    {\"minor\", \"Minor version number\"},\n    {\"build\", \"Build number\"},\n    {\"platform\", \"Operating system platform\"},\n    {\"service_pack\", \"Latest Service Pack installed on the system\"},\n    {\"service_pack_major\", \"Service Pack major version number\"},\n    {\"service_pack_minor\", \"Service Pack minor version number\"},\n    {\"suite_mask\", \"Bit mask identifying available product suites\"},\n    {\"product_type\", \"System product type\"},\n    {\"platform_version\", \"Diagnostic version number\"},\n    {0}\n};\n\nstatic PyStructSequence_Desc windows_version_desc = {\n    \"sys.getwindowsversion\",       /* name */\n    sys_getwindowsversion__doc__,  /* doc */\n    windows_version_fields,        /* fields */\n    5                              /* For backward compatibility,\n                                      only the first 5 items are accessible\n                                      via indexing, the rest are name only */\n};\n\nstatic PyObject *\n_sys_getwindowsversion_from_kernel32(void)\n{\n#ifndef MS_WINDOWS_DESKTOP\n    return NULL;\n#else\n    HANDLE hKernel32;\n    wchar_t kernel32_path[MAX_PATH];\n    LPVOID verblock;\n    DWORD verblock_size;\n    VS_FIXEDFILEINFO *ffi;\n    UINT ffi_len;\n    DWORD realMajor, realMinor, realBuild;\n\n    Py_BEGIN_ALLOW_THREADS\n    hKernel32 = GetModuleHandleW(L\"kernel32.dll\");\n    Py_END_ALLOW_THREADS\n    if (!hKernel32 || !GetModuleFileNameW(hKernel32, kernel32_path, MAX_PATH)) {\n        PyErr_SetFromWindowsErr(0);\n        return NULL;\n    }\n    verblock_size = GetFileVersionInfoSizeW(kernel32_path, NULL);\n    if (!verblock_size) {\n        PyErr_SetFromWindowsErr(0);\n        return NULL;\n    }\n    verblock = PyMem_RawMalloc(verblock_size);\n    if (!verblock ||\n        !GetFileVersionInfoW(kernel32_path, 0, verblock_size, verblock) ||\n        !VerQueryValueW(verblock, L\"\", (LPVOID)&ffi, &ffi_len)) {\n        PyErr_SetFromWindowsErr(0);\n        return NULL;\n    }\n\n    realMajor = HIWORD(ffi->dwProductVersionMS);\n    realMinor = LOWORD(ffi->dwProductVersionMS);\n    realBuild = HIWORD(ffi->dwProductVersionLS);\n    PyMem_RawFree(verblock);\n    return Py_BuildValue(\"(kkk)\", realMajor, realMinor, realBuild);\n#endif /* !MS_WINDOWS_DESKTOP */\n}\n\n/* Disable deprecation warnings about GetVersionEx as the result is\n   being passed straight through to the caller, who is responsible for\n   using it correctly. */\n#pragma warning(push)\n#pragma warning(disable:4996)\n\n/*[clinic input]\nsys.getwindowsversion\n\nReturn info about the running version of Windows as a named tuple.\n\nThe members are named: major, minor, build, platform, service_pack,\nservice_pack_major, service_pack_minor, suite_mask, product_type and\nplatform_version. For backward compatibility, only the first 5 items\nare available by indexing. All elements are numbers, except\nservice_pack and platform_type which are strings, and platform_version\nwhich is a 3-tuple. Platform is always 2. Product_type may be 1 for a\nworkstation, 2 for a domain controller, 3 for a server.\nPlatform_version is a 3-tuple containing a version number that is\nintended for identifying the OS rather than feature detection.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_getwindowsversion_impl(PyObject *module)\n/*[clinic end generated code: output=1ec063280b932857 input=73a228a328fee63a]*/\n{\n    PyObject *version;\n    int pos = 0;\n    OSVERSIONINFOEXW ver;\n\n    version = PyObject_GetAttrString(module, \"_cached_windows_version\");\n    if (version && PyObject_TypeCheck(version, &WindowsVersionType)) {\n        return version;\n    }\n    Py_XDECREF(version);\n    PyErr_Clear();\n\n    ver.dwOSVersionInfoSize = sizeof(ver);\n    if (!GetVersionExW((OSVERSIONINFOW*) &ver))\n        return PyErr_SetFromWindowsErr(0);\n\n    version = PyStructSequence_New(&WindowsVersionType);\n    if (version == NULL)\n        return NULL;\n\n    PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMajorVersion));\n    PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMinorVersion));\n    PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwBuildNumber));\n    PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwPlatformId));\n    PyStructSequence_SET_ITEM(version, pos++, PyUnicode_FromWideChar(ver.szCSDVersion, -1));\n    PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMajor));\n    PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMinor));\n    PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wSuiteMask));\n    PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wProductType));\n\n    // GetVersion will lie if we are running in a compatibility mode.\n    // We need to read the version info from a system file resource\n    // to accurately identify the OS version. If we fail for any reason,\n    // just return whatever GetVersion said.\n    PyObject *realVersion = _sys_getwindowsversion_from_kernel32();\n    if (!realVersion) {\n        PyErr_Clear();\n        realVersion = Py_BuildValue(\"(kkk)\",\n            ver.dwMajorVersion,\n            ver.dwMinorVersion,\n            ver.dwBuildNumber\n        );\n    }\n\n    if (realVersion) {\n        PyStructSequence_SET_ITEM(version, pos++, realVersion);\n    }\n\n    if (PyErr_Occurred()) {\n        Py_DECREF(version);\n        return NULL;\n    }\n\n    if (PyObject_SetAttrString(module, \"_cached_windows_version\", version) < 0) {\n        Py_DECREF(version);\n        return NULL;\n    }\n\n    return version;\n}\n\n#pragma warning(pop)\n\n/*[clinic input]\nsys._enablelegacywindowsfsencoding\n\nChanges the default filesystem encoding to mbcs:replace.\n\nThis is done for consistency with earlier versions of Python. See PEP\n529 for more information.\n\nThis is equivalent to defining the PYTHONLEGACYWINDOWSFSENCODING\nenvironment variable before launching Python.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__enablelegacywindowsfsencoding_impl(PyObject *module)\n/*[clinic end generated code: output=f5c3855b45e24fe9 input=2bfa931a20704492]*/\n{\n    if (_PyUnicode_EnableLegacyWindowsFSEncoding() < 0) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\n#endif /* MS_WINDOWS */\n\n#ifdef HAVE_DLOPEN\n\n/*[clinic input]\nsys.setdlopenflags\n\n    flags as new_val: int\n    /\n\nSet the flags used by the interpreter for dlopen calls.\n\nThis is used, for example, when the interpreter loads extension\nmodules. Among other things, this will enable a lazy resolving of\nsymbols when importing a module, if called as sys.setdlopenflags(0).\nTo share symbols across extension modules, call as\nsys.setdlopenflags(os.RTLD_GLOBAL).  Symbolic names for the flag\nmodules can be found in the os module (RTLD_xxx constants, e.g.\nos.RTLD_LAZY).\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_setdlopenflags_impl(PyObject *module, int new_val)\n/*[clinic end generated code: output=ec918b7fe0a37281 input=4c838211e857a77f]*/\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    _PyImport_SetDLOpenFlags(interp, new_val);\n    Py_RETURN_NONE;\n}\n\n\n/*[clinic input]\nsys.getdlopenflags\n\nReturn the current value of the flags that are used for dlopen calls.\n\nThe flag constants are defined in the os module.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_getdlopenflags_impl(PyObject *module)\n/*[clinic end generated code: output=e92cd1bc5005da6e input=dc4ea0899c53b4b6]*/\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    return PyLong_FromLong(\n            _PyImport_GetDLOpenFlags(interp));\n}\n\n#endif  /* HAVE_DLOPEN */\n\n#ifdef USE_MALLOPT\n/* Link with -lmalloc (or -lmpc) on an SGI */\n#include <malloc.h>\n\n/*[clinic input]\nsys.mdebug\n\n    flag: int\n    /\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_mdebug_impl(PyObject *module, int flag)\n/*[clinic end generated code: output=5431d545847c3637 input=151d150ae1636f8a]*/\n{\n    int flag;\n    mallopt(M_DEBUG, flag);\n    Py_RETURN_NONE;\n}\n#endif /* USE_MALLOPT */\n\n\n/*[clinic input]\nsys.get_int_max_str_digits\n\nReturn the maximum string digits limit for non-binary int<->str conversions.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_get_int_max_str_digits_impl(PyObject *module)\n/*[clinic end generated code: output=0042f5e8ae0e8631 input=61bf9f99bc8b112d]*/\n{\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    return PyLong_FromLong(interp->long_state.max_str_digits);\n}\n\n/*[clinic input]\nsys.set_int_max_str_digits\n\n    maxdigits: int\n\nSet the maximum string digits limit for non-binary int<->str conversions.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_set_int_max_str_digits_impl(PyObject *module, int maxdigits)\n/*[clinic end generated code: output=734d4c2511f2a56d input=d7e3f325db6910c5]*/\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if ((!maxdigits) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD)) {\n        tstate->interp->long_state.max_str_digits = maxdigits;\n        Py_RETURN_NONE;\n    } else {\n        PyErr_Format(\n            PyExc_ValueError, \"maxdigits must be 0 or larger than %d\",\n            _PY_LONG_MAX_STR_DIGITS_THRESHOLD);\n        return NULL;\n    }\n}\n\nsize_t\n_PySys_GetSizeOf(PyObject *o)\n{\n    PyObject *res = NULL;\n    PyObject *method;\n    Py_ssize_t size;\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    /* Make sure the type is initialized. float gets initialized late */\n    if (PyType_Ready(Py_TYPE(o)) < 0) {\n        return (size_t)-1;\n    }\n\n    method = _PyObject_LookupSpecial(o, &_Py_ID(__sizeof__));\n    if (method == NULL) {\n        if (!_PyErr_Occurred(tstate)) {\n            _PyErr_Format(tstate, PyExc_TypeError,\n                          \"Type %.100s doesn't define __sizeof__\",\n                          Py_TYPE(o)->tp_name);\n        }\n    }\n    else {\n        res = _PyObject_CallNoArgs(method);\n        Py_DECREF(method);\n    }\n\n    if (res == NULL)\n        return (size_t)-1;\n\n    size = PyLong_AsSsize_t(res);\n    Py_DECREF(res);\n    if (size == -1 && _PyErr_Occurred(tstate))\n        return (size_t)-1;\n\n    if (size < 0) {\n        _PyErr_SetString(tstate, PyExc_ValueError,\n                          \"__sizeof__() should return >= 0\");\n        return (size_t)-1;\n    }\n\n    return (size_t)size + _PyType_PreHeaderSize(Py_TYPE(o));\n}\n\nstatic PyObject *\nsys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds)\n{\n    static char *kwlist[] = {\"object\", \"default\", 0};\n    size_t size;\n    PyObject *o, *dflt = NULL;\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    if (!PyArg_ParseTupleAndKeywords(args, kwds, \"O|O:getsizeof\",\n                                     kwlist, &o, &dflt)) {\n        return NULL;\n    }\n\n    size = _PySys_GetSizeOf(o);\n\n    if (size == (size_t)-1 && _PyErr_Occurred(tstate)) {\n        /* Has a default value been given */\n        if (dflt != NULL && _PyErr_ExceptionMatches(tstate, PyExc_TypeError)) {\n            _PyErr_Clear(tstate);\n            return Py_NewRef(dflt);\n        }\n        else\n            return NULL;\n    }\n\n    return PyLong_FromSize_t(size);\n}\n\nPyDoc_STRVAR(getsizeof_doc,\n\"getsizeof(object [, default]) -> int\\n\\\n\\n\\\nReturn the size of object in bytes.\");\n\n/*[clinic input]\nsys.getrefcount -> Py_ssize_t\n\n    object:  object\n    /\n\nReturn the reference count of object.\n\nThe count returned is generally one higher than you might expect,\nbecause it includes the (temporary) reference as an argument to\ngetrefcount().\n[clinic start generated code]*/\n\nstatic Py_ssize_t\nsys_getrefcount_impl(PyObject *module, PyObject *object)\n/*[clinic end generated code: output=5fd477f2264b85b2 input=bf474efd50a21535]*/\n{\n    return Py_REFCNT(object);\n}\n\n#ifdef Py_REF_DEBUG\n/*[clinic input]\nsys.gettotalrefcount -> Py_ssize_t\n[clinic start generated code]*/\n\nstatic Py_ssize_t\nsys_gettotalrefcount_impl(PyObject *module)\n/*[clinic end generated code: output=4103886cf17c25bc input=53b744faa5d2e4f6]*/\n{\n    /* It may make sense to return the total for the current interpreter\n       or have a second function that does so. */\n    return _Py_GetGlobalRefTotal();\n}\n\n#endif /* Py_REF_DEBUG */\n\n/*[clinic input]\nsys.getallocatedblocks -> Py_ssize_t\n\nReturn the number of memory blocks currently allocated.\n[clinic start generated code]*/\n\nstatic Py_ssize_t\nsys_getallocatedblocks_impl(PyObject *module)\n/*[clinic end generated code: output=f0c4e873f0b6dcf7 input=dab13ee346a0673e]*/\n{\n    // It might make sense to return the count\n    // for just the current interpreter.\n    return _Py_GetGlobalAllocatedBlocks();\n}\n\n/*[clinic input]\nsys.getunicodeinternedsize -> Py_ssize_t\n\nReturn the number of elements of the unicode interned dictionary\n[clinic start generated code]*/\n\nstatic Py_ssize_t\nsys_getunicodeinternedsize_impl(PyObject *module)\n/*[clinic end generated code: output=ad0e4c9738ed4129 input=726298eaa063347a]*/\n{\n    return _PyUnicode_InternedSize();\n}\n\n/*[clinic input]\nsys._getframe\n\n    depth: int = 0\n    /\n\nReturn a frame object from the call stack.\n\nIf optional integer depth is given, return the frame object that many\ncalls below the top of the stack.  If that is deeper than the call\nstack, ValueError is raised.  The default for depth is zero, returning\nthe frame at the top of the call stack.\n\nThis function should be used for internal and specialized purposes\nonly.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__getframe_impl(PyObject *module, int depth)\n/*[clinic end generated code: output=d438776c04d59804 input=c1be8a6464b11ee5]*/\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    _PyInterpreterFrame *frame = tstate->cframe->current_frame;\n\n    if (frame != NULL) {\n        while (depth > 0) {\n            frame = _PyFrame_GetFirstComplete(frame->previous);\n            if (frame == NULL) {\n                break;\n            }\n            --depth;\n        }\n    }\n    if (frame == NULL) {\n        _PyErr_SetString(tstate, PyExc_ValueError,\n                         \"call stack is not deep enough\");\n        return NULL;\n    }\n\n    PyObject *pyFrame = Py_XNewRef((PyObject *)_PyFrame_GetFrameObject(frame));\n    if (pyFrame && _PySys_Audit(tstate, \"sys._getframe\", \"(O)\", pyFrame) < 0) {\n        Py_DECREF(pyFrame);\n        return NULL;\n    }\n    return pyFrame;\n}\n\n/*[clinic input]\nsys._current_frames\n\nReturn a dict mapping each thread's thread id to its current stack frame.\n\nThis function should be used for specialized purposes only.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__current_frames_impl(PyObject *module)\n/*[clinic end generated code: output=d2a41ac0a0a3809a input=2a9049c5f5033691]*/\n{\n    return _PyThread_CurrentFrames();\n}\n\n/*[clinic input]\nsys._current_exceptions\n\nReturn a dict mapping each thread's identifier to its current raised exception.\n\nThis function should be used for specialized purposes only.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__current_exceptions_impl(PyObject *module)\n/*[clinic end generated code: output=2ccfd838c746f0ba input=0e91818fbf2edc1f]*/\n{\n    return _PyThread_CurrentExceptions();\n}\n\n/*[clinic input]\nsys.call_tracing\n\n    func: object\n    args as funcargs: object(subclass_of='&PyTuple_Type')\n    /\n\nCall func(*args), while tracing is enabled.\n\nThe tracing state is saved, and restored afterwards.  This is intended\nto be called from a debugger from a checkpoint, to recursively debug\nsome other code.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_call_tracing_impl(PyObject *module, PyObject *func, PyObject *funcargs)\n/*[clinic end generated code: output=7e4999853cd4e5a6 input=5102e8b11049f92f]*/\n{\n    return _PyEval_CallTracing(func, funcargs);\n}\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*[clinic input]\nsys._debugmallocstats\n\nPrint summary info to stderr about the state of pymalloc's structures.\n\nIn Py_DEBUG mode, also perform some expensive internal consistency\nchecks.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__debugmallocstats_impl(PyObject *module)\n/*[clinic end generated code: output=ec3565f8c7cee46a input=33c0c9c416f98424]*/\n{\n#ifdef WITH_PYMALLOC\n    if (_PyObject_DebugMallocStats(stderr)) {\n        fputc('\\n', stderr);\n    }\n#endif\n    _PyObject_DebugTypeStats(stderr);\n\n    Py_RETURN_NONE;\n}\n\n#ifdef Py_TRACE_REFS\n/* Defined in objects.c because it uses static globals in that file */\nextern PyObject *_Py_GetObjects(PyObject *, PyObject *);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/*[clinic input]\nsys._clear_type_cache\n\nClear the internal type lookup cache.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__clear_type_cache_impl(PyObject *module)\n/*[clinic end generated code: output=20e48ca54a6f6971 input=127f3e04a8d9b555]*/\n{\n    PyType_ClearCache();\n    Py_RETURN_NONE;\n}\n\n/* Note that, for now, we do not have a per-interpreter equivalent\n  for sys.is_finalizing(). */\n\n/*[clinic input]\nsys.is_finalizing\n\nReturn True if Python is exiting.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_is_finalizing_impl(PyObject *module)\n/*[clinic end generated code: output=735b5ff7962ab281 input=f0df747a039948a5]*/\n{\n    return PyBool_FromLong(_Py_IsFinalizing());\n}\n\n#ifdef Py_STATS\n/*[clinic input]\nsys._stats_on\n\nTurns on stats gathering (stats gathering is on by default).\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__stats_on_impl(PyObject *module)\n/*[clinic end generated code: output=aca53eafcbb4d9fe input=8ddc6df94e484f3a]*/\n{\n    _py_stats = &_py_stats_struct;\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nsys._stats_off\n\nTurns off stats gathering (stats gathering is on by default).\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__stats_off_impl(PyObject *module)\n/*[clinic end generated code: output=1534c1ee63812214 input=b3e50e71ecf29f66]*/\n{\n    _py_stats = NULL;\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nsys._stats_clear\n\nClears the stats.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__stats_clear_impl(PyObject *module)\n/*[clinic end generated code: output=fb65a2525ee50604 input=3e03f2654f44da96]*/\n{\n    _Py_StatsClear();\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nsys._stats_dump\n\nDump stats to file, and clears the stats.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__stats_dump_impl(PyObject *module)\n/*[clinic end generated code: output=79f796fb2b4ddf05 input=92346f16d64f6f95]*/\n{\n    _Py_PrintSpecializationStats(1);\n    _Py_StatsClear();\n    Py_RETURN_NONE;\n}\n\n#endif\n\n#ifdef ANDROID_API_LEVEL\n/*[clinic input]\nsys.getandroidapilevel\n\nReturn the build time API version of Android as an integer.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_getandroidapilevel_impl(PyObject *module)\n/*[clinic end generated code: output=214abf183a1c70c1 input=3e6d6c9fcdd24ac6]*/\n{\n    return PyLong_FromLong(ANDROID_API_LEVEL);\n}\n#endif   /* ANDROID_API_LEVEL */\n\n/*[clinic input]\nsys.activate_stack_trampoline\n\n    backend: str\n    /\n\nActivate stack profiler trampoline *backend*.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_activate_stack_trampoline_impl(PyObject *module, const char *backend)\n/*[clinic end generated code: output=5783cdeb51874b43 input=a12df928758a82b4]*/\n{\n#ifdef PY_HAVE_PERF_TRAMPOLINE\n    if (strcmp(backend, \"perf\") == 0) {\n        _PyPerf_Callbacks cur_cb;\n        _PyPerfTrampoline_GetCallbacks(&cur_cb);\n        if (cur_cb.write_state != _Py_perfmap_callbacks.write_state) {\n            if (_PyPerfTrampoline_SetCallbacks(&_Py_perfmap_callbacks) < 0 ) {\n                PyErr_SetString(PyExc_ValueError, \"can't activate perf trampoline\");\n                return NULL;\n            }\n        }\n    }\n    else {\n        PyErr_Format(PyExc_ValueError, \"invalid backend: %s\", backend);\n        return NULL;\n    }\n    if (_PyPerfTrampoline_Init(1) < 0) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n#else\n    PyErr_SetString(PyExc_ValueError, \"perf trampoline not available\");\n    return NULL;\n#endif\n}\n\n\n/*[clinic input]\nsys.deactivate_stack_trampoline\n\nDeactivate the current stack profiler trampoline backend.\n\nIf no stack profiler is activated, this function has no effect.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_deactivate_stack_trampoline_impl(PyObject *module)\n/*[clinic end generated code: output=b50da25465df0ef1 input=9f629a6be9fe7fc8]*/\n{\n    if  (_PyPerfTrampoline_Init(0) < 0) {\n        return NULL;\n    }\n    Py_RETURN_NONE;\n}\n\n/*[clinic input]\nsys.is_stack_trampoline_active\n\nReturn *True* if a stack profiler trampoline is active.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys_is_stack_trampoline_active_impl(PyObject *module)\n/*[clinic end generated code: output=ab2746de0ad9d293 input=29616b7bf6a0b703]*/\n{\n#ifdef PY_HAVE_PERF_TRAMPOLINE\n    if (_PyIsPerfTrampolineActive()) {\n        Py_RETURN_TRUE;\n    }\n#endif\n    Py_RETURN_FALSE;\n}\n\n\n/*[clinic input]\nsys._getframemodulename\n\n    depth: int = 0\n\nReturn the name of the module for a calling frame.\n\nThe default depth returns the module containing the call to this API.\nA more typical use in a library will pass a depth of 1 to get the user's\nmodule rather than the library module.\n\nIf no frame, module, or name can be found, returns None.\n[clinic start generated code]*/\n\nstatic PyObject *\nsys__getframemodulename_impl(PyObject *module, int depth)\n/*[clinic end generated code: output=1d70ef691f09d2db input=d4f1a8ed43b8fb46]*/\n{\n    if (PySys_Audit(\"sys._getframemodulename\", \"i\", depth) < 0) {\n        return NULL;\n    }\n    _PyInterpreterFrame *f = _PyThreadState_GET()->cframe->current_frame;\n    while (f && (_PyFrame_IsIncomplete(f) || depth-- > 0)) {\n        f = f->previous;\n    }\n    if (f == NULL || f->f_funcobj == NULL) {\n        Py_RETURN_NONE;\n    }\n    PyObject *r = PyFunction_GetModule(f->f_funcobj);\n    if (!r) {\n        PyErr_Clear();\n        r = Py_None;\n    }\n    return Py_NewRef(r);\n}\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nstatic PerfMapState perf_map_state;\n\nPyAPI_FUNC(int) PyUnstable_PerfMapState_Init(void) {\n#ifndef MS_WINDOWS\n    char filename[100];\n    pid_t pid = getpid();\n    // Use nofollow flag to prevent symlink attacks.\n    int flags = O_WRONLY | O_CREAT | O_APPEND | O_NOFOLLOW | O_CLOEXEC;\n    snprintf(filename, sizeof(filename) - 1, \"/tmp/perf-%jd.map\",\n                (intmax_t)pid);\n    int fd = open(filename, flags, 0600);\n    if (fd == -1) {\n        return -1;\n    }\n    else{\n        perf_map_state.perf_map = fdopen(fd, \"a\");\n        if (perf_map_state.perf_map == NULL) {\n            close(fd);\n            return -1;\n        }\n    }\n    perf_map_state.map_lock = PyThread_allocate_lock();\n    if (perf_map_state.map_lock == NULL) {\n        fclose(perf_map_state.perf_map);\n        return -2;\n    }\n#endif\n    return 0;\n}\n\nPyAPI_FUNC(int) PyUnstable_WritePerfMapEntry(\n    const void *code_addr,\n    unsigned int code_size,\n    const char *entry_name\n) {\n#ifndef MS_WINDOWS\n    if (perf_map_state.perf_map == NULL) {\n        int ret = PyUnstable_PerfMapState_Init();\n        if(ret != 0){\n            return ret;\n        }\n    }\n    PyThread_acquire_lock(perf_map_state.map_lock, 1);\n    fprintf(perf_map_state.perf_map, \"%\" PRIxPTR \" %x %s\\n\", (uintptr_t) code_addr, code_size, entry_name);\n    fflush(perf_map_state.perf_map);\n    PyThread_release_lock(perf_map_state.map_lock);\n#endif\n    return 0;\n}\n\nPyAPI_FUNC(void) PyUnstable_PerfMapState_Fini(void) {\n#ifndef MS_WINDOWS\n    if (perf_map_state.perf_map != NULL) {\n        // close the file\n        PyThread_acquire_lock(perf_map_state.map_lock, 1);\n        fclose(perf_map_state.perf_map);\n        PyThread_release_lock(perf_map_state.map_lock);\n\n        // clean up the lock and state\n        PyThread_free_lock(perf_map_state.map_lock);\n        perf_map_state.perf_map = NULL;\n    }\n#endif\n}\n\n#ifdef __cplusplus\n}\n#endif\n\n\nstatic PyMethodDef sys_methods[] = {\n    /* Might as well keep this in alphabetic order */\n    SYS_ADDAUDITHOOK_METHODDEF\n    {\"audit\", _PyCFunction_CAST(sys_audit), METH_FASTCALL, audit_doc },\n    {\"breakpointhook\", _PyCFunction_CAST(sys_breakpointhook),\n     METH_FASTCALL | METH_KEYWORDS, breakpointhook_doc},\n    SYS__CLEAR_TYPE_CACHE_METHODDEF\n    SYS__CURRENT_FRAMES_METHODDEF\n    SYS__CURRENT_EXCEPTIONS_METHODDEF\n    SYS_DISPLAYHOOK_METHODDEF\n    SYS_EXCEPTION_METHODDEF\n    SYS_EXC_INFO_METHODDEF\n    SYS_EXCEPTHOOK_METHODDEF\n    SYS_EXIT_METHODDEF\n    SYS_GETDEFAULTENCODING_METHODDEF\n    SYS_GETDLOPENFLAGS_METHODDEF\n    SYS_GETALLOCATEDBLOCKS_METHODDEF\n    SYS_GETUNICODEINTERNEDSIZE_METHODDEF\n    SYS_GETFILESYSTEMENCODING_METHODDEF\n    SYS_GETFILESYSTEMENCODEERRORS_METHODDEF\n#ifdef Py_TRACE_REFS\n    {\"getobjects\", _Py_GetObjects, METH_VARARGS},\n#endif\n    SYS_GETTOTALREFCOUNT_METHODDEF\n    SYS_GETREFCOUNT_METHODDEF\n    SYS_GETRECURSIONLIMIT_METHODDEF\n    {\"getsizeof\", _PyCFunction_CAST(sys_getsizeof),\n     METH_VARARGS | METH_KEYWORDS, getsizeof_doc},\n    SYS__GETFRAME_METHODDEF\n    SYS__GETFRAMEMODULENAME_METHODDEF\n    SYS_GETWINDOWSVERSION_METHODDEF\n    SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF\n    SYS_INTERN_METHODDEF\n    SYS_IS_FINALIZING_METHODDEF\n    SYS_MDEBUG_METHODDEF\n    SYS_SETSWITCHINTERVAL_METHODDEF\n    SYS_GETSWITCHINTERVAL_METHODDEF\n    SYS_SETDLOPENFLAGS_METHODDEF\n    {\"setprofile\", sys_setprofile, METH_O, setprofile_doc},\n    SYS__SETPROFILEALLTHREADS_METHODDEF\n    SYS_GETPROFILE_METHODDEF\n    SYS_SETRECURSIONLIMIT_METHODDEF\n    {\"settrace\", sys_settrace, METH_O, settrace_doc},\n    SYS__SETTRACEALLTHREADS_METHODDEF\n    SYS_GETTRACE_METHODDEF\n    SYS_CALL_TRACING_METHODDEF\n    SYS__DEBUGMALLOCSTATS_METHODDEF\n    SYS_SET_COROUTINE_ORIGIN_TRACKING_DEPTH_METHODDEF\n    SYS_GET_COROUTINE_ORIGIN_TRACKING_DEPTH_METHODDEF\n    {\"set_asyncgen_hooks\", _PyCFunction_CAST(sys_set_asyncgen_hooks),\n     METH_VARARGS | METH_KEYWORDS, set_asyncgen_hooks_doc},\n    SYS_GET_ASYNCGEN_HOOKS_METHODDEF\n    SYS_GETANDROIDAPILEVEL_METHODDEF\n    SYS_ACTIVATE_STACK_TRAMPOLINE_METHODDEF\n    SYS_DEACTIVATE_STACK_TRAMPOLINE_METHODDEF\n    SYS_IS_STACK_TRAMPOLINE_ACTIVE_METHODDEF\n    SYS_UNRAISABLEHOOK_METHODDEF\n    SYS_GET_INT_MAX_STR_DIGITS_METHODDEF\n    SYS_SET_INT_MAX_STR_DIGITS_METHODDEF\n#ifdef Py_STATS\n    SYS__STATS_ON_METHODDEF\n    SYS__STATS_OFF_METHODDEF\n    SYS__STATS_CLEAR_METHODDEF\n    SYS__STATS_DUMP_METHODDEF\n#endif\n    {NULL, NULL}  // sentinel\n};\n\n\nstatic PyObject *\nlist_builtin_module_names(void)\n{\n    PyObject *list = _PyImport_GetBuiltinModuleNames();\n    if (list == NULL) {\n        return NULL;\n    }\n    if (PyList_Sort(list) != 0) {\n        goto error;\n    }\n    PyObject *tuple = PyList_AsTuple(list);\n    Py_DECREF(list);\n    return tuple;\n\nerror:\n    Py_DECREF(list);\n    return NULL;\n}\n\n\nstatic PyObject *\nlist_stdlib_module_names(void)\n{\n    Py_ssize_t len = Py_ARRAY_LENGTH(_Py_stdlib_module_names);\n    PyObject *names = PyTuple_New(len);\n    if (names == NULL) {\n        return NULL;\n    }\n\n    for (Py_ssize_t i = 0; i < len; i++) {\n        PyObject *name = PyUnicode_FromString(_Py_stdlib_module_names[i]);\n        if (name == NULL) {\n            Py_DECREF(names);\n            return NULL;\n        }\n        PyTuple_SET_ITEM(names, i, name);\n    }\n\n    PyObject *set = PyObject_CallFunction((PyObject *)&PyFrozenSet_Type,\n                                          \"(O)\", names);\n    Py_DECREF(names);\n    return set;\n}\n\n\n/* Pre-initialization support for sys.warnoptions and sys._xoptions\n *\n * Modern internal code paths:\n *   These APIs get called after _Py_InitializeCore and get to use the\n *   regular CPython list, dict, and unicode APIs.\n *\n * Legacy embedding code paths:\n *   The multi-phase initialization API isn't public yet, so embedding\n *   apps still need to be able configure sys.warnoptions and sys._xoptions\n *   before they call Py_Initialize. To support this, we stash copies of\n *   the supplied wchar * sequences in linked lists, and then migrate the\n *   contents of those lists to the sys module in _PyInitializeCore.\n *\n */\n\nstruct _preinit_entry {\n    wchar_t *value;\n    struct _preinit_entry *next;\n};\n\ntypedef struct _preinit_entry *_Py_PreInitEntry;\n\nstatic _Py_PreInitEntry _preinit_warnoptions = NULL;\nstatic _Py_PreInitEntry _preinit_xoptions = NULL;\n\nstatic _Py_PreInitEntry\n_alloc_preinit_entry(const wchar_t *value)\n{\n    /* To get this to work, we have to initialize the runtime implicitly */\n    _PyRuntime_Initialize();\n\n    /* Force default allocator, so we can ensure that it also gets used to\n     * destroy the linked list in _clear_preinit_entries.\n     */\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n\n    _Py_PreInitEntry node = PyMem_RawCalloc(1, sizeof(*node));\n    if (node != NULL) {\n        node->value = _PyMem_RawWcsdup(value);\n        if (node->value == NULL) {\n            PyMem_RawFree(node);\n            node = NULL;\n        };\n    };\n\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n    return node;\n}\n\nstatic int\n_append_preinit_entry(_Py_PreInitEntry *optionlist, const wchar_t *value)\n{\n    _Py_PreInitEntry new_entry = _alloc_preinit_entry(value);\n    if (new_entry == NULL) {\n        return -1;\n    }\n    /* We maintain the linked list in this order so it's easy to play back\n     * the add commands in the same order later on in _Py_InitializeCore\n     */\n    _Py_PreInitEntry last_entry = *optionlist;\n    if (last_entry == NULL) {\n        *optionlist = new_entry;\n    } else {\n        while (last_entry->next != NULL) {\n            last_entry = last_entry->next;\n        }\n        last_entry->next = new_entry;\n    }\n    return 0;\n}\n\nstatic void\n_clear_preinit_entries(_Py_PreInitEntry *optionlist)\n{\n    _Py_PreInitEntry current = *optionlist;\n    *optionlist = NULL;\n    /* Deallocate the nodes and their contents using the default allocator */\n    PyMemAllocatorEx old_alloc;\n    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n    while (current != NULL) {\n        _Py_PreInitEntry next = current->next;\n        PyMem_RawFree(current->value);\n        PyMem_RawFree(current);\n        current = next;\n    }\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);\n}\n\n\nPyStatus\n_PySys_ReadPreinitWarnOptions(PyWideStringList *options)\n{\n    PyStatus status;\n    _Py_PreInitEntry entry;\n\n    for (entry = _preinit_warnoptions; entry != NULL; entry = entry->next) {\n        status = PyWideStringList_Append(options, entry->value);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    _clear_preinit_entries(&_preinit_warnoptions);\n    return _PyStatus_OK();\n}\n\n\nPyStatus\n_PySys_ReadPreinitXOptions(PyConfig *config)\n{\n    PyStatus status;\n    _Py_PreInitEntry entry;\n\n    for (entry = _preinit_xoptions; entry != NULL; entry = entry->next) {\n        status = PyWideStringList_Append(&config->xoptions, entry->value);\n        if (_PyStatus_EXCEPTION(status)) {\n            return status;\n        }\n    }\n\n    _clear_preinit_entries(&_preinit_xoptions);\n    return _PyStatus_OK();\n}\n\n\nstatic PyObject *\nget_warnoptions(PyThreadState *tstate)\n{\n    PyObject *warnoptions = _PySys_GetAttr(tstate, &_Py_ID(warnoptions));\n    if (warnoptions == NULL || !PyList_Check(warnoptions)) {\n        /* PEP432 TODO: we can reach this if warnoptions is NULL in the main\n        *  interpreter config. When that happens, we need to properly set\n         * the `warnoptions` reference in the main interpreter config as well.\n         *\n         * For Python 3.7, we shouldn't be able to get here due to the\n         * combination of how _PyMainInterpreter_ReadConfig and _PySys_EndInit\n         * work, but we expect 3.8+ to make the _PyMainInterpreter_ReadConfig\n         * call optional for embedding applications, thus making this\n         * reachable again.\n         */\n        warnoptions = PyList_New(0);\n        if (warnoptions == NULL) {\n            return NULL;\n        }\n        if (sys_set_object(tstate->interp, &_Py_ID(warnoptions), warnoptions)) {\n            Py_DECREF(warnoptions);\n            return NULL;\n        }\n        Py_DECREF(warnoptions);\n    }\n    return warnoptions;\n}\n\nvoid\nPySys_ResetWarnOptions(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (tstate == NULL) {\n        _clear_preinit_entries(&_preinit_warnoptions);\n        return;\n    }\n\n    PyObject *warnoptions = _PySys_GetAttr(tstate, &_Py_ID(warnoptions));\n    if (warnoptions == NULL || !PyList_Check(warnoptions))\n        return;\n    PyList_SetSlice(warnoptions, 0, PyList_GET_SIZE(warnoptions), NULL);\n}\n\nstatic int\n_PySys_AddWarnOptionWithError(PyThreadState *tstate, PyObject *option)\n{\n    PyObject *warnoptions = get_warnoptions(tstate);\n    if (warnoptions == NULL) {\n        return -1;\n    }\n    if (PyList_Append(warnoptions, option)) {\n        return -1;\n    }\n    return 0;\n}\n\nvoid\nPySys_AddWarnOptionUnicode(PyObject *option)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (_PySys_AddWarnOptionWithError(tstate, option) < 0) {\n        /* No return value, therefore clear error state if possible */\n        if (tstate) {\n            _PyErr_Clear(tstate);\n        }\n    }\n}\n\nvoid\nPySys_AddWarnOption(const wchar_t *s)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (tstate == NULL) {\n        _append_preinit_entry(&_preinit_warnoptions, s);\n        return;\n    }\n    PyObject *unicode;\n    unicode = PyUnicode_FromWideChar(s, -1);\n    if (unicode == NULL)\n        return;\n_Py_COMP_DIAG_PUSH\n_Py_COMP_DIAG_IGNORE_DEPR_DECLS\n    PySys_AddWarnOptionUnicode(unicode);\n_Py_COMP_DIAG_POP\n    Py_DECREF(unicode);\n}\n\nint\nPySys_HasWarnOptions(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *warnoptions = _PySys_GetAttr(tstate, &_Py_ID(warnoptions));\n    return (warnoptions != NULL && PyList_Check(warnoptions)\n            && PyList_GET_SIZE(warnoptions) > 0);\n}\n\nstatic PyObject *\nget_xoptions(PyThreadState *tstate)\n{\n    PyObject *xoptions = _PySys_GetAttr(tstate, &_Py_ID(_xoptions));\n    if (xoptions == NULL || !PyDict_Check(xoptions)) {\n        /* PEP432 TODO: we can reach this if xoptions is NULL in the main\n        *  interpreter config. When that happens, we need to properly set\n         * the `xoptions` reference in the main interpreter config as well.\n         *\n         * For Python 3.7, we shouldn't be able to get here due to the\n         * combination of how _PyMainInterpreter_ReadConfig and _PySys_EndInit\n         * work, but we expect 3.8+ to make the _PyMainInterpreter_ReadConfig\n         * call optional for embedding applications, thus making this\n         * reachable again.\n         */\n        xoptions = PyDict_New();\n        if (xoptions == NULL) {\n            return NULL;\n        }\n        if (sys_set_object(tstate->interp, &_Py_ID(_xoptions), xoptions)) {\n            Py_DECREF(xoptions);\n            return NULL;\n        }\n        Py_DECREF(xoptions);\n    }\n    return xoptions;\n}\n\nstatic int\n_PySys_AddXOptionWithError(const wchar_t *s)\n{\n    PyObject *name = NULL, *value = NULL;\n\n    PyThreadState *tstate = _PyThreadState_GET();\n    PyObject *opts = get_xoptions(tstate);\n    if (opts == NULL) {\n        goto error;\n    }\n\n    const wchar_t *name_end = wcschr(s, L'=');\n    if (!name_end) {\n        name = PyUnicode_FromWideChar(s, -1);\n        value = Py_NewRef(Py_True);\n    }\n    else {\n        name = PyUnicode_FromWideChar(s, name_end - s);\n        value = PyUnicode_FromWideChar(name_end + 1, -1);\n    }\n    if (name == NULL || value == NULL) {\n        goto error;\n    }\n    if (PyDict_SetItem(opts, name, value) < 0) {\n        goto error;\n    }\n    Py_DECREF(name);\n    Py_DECREF(value);\n    return 0;\n\nerror:\n    Py_XDECREF(name);\n    Py_XDECREF(value);\n    return -1;\n}\n\nvoid\nPySys_AddXOption(const wchar_t *s)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    if (tstate == NULL) {\n        _append_preinit_entry(&_preinit_xoptions, s);\n        return;\n    }\n    if (_PySys_AddXOptionWithError(s) < 0) {\n        /* No return value, therefore clear error state if possible */\n        _PyErr_Clear(tstate);\n    }\n}\n\nPyObject *\nPySys_GetXOptions(void)\n{\n    PyThreadState *tstate = _PyThreadState_GET();\n    return get_xoptions(tstate);\n}\n\n/* XXX This doc string is too long to be a single string literal in VC++ 5.0.\n   Two literals concatenated works just fine.  If you have a K&R compiler\n   or other abomination that however *does* understand longer strings,\n   get rid of the !!! comment in the middle and the quotes that surround it. */\nPyDoc_VAR(sys_doc) =\nPyDoc_STR(\n\"This module provides access to some objects used or maintained by the\\n\\\ninterpreter and to functions that interact strongly with the interpreter.\\n\\\n\\n\\\nDynamic objects:\\n\\\n\\n\\\nargv -- command line arguments; argv[0] is the script pathname if known\\n\\\npath -- module search path; path[0] is the script directory, else ''\\n\\\nmodules -- dictionary of loaded modules\\n\\\n\\n\\\ndisplayhook -- called to show results in an interactive session\\n\\\nexcepthook -- called to handle any uncaught exception other than SystemExit\\n\\\n  To customize printing in an interactive session or to install a custom\\n\\\n  top-level exception handler, assign other functions to replace these.\\n\\\n\\n\\\nstdin -- standard input file object; used by input()\\n\\\nstdout -- standard output file object; used by print()\\n\\\nstderr -- standard error object; used for error messages\\n\\\n  By assigning other file objects (or objects that behave like files)\\n\\\n  to these, it is possible to redirect all of the interpreter's I/O.\\n\\\n\\n\\\nlast_exc - the last uncaught exception\\n\\\n  Only available in an interactive session after a\\n\\\n  traceback has been printed.\\n\\\nlast_type -- type of last uncaught exception\\n\\\nlast_value -- value of last uncaught exception\\n\\\nlast_traceback -- traceback of last uncaught exception\\n\\\n  These three are the (deprecated) legacy representation of last_exc.\\n\\\n\"\n)\n/* concatenating string here */\nPyDoc_STR(\n\"\\n\\\nStatic objects:\\n\\\n\\n\\\nbuiltin_module_names -- tuple of module names built into this interpreter\\n\\\ncopyright -- copyright notice pertaining to this interpreter\\n\\\nexec_prefix -- prefix used to find the machine-specific Python library\\n\\\nexecutable -- absolute path of the executable binary of the Python interpreter\\n\\\nfloat_info -- a named tuple with information about the float implementation.\\n\\\nfloat_repr_style -- string indicating the style of repr() output for floats\\n\\\nhash_info -- a named tuple with information about the hash algorithm.\\n\\\nhexversion -- version information encoded as a single integer\\n\\\nimplementation -- Python implementation information.\\n\\\nint_info -- a named tuple with information about the int implementation.\\n\\\nmaxsize -- the largest supported length of containers.\\n\\\nmaxunicode -- the value of the largest Unicode code point\\n\\\nplatform -- platform identifier\\n\\\nprefix -- prefix used to find the Python library\\n\\\nthread_info -- a named tuple with information about the thread implementation.\\n\\\nversion -- the version of this interpreter as a string\\n\\\nversion_info -- version information as a named tuple\\n\\\n\"\n)\n#ifdef MS_COREDLL\n/* concatenating string here */\nPyDoc_STR(\n\"dllhandle -- [Windows only] integer handle of the Python DLL\\n\\\nwinver -- [Windows only] version number of the Python DLL\\n\\\n\"\n)\n#endif /* MS_COREDLL */\n#ifdef MS_WINDOWS\n/* concatenating string here */\nPyDoc_STR(\n\"_enablelegacywindowsfsencoding -- [Windows only]\\n\\\n\"\n)\n#endif\nPyDoc_STR(\n\"__stdin__ -- the original stdin; don't touch!\\n\\\n__stdout__ -- the original stdout; don't touch!\\n\\\n__stderr__ -- the original stderr; don't touch!\\n\\\n__displayhook__ -- the original displayhook; don't touch!\\n\\\n__excepthook__ -- the original excepthook; don't touch!\\n\\\n\\n\\\nFunctions:\\n\\\n\\n\\\ndisplayhook() -- print an object to the screen, and save it in builtins._\\n\\\nexcepthook() -- print an exception and its traceback to sys.stderr\\n\\\nexception() -- return the current thread's active exception\\n\\\nexc_info() -- return information about the current thread's active exception\\n\\\nexit() -- exit the interpreter by raising SystemExit\\n\\\ngetdlopenflags() -- returns flags to be used for dlopen() calls\\n\\\ngetprofile() -- get the global profiling function\\n\\\ngetrefcount() -- return the reference count for an object (plus one :-)\\n\\\ngetrecursionlimit() -- return the max recursion depth for the interpreter\\n\\\ngetsizeof() -- return the size of an object in bytes\\n\\\ngettrace() -- get the global debug tracing function\\n\\\nsetdlopenflags() -- set the flags to be used for dlopen() calls\\n\\\nsetprofile() -- set the global profiling function\\n\\\nsetrecursionlimit() -- set the max recursion depth for the interpreter\\n\\\nsettrace() -- set the global debug tracing function\\n\\\n\"\n)\n/* end of sys_doc */ ;\n\n\nPyDoc_STRVAR(flags__doc__,\n\"sys.flags\\n\\\n\\n\\\nFlags provided through command line arguments or environment vars.\");\n\nstatic PyTypeObject FlagsType;\n\nstatic PyStructSequence_Field flags_fields[] = {\n    {\"debug\",                   \"-d\"},\n    {\"inspect\",                 \"-i\"},\n    {\"interactive\",             \"-i\"},\n    {\"optimize\",                \"-O or -OO\"},\n    {\"dont_write_bytecode\",     \"-B\"},\n    {\"no_user_site\",            \"-s\"},\n    {\"no_site\",                 \"-S\"},\n    {\"ignore_environment\",      \"-E\"},\n    {\"verbose\",                 \"-v\"},\n    {\"bytes_warning\",           \"-b\"},\n    {\"quiet\",                   \"-q\"},\n    {\"hash_randomization\",      \"-R\"},\n    {\"isolated\",                \"-I\"},\n    {\"dev_mode\",                \"-X dev\"},\n    {\"utf8_mode\",               \"-X utf8\"},\n    {\"warn_default_encoding\",   \"-X warn_default_encoding\"},\n    {\"safe_path\", \"-P\"},\n    {\"int_max_str_digits\",      \"-X int_max_str_digits\"},\n    {0}\n};\n\nstatic PyStructSequence_Desc flags_desc = {\n    \"sys.flags\",        /* name */\n    flags__doc__,       /* doc */\n    flags_fields,       /* fields */\n    18\n};\n\nstatic int\nset_flags_from_config(PyInterpreterState *interp, PyObject *flags)\n{\n    const PyPreConfig *preconfig = &interp->runtime->preconfig;\n    const PyConfig *config = _PyInterpreterState_GetConfig(interp);\n\n    // _PySys_UpdateConfig() modifies sys.flags in-place:\n    // Py_XDECREF() is needed in this case.\n    Py_ssize_t pos = 0;\n#define SetFlagObj(expr) \\\n    do { \\\n        PyObject *value = (expr); \\\n        if (value == NULL) { \\\n            return -1; \\\n        } \\\n        Py_XDECREF(PyStructSequence_GET_ITEM(flags, pos)); \\\n        PyStructSequence_SET_ITEM(flags, pos, value); \\\n        pos++; \\\n    } while (0)\n#define SetFlag(expr) SetFlagObj(PyLong_FromLong(expr))\n\n    SetFlag(config->parser_debug);\n    SetFlag(config->inspect);\n    SetFlag(config->interactive);\n    SetFlag(config->optimization_level);\n    SetFlag(!config->write_bytecode);\n    SetFlag(!config->user_site_directory);\n    SetFlag(!config->site_import);\n    SetFlag(!config->use_environment);\n    SetFlag(config->verbose);\n    SetFlag(config->bytes_warning);\n    SetFlag(config->quiet);\n    SetFlag(config->use_hash_seed == 0 || config->hash_seed != 0);\n    SetFlag(config->isolated);\n    SetFlagObj(PyBool_FromLong(config->dev_mode));\n    SetFlag(preconfig->utf8_mode);\n    SetFlag(config->warn_default_encoding);\n    SetFlagObj(PyBool_FromLong(config->safe_path));\n    SetFlag(config->int_max_str_digits);\n#undef SetFlagObj\n#undef SetFlag\n    return 0;\n}\n\n\nstatic PyObject*\nmake_flags(PyInterpreterState *interp)\n{\n    PyObject *flags = PyStructSequence_New(&FlagsType);\n    if (flags == NULL) {\n        return NULL;\n    }\n\n    if (set_flags_from_config(interp, flags) < 0) {\n        Py_DECREF(flags);\n        return NULL;\n    }\n    return flags;\n}\n\n\nPyDoc_STRVAR(version_info__doc__,\n\"sys.version_info\\n\\\n\\n\\\nVersion information as a named tuple.\");\n\nstatic PyTypeObject VersionInfoType;\n\nstatic PyStructSequence_Field version_info_fields[] = {\n    {\"major\", \"Major release number\"},\n    {\"minor\", \"Minor release number\"},\n    {\"micro\", \"Patch release number\"},\n    {\"releaselevel\", \"'alpha', 'beta', 'candidate', or 'final'\"},\n    {\"serial\", \"Serial release number\"},\n    {0}\n};\n\nstatic PyStructSequence_Desc version_info_desc = {\n    \"sys.version_info\",     /* name */\n    version_info__doc__,    /* doc */\n    version_info_fields,    /* fields */\n    5\n};\n\nstatic PyObject *\nmake_version_info(PyThreadState *tstate)\n{\n    PyObject *version_info;\n    char *s;\n    int pos = 0;\n\n    version_info = PyStructSequence_New(&VersionInfoType);\n    if (version_info == NULL) {\n        return NULL;\n    }\n\n    /*\n     * These release level checks are mutually exclusive and cover\n     * the field, so don't get too fancy with the pre-processor!\n     */\n#if PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_ALPHA\n    s = \"alpha\";\n#elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_BETA\n    s = \"beta\";\n#elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_GAMMA\n    s = \"candidate\";\n#elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_FINAL\n    s = \"final\";\n#endif\n\n#define SetIntItem(flag) \\\n    PyStructSequence_SET_ITEM(version_info, pos++, PyLong_FromLong(flag))\n#define SetStrItem(flag) \\\n    PyStructSequence_SET_ITEM(version_info, pos++, PyUnicode_FromString(flag))\n\n    SetIntItem(PY_MAJOR_VERSION);\n    SetIntItem(PY_MINOR_VERSION);\n    SetIntItem(PY_MICRO_VERSION);\n    SetStrItem(s);\n    SetIntItem(PY_RELEASE_SERIAL);\n#undef SetIntItem\n#undef SetStrItem\n\n    if (_PyErr_Occurred(tstate)) {\n        Py_CLEAR(version_info);\n        return NULL;\n    }\n    return version_info;\n}\n\n/* sys.implementation values */\n#define NAME \"cpython\"\nconst char *_PySys_ImplName = NAME;\n#define MAJOR Py_STRINGIFY(PY_MAJOR_VERSION)\n#define MINOR Py_STRINGIFY(PY_MINOR_VERSION)\n#define TAG NAME \"-\" MAJOR MINOR\nconst char *_PySys_ImplCacheTag = TAG;\n#undef NAME\n#undef MAJOR\n#undef MINOR\n#undef TAG\n\nstatic PyObject *\nmake_impl_info(PyObject *version_info)\n{\n    int res;\n    PyObject *impl_info, *value, *ns;\n\n    impl_info = PyDict_New();\n    if (impl_info == NULL)\n        return NULL;\n\n    /* populate the dict */\n\n    value = PyUnicode_FromString(_PySys_ImplName);\n    if (value == NULL)\n        goto error;\n    res = PyDict_SetItemString(impl_info, \"name\", value);\n    Py_DECREF(value);\n    if (res < 0)\n        goto error;\n\n    value = PyUnicode_FromString(_PySys_ImplCacheTag);\n    if (value == NULL)\n        goto error;\n    res = PyDict_SetItemString(impl_info, \"cache_tag\", value);\n    Py_DECREF(value);\n    if (res < 0)\n        goto error;\n\n    res = PyDict_SetItemString(impl_info, \"version\", version_info);\n    if (res < 0)\n        goto error;\n\n    value = PyLong_FromLong(PY_VERSION_HEX);\n    if (value == NULL)\n        goto error;\n    res = PyDict_SetItemString(impl_info, \"hexversion\", value);\n    Py_DECREF(value);\n    if (res < 0)\n        goto error;\n\n#ifdef MULTIARCH\n    value = PyUnicode_FromString(MULTIARCH);\n    if (value == NULL)\n        goto error;\n    res = PyDict_SetItemString(impl_info, \"_multiarch\", value);\n    Py_DECREF(value);\n    if (res < 0)\n        goto error;\n#endif\n\n    /* dict ready */\n\n    ns = _PyNamespace_New(impl_info);\n    Py_DECREF(impl_info);\n    return ns;\n\nerror:\n    Py_CLEAR(impl_info);\n    return NULL;\n}\n\n#ifdef __EMSCRIPTEN__\n\nPyDoc_STRVAR(emscripten_info__doc__,\n\"sys._emscripten_info\\n\\\n\\n\\\nWebAssembly Emscripten platform information.\");\n\nstatic PyTypeObject *EmscriptenInfoType;\n\nstatic PyStructSequence_Field emscripten_info_fields[] = {\n    {\"emscripten_version\", \"Emscripten version (major, minor, micro)\"},\n    {\"runtime\", \"Runtime (Node.JS version, browser user agent)\"},\n    {\"pthreads\", \"pthread support\"},\n    {\"shared_memory\", \"shared memory support\"},\n    {0}\n};\n\nstatic PyStructSequence_Desc emscripten_info_desc = {\n    \"sys._emscripten_info\",     /* name */\n    emscripten_info__doc__ ,    /* doc */\n    emscripten_info_fields,     /* fields */\n    4\n};\n\nEM_JS(char *, _Py_emscripten_runtime, (void), {\n    var info;\n    if (typeof navigator == 'object') {\n        info = navigator.userAgent;\n    } else if (typeof process == 'object') {\n        info = \"Node.js \".concat(process.version);\n    } else {\n        info = \"UNKNOWN\";\n    }\n    var len = lengthBytesUTF8(info) + 1;\n    var res = _malloc(len);\n    if (res) stringToUTF8(info, res, len);\n#if __wasm64__\n    return BigInt(res);\n#else\n    return res;\n#endif\n});\n\nstatic PyObject *\nmake_emscripten_info(void)\n{\n    PyObject *emscripten_info = NULL;\n    PyObject *version = NULL;\n    char *ua;\n    int pos = 0;\n\n    emscripten_info = PyStructSequence_New(EmscriptenInfoType);\n    if (emscripten_info == NULL) {\n        return NULL;\n    }\n\n    version = Py_BuildValue(\"(iii)\",\n        __EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__);\n    if (version == NULL) {\n        goto error;\n    }\n    PyStructSequence_SET_ITEM(emscripten_info, pos++, version);\n\n    ua = _Py_emscripten_runtime();\n    if (ua != NULL) {\n        PyObject *oua = PyUnicode_DecodeUTF8(ua, strlen(ua), \"strict\");\n        free(ua);\n        if (oua == NULL) {\n            goto error;\n        }\n        PyStructSequence_SET_ITEM(emscripten_info, pos++, oua);\n    } else {\n        PyStructSequence_SET_ITEM(emscripten_info, pos++, Py_NewRef(Py_None));\n    }\n\n#define SetBoolItem(flag) \\\n    PyStructSequence_SET_ITEM(emscripten_info, pos++, PyBool_FromLong(flag))\n\n#ifdef __EMSCRIPTEN_PTHREADS__\n    SetBoolItem(1);\n#else\n    SetBoolItem(0);\n#endif\n\n#ifdef __EMSCRIPTEN_SHARED_MEMORY__\n    SetBoolItem(1);\n#else\n    SetBoolItem(0);\n#endif\n\n#undef SetBoolItem\n\n    if (PyErr_Occurred()) {\n        goto error;\n    }\n    return emscripten_info;\n\n  error:\n    Py_CLEAR(emscripten_info);\n    return NULL;\n}\n\n#endif // __EMSCRIPTEN__\n\nstatic struct PyModuleDef sysmodule = {\n    PyModuleDef_HEAD_INIT,\n    \"sys\",\n    sys_doc,\n    -1, /* multiple \"initialization\" just copies the module dict. */\n    sys_methods,\n    NULL,\n    NULL,\n    NULL,\n    NULL\n};\n\n/* Updating the sys namespace, returning NULL pointer on error */\n#define SET_SYS(key, value)                                \\\n    do {                                                   \\\n        PyObject *v = (value);                             \\\n        if (v == NULL) {                                   \\\n            goto err_occurred;                             \\\n        }                                                  \\\n        res = PyDict_SetItemString(sysdict, key, v);       \\\n        Py_DECREF(v);                                      \\\n        if (res < 0) {                                     \\\n            goto err_occurred;                             \\\n        }                                                  \\\n    } while (0)\n\n#define SET_SYS_FROM_STRING(key, value) \\\n        SET_SYS(key, PyUnicode_FromString(value))\n\nstatic PyStatus\n_PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)\n{\n    PyObject *version_info;\n    int res;\n    PyInterpreterState *interp = tstate->interp;\n\n    /* stdin/stdout/stderr are set in pylifecycle.c */\n\n#define COPY_SYS_ATTR(tokey, fromkey) \\\n        SET_SYS(tokey, PyMapping_GetItemString(sysdict, fromkey))\n\n    COPY_SYS_ATTR(\"__displayhook__\", \"displayhook\");\n    COPY_SYS_ATTR(\"__excepthook__\", \"excepthook\");\n    COPY_SYS_ATTR(\"__breakpointhook__\", \"breakpointhook\");\n    COPY_SYS_ATTR(\"__unraisablehook__\", \"unraisablehook\");\n\n#undef COPY_SYS_ATTR\n\n    SET_SYS_FROM_STRING(\"version\", Py_GetVersion());\n    SET_SYS(\"hexversion\", PyLong_FromLong(PY_VERSION_HEX));\n    SET_SYS(\"_git\", Py_BuildValue(\"(szz)\", \"CPython\", _Py_gitidentifier(),\n                                  _Py_gitversion()));\n    SET_SYS_FROM_STRING(\"_framework\", _PYTHONFRAMEWORK);\n    SET_SYS(\"api_version\", PyLong_FromLong(PYTHON_API_VERSION));\n    SET_SYS_FROM_STRING(\"copyright\", Py_GetCopyright());\n    SET_SYS_FROM_STRING(\"platform\", Py_GetPlatform());\n    SET_SYS(\"maxsize\", PyLong_FromSsize_t(PY_SSIZE_T_MAX));\n    SET_SYS(\"float_info\", PyFloat_GetInfo());\n    SET_SYS(\"int_info\", PyLong_GetInfo());\n    /* initialize hash_info */\n    if (_PyStructSequence_InitBuiltin(interp, &Hash_InfoType,\n                                      &hash_info_desc) < 0)\n    {\n        goto type_init_failed;\n    }\n    SET_SYS(\"hash_info\", get_hash_info(tstate));\n    SET_SYS(\"maxunicode\", PyLong_FromLong(0x10FFFF));\n    SET_SYS(\"builtin_module_names\", list_builtin_module_names());\n    SET_SYS(\"stdlib_module_names\", list_stdlib_module_names());\n#if PY_BIG_ENDIAN\n    SET_SYS_FROM_STRING(\"byteorder\", \"big\");\n#else\n    SET_SYS_FROM_STRING(\"byteorder\", \"little\");\n#endif\n\n#ifdef MS_COREDLL\n    SET_SYS(\"dllhandle\", PyLong_FromVoidPtr(PyWin_DLLhModule));\n    SET_SYS_FROM_STRING(\"winver\", PyWin_DLLVersionString);\n#endif\n#ifdef ABIFLAGS\n    SET_SYS_FROM_STRING(\"abiflags\", ABIFLAGS);\n#endif\n\n#define ENSURE_INFO_TYPE(TYPE, DESC) \\\n    do { \\\n        if (_PyStructSequence_InitBuiltinWithFlags( \\\n                interp, &TYPE, &DESC, Py_TPFLAGS_DISALLOW_INSTANTIATION) < 0) { \\\n            goto type_init_failed; \\\n        } \\\n    } while (0)\n\n    /* version_info */\n    ENSURE_INFO_TYPE(VersionInfoType, version_info_desc);\n    version_info = make_version_info(tstate);\n    SET_SYS(\"version_info\", version_info);\n\n    /* implementation */\n    SET_SYS(\"implementation\", make_impl_info(version_info));\n\n    // sys.flags: updated in-place later by _PySys_UpdateConfig()\n    ENSURE_INFO_TYPE(FlagsType, flags_desc);\n    SET_SYS(\"flags\", make_flags(tstate->interp));\n\n#if defined(MS_WINDOWS)\n    /* getwindowsversion */\n    ENSURE_INFO_TYPE(WindowsVersionType, windows_version_desc);\n\n    SET_SYS_FROM_STRING(\"_vpath\", VPATH);\n#endif\n\n#undef ENSURE_INFO_TYPE\n\n    /* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */\n#if _PY_SHORT_FLOAT_REPR == 1\n    SET_SYS_FROM_STRING(\"float_repr_style\", \"short\");\n#else\n    SET_SYS_FROM_STRING(\"float_repr_style\", \"legacy\");\n#endif\n\n    SET_SYS(\"thread_info\", PyThread_GetInfo());\n\n    /* initialize asyncgen_hooks */\n    if (_PyStructSequence_InitBuiltin(interp, &AsyncGenHooksType,\n                                      &asyncgen_hooks_desc) < 0)\n    {\n        goto type_init_failed;\n    }\n\n#ifdef __EMSCRIPTEN__\n    if (EmscriptenInfoType == NULL) {\n        EmscriptenInfoType = PyStructSequence_NewType(&emscripten_info_desc);\n        if (EmscriptenInfoType == NULL) {\n            goto type_init_failed;\n        }\n    }\n    SET_SYS(\"_emscripten_info\", make_emscripten_info());\n#endif\n\n    /* adding sys.path_hooks and sys.path_importer_cache */\n    SET_SYS(\"meta_path\", PyList_New(0));\n    SET_SYS(\"path_importer_cache\", PyDict_New());\n    SET_SYS(\"path_hooks\", PyList_New(0));\n\n    if (_PyErr_Occurred(tstate)) {\n        goto err_occurred;\n    }\n    return _PyStatus_OK();\n\ntype_init_failed:\n    return _PyStatus_ERR(\"failed to initialize a type\");\n\nerr_occurred:\n    return _PyStatus_ERR(\"can't initialize sys module\");\n}\n\nstatic int\nsys_add_xoption(PyObject *opts, const wchar_t *s)\n{\n    PyObject *name, *value;\n\n    const wchar_t *name_end = wcschr(s, L'=');\n    if (!name_end) {\n        name = PyUnicode_FromWideChar(s, -1);\n        value = Py_NewRef(Py_True);\n    }\n    else {\n        name = PyUnicode_FromWideChar(s, name_end - s);\n        value = PyUnicode_FromWideChar(name_end + 1, -1);\n    }\n    if (name == NULL || value == NULL) {\n        goto error;\n    }\n    if (PyDict_SetItem(opts, name, value) < 0) {\n        goto error;\n    }\n    Py_DECREF(name);\n    Py_DECREF(value);\n    return 0;\n\nerror:\n    Py_XDECREF(name);\n    Py_XDECREF(value);\n    return -1;\n}\n\n\nstatic PyObject*\nsys_create_xoptions_dict(const PyConfig *config)\n{\n    Py_ssize_t nxoption = config->xoptions.length;\n    wchar_t * const * xoptions = config->xoptions.items;\n    PyObject *dict = PyDict_New();\n    if (dict == NULL) {\n        return NULL;\n    }\n\n    for (Py_ssize_t i=0; i < nxoption; i++) {\n        const wchar_t *option = xoptions[i];\n        if (sys_add_xoption(dict, option) < 0) {\n            Py_DECREF(dict);\n            return NULL;\n        }\n    }\n\n    return dict;\n}\n\n\n// Update sys attributes for a new PyConfig configuration.\n// This function also adds attributes that _PySys_InitCore() didn't add.\nint\n_PySys_UpdateConfig(PyThreadState *tstate)\n{\n    PyInterpreterState *interp = tstate->interp;\n    PyObject *sysdict = interp->sysdict;\n    const PyConfig *config = _PyInterpreterState_GetConfig(interp);\n    int res;\n\n#define COPY_LIST(KEY, VALUE) \\\n        SET_SYS(KEY, _PyWideStringList_AsList(&(VALUE)));\n\n#define SET_SYS_FROM_WSTR(KEY, VALUE) \\\n        SET_SYS(KEY, PyUnicode_FromWideChar(VALUE, -1));\n\n#define COPY_WSTR(SYS_ATTR, WSTR) \\\n    if (WSTR != NULL) { \\\n        SET_SYS_FROM_WSTR(SYS_ATTR, WSTR); \\\n    }\n\n    if (config->module_search_paths_set) {\n        COPY_LIST(\"path\", config->module_search_paths);\n    }\n\n    COPY_WSTR(\"executable\", config->executable);\n    COPY_WSTR(\"_base_executable\", config->base_executable);\n    COPY_WSTR(\"prefix\", config->prefix);\n    COPY_WSTR(\"base_prefix\", config->base_prefix);\n    COPY_WSTR(\"exec_prefix\", config->exec_prefix);\n    COPY_WSTR(\"base_exec_prefix\", config->base_exec_prefix);\n    COPY_WSTR(\"platlibdir\", config->platlibdir);\n\n    if (config->pycache_prefix != NULL) {\n        SET_SYS_FROM_WSTR(\"pycache_prefix\", config->pycache_prefix);\n    } else {\n        PyDict_SetItemString(sysdict, \"pycache_prefix\", Py_None);\n    }\n\n    COPY_LIST(\"argv\", config->argv);\n    COPY_LIST(\"orig_argv\", config->orig_argv);\n    COPY_LIST(\"warnoptions\", config->warnoptions);\n\n    SET_SYS(\"_xoptions\", sys_create_xoptions_dict(config));\n\n    const wchar_t *stdlibdir = _Py_GetStdlibDir();\n    if (stdlibdir != NULL) {\n        SET_SYS_FROM_WSTR(\"_stdlib_dir\", stdlibdir);\n    }\n    else {\n        PyDict_SetItemString(sysdict, \"_stdlib_dir\", Py_None);\n    }\n\n#undef SET_SYS_FROM_WSTR\n#undef COPY_LIST\n#undef COPY_WSTR\n\n    // sys.flags\n    PyObject *flags = _PySys_GetObject(interp, \"flags\"); // borrowed ref\n    if (flags == NULL) {\n        return -1;\n    }\n    if (set_flags_from_config(interp, flags) < 0) {\n        return -1;\n    }\n\n    SET_SYS(\"dont_write_bytecode\", PyBool_FromLong(!config->write_bytecode));\n\n    if (_PyErr_Occurred(tstate)) {\n        goto err_occurred;\n    }\n\n    return 0;\n\nerr_occurred:\n    return -1;\n}\n\n#undef SET_SYS\n#undef SET_SYS_FROM_STRING\n\n\n/* Set up a preliminary stderr printer until we have enough\n   infrastructure for the io module in place.\n\n   Use UTF-8/backslashreplace and ignore EAGAIN errors. */\nstatic PyStatus\n_PySys_SetPreliminaryStderr(PyObject *sysdict)\n{\n    PyObject *pstderr = PyFile_NewStdPrinter(fileno(stderr));\n    if (pstderr == NULL) {\n        goto error;\n    }\n    if (PyDict_SetItem(sysdict, &_Py_ID(stderr), pstderr) < 0) {\n        goto error;\n    }\n    if (PyDict_SetItemString(sysdict, \"__stderr__\", pstderr) < 0) {\n        goto error;\n    }\n    Py_DECREF(pstderr);\n    return _PyStatus_OK();\n\nerror:\n    Py_XDECREF(pstderr);\n    return _PyStatus_ERR(\"can't set preliminary stderr\");\n}\n\nPyObject *_Py_CreateMonitoringObject(void);\n\n/* Create sys module without all attributes.\n   _PySys_UpdateConfig() should be called later to add remaining attributes. */\nPyStatus\n_PySys_Create(PyThreadState *tstate, PyObject **sysmod_p)\n{\n    assert(!_PyErr_Occurred(tstate));\n\n    PyInterpreterState *interp = tstate->interp;\n\n    PyObject *modules = _PyImport_InitModules(interp);\n    if (modules == NULL) {\n        goto error;\n    }\n\n    PyObject *sysmod = _PyModule_CreateInitialized(&sysmodule, PYTHON_API_VERSION);\n    if (sysmod == NULL) {\n        return _PyStatus_ERR(\"failed to create a module object\");\n    }\n\n    PyObject *sysdict = PyModule_GetDict(sysmod);\n    if (sysdict == NULL) {\n        goto error;\n    }\n    interp->sysdict = Py_NewRef(sysdict);\n\n    interp->sysdict_copy = PyDict_Copy(sysdict);\n    if (interp->sysdict_copy == NULL) {\n        goto error;\n    }\n\n    if (PyDict_SetItemString(sysdict, \"modules\", modules) < 0) {\n        goto error;\n    }\n\n    PyStatus status = _PySys_SetPreliminaryStderr(sysdict);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    status = _PySys_InitCore(tstate, sysdict);\n    if (_PyStatus_EXCEPTION(status)) {\n        return status;\n    }\n\n    if (_PyImport_FixupBuiltin(sysmod, \"sys\", modules) < 0) {\n        goto error;\n    }\n\n    PyObject *monitoring = _Py_CreateMonitoringObject();\n    if (monitoring == NULL) {\n        goto error;\n    }\n    int err = PyDict_SetItemString(sysdict, \"monitoring\", monitoring);\n    Py_DECREF(monitoring);\n    if (err < 0) {\n        goto error;\n    }\n\n    assert(!_PyErr_Occurred(tstate));\n\n    *sysmod_p = sysmod;\n    return _PyStatus_OK();\n\nerror:\n    return _PyStatus_ERR(\"can't initialize sys module\");\n}\n\n\nvoid\n_PySys_FiniTypes(PyInterpreterState *interp)\n{\n    _PyStructSequence_FiniBuiltin(interp, &VersionInfoType);\n    _PyStructSequence_FiniBuiltin(interp, &FlagsType);\n#if defined(MS_WINDOWS)\n    _PyStructSequence_FiniBuiltin(interp, &WindowsVersionType);\n#endif\n    _PyStructSequence_FiniBuiltin(interp, &Hash_InfoType);\n    _PyStructSequence_FiniBuiltin(interp, &AsyncGenHooksType);\n#ifdef __EMSCRIPTEN__\n    if (_Py_IsMainInterpreter(interp)) {\n        Py_CLEAR(EmscriptenInfoType);\n    }\n#endif\n}\n\n\nstatic PyObject *\nmakepathobject(const wchar_t *path, wchar_t delim)\n{\n    int i, n;\n    const wchar_t *p;\n    PyObject *v, *w;\n\n    n = 1;\n    p = path;\n    while ((p = wcschr(p, delim)) != NULL) {\n        n++;\n        p++;\n    }\n    v = PyList_New(n);\n    if (v == NULL)\n        return NULL;\n    for (i = 0; ; i++) {\n        p = wcschr(path, delim);\n        if (p == NULL)\n            p = path + wcslen(path); /* End of string */\n        w = PyUnicode_FromWideChar(path, (Py_ssize_t)(p - path));\n        if (w == NULL) {\n            Py_DECREF(v);\n            return NULL;\n        }\n        PyList_SET_ITEM(v, i, w);\n        if (*p == '\\0')\n            break;\n        path = p+1;\n    }\n    return v;\n}\n\nvoid\nPySys_SetPath(const wchar_t *path)\n{\n    PyObject *v;\n    if ((v = makepathobject(path, DELIM)) == NULL)\n        Py_FatalError(\"can't create sys.path\");\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (sys_set_object(interp, &_Py_ID(path), v) != 0) {\n        Py_FatalError(\"can't assign sys.path\");\n    }\n    Py_DECREF(v);\n}\n\nstatic PyObject *\nmake_sys_argv(int argc, wchar_t * const * argv)\n{\n    PyObject *list = PyList_New(argc);\n    if (list == NULL) {\n        return NULL;\n    }\n\n    for (Py_ssize_t i = 0; i < argc; i++) {\n        PyObject *v = PyUnicode_FromWideChar(argv[i], -1);\n        if (v == NULL) {\n            Py_DECREF(list);\n            return NULL;\n        }\n        PyList_SET_ITEM(list, i, v);\n    }\n    return list;\n}\n\nvoid\nPySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)\n{\n    wchar_t* empty_argv[1] = {L\"\"};\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    if (argc < 1 || argv == NULL) {\n        /* Ensure at least one (empty) argument is seen */\n        argv = empty_argv;\n        argc = 1;\n    }\n\n    PyObject *av = make_sys_argv(argc, argv);\n    if (av == NULL) {\n        Py_FatalError(\"no mem for sys.argv\");\n    }\n    if (sys_set_object_str(tstate->interp, \"argv\", av) != 0) {\n        Py_DECREF(av);\n        Py_FatalError(\"can't assign sys.argv\");\n    }\n    Py_DECREF(av);\n\n    if (updatepath) {\n        /* If argv[0] is not '-c' nor '-m', prepend argv[0] to sys.path.\n           If argv[0] is a symlink, use the real path. */\n        const PyWideStringList argv_list = {.length = argc, .items = argv};\n        PyObject *path0 = NULL;\n        if (_PyPathConfig_ComputeSysPath0(&argv_list, &path0)) {\n            if (path0 == NULL) {\n                Py_FatalError(\"can't compute path0 from argv\");\n            }\n\n            PyObject *sys_path = _PySys_GetAttr(tstate, &_Py_ID(path));\n            if (sys_path != NULL) {\n                if (PyList_Insert(sys_path, 0, path0) < 0) {\n                    Py_DECREF(path0);\n                    Py_FatalError(\"can't prepend path0 to sys.path\");\n                }\n            }\n            Py_DECREF(path0);\n        }\n    }\n}\n\nvoid\nPySys_SetArgv(int argc, wchar_t **argv)\n{\n_Py_COMP_DIAG_PUSH\n_Py_COMP_DIAG_IGNORE_DEPR_DECLS\n    PySys_SetArgvEx(argc, argv, Py_IsolatedFlag == 0);\n_Py_COMP_DIAG_POP\n}\n\n/* Reimplementation of PyFile_WriteString() no calling indirectly\n   PyErr_CheckSignals(): avoid the call to PyObject_Str(). */\n\nstatic int\nsys_pyfile_write_unicode(PyObject *unicode, PyObject *file)\n{\n    if (file == NULL)\n        return -1;\n    assert(unicode != NULL);\n    PyObject *result = _PyObject_CallMethodOneArg(file, &_Py_ID(write), unicode);\n    if (result == NULL) {\n        return -1;\n    }\n    Py_DECREF(result);\n    return 0;\n}\n\nstatic int\nsys_pyfile_write(const char *text, PyObject *file)\n{\n    PyObject *unicode = NULL;\n    int err;\n\n    if (file == NULL)\n        return -1;\n\n    unicode = PyUnicode_FromString(text);\n    if (unicode == NULL)\n        return -1;\n\n    err = sys_pyfile_write_unicode(unicode, file);\n    Py_DECREF(unicode);\n    return err;\n}\n\n/* APIs to write to sys.stdout or sys.stderr using a printf-like interface.\n   Adapted from code submitted by Just van Rossum.\n\n   PySys_WriteStdout(format, ...)\n   PySys_WriteStderr(format, ...)\n\n      The first function writes to sys.stdout; the second to sys.stderr.  When\n      there is a problem, they write to the real (C level) stdout or stderr;\n      no exceptions are raised.\n\n      PyErr_CheckSignals() is not called to avoid the execution of the Python\n      signal handlers: they may raise a new exception whereas sys_write()\n      ignores all exceptions.\n\n      Both take a printf-style format string as their first argument followed\n      by a variable length argument list determined by the format string.\n\n      *** WARNING ***\n\n      The format should limit the total size of the formatted output string to\n      1000 bytes.  In particular, this means that no unrestricted \"%s\" formats\n      should occur; these should be limited using \"%.<N>s where <N> is a\n      decimal number calculated so that <N> plus the maximum size of other\n      formatted text does not exceed 1000 bytes.  Also watch out for \"%f\",\n      which can print hundreds of digits for very large numbers.\n\n */\n\nstatic void\nsys_write(PyObject *key, FILE *fp, const char *format, va_list va)\n{\n    PyObject *file;\n    char buffer[1001];\n    int written;\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    file = _PySys_GetAttr(tstate, key);\n    written = PyOS_vsnprintf(buffer, sizeof(buffer), format, va);\n    if (sys_pyfile_write(buffer, file) != 0) {\n        _PyErr_Clear(tstate);\n        fputs(buffer, fp);\n    }\n    if (written < 0 || (size_t)written >= sizeof(buffer)) {\n        const char *truncated = \"... truncated\";\n        if (sys_pyfile_write(truncated, file) != 0)\n            fputs(truncated, fp);\n    }\n    _PyErr_SetRaisedException(tstate, exc);\n}\n\nvoid\nPySys_WriteStdout(const char *format, ...)\n{\n    va_list va;\n\n    va_start(va, format);\n    sys_write(&_Py_ID(stdout), stdout, format, va);\n    va_end(va);\n}\n\nvoid\nPySys_WriteStderr(const char *format, ...)\n{\n    va_list va;\n\n    va_start(va, format);\n    sys_write(&_Py_ID(stderr), stderr, format, va);\n    va_end(va);\n}\n\nstatic void\nsys_format(PyObject *key, FILE *fp, const char *format, va_list va)\n{\n    PyObject *file, *message;\n    const char *utf8;\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n    file = _PySys_GetAttr(tstate, key);\n    message = PyUnicode_FromFormatV(format, va);\n    if (message != NULL) {\n        if (sys_pyfile_write_unicode(message, file) != 0) {\n            _PyErr_Clear(tstate);\n            utf8 = PyUnicode_AsUTF8(message);\n            if (utf8 != NULL)\n                fputs(utf8, fp);\n        }\n        Py_DECREF(message);\n    }\n    _PyErr_SetRaisedException(tstate, exc);\n}\n\nvoid\nPySys_FormatStdout(const char *format, ...)\n{\n    va_list va;\n\n    va_start(va, format);\n    sys_format(&_Py_ID(stdout), stdout, format, va);\n    va_end(va);\n}\n\nvoid\nPySys_FormatStderr(const char *format, ...)\n{\n    va_list va;\n\n    va_start(va, format);\n    sys_format(&_Py_ID(stderr), stderr, format, va);\n    va_end(va);\n}\n"
  },
  {
    "path": "Thread.c",
    "content": "\n/* Thread package.\n   This is intended to be usable independently from Python.\n   The implementation for system foobar is in a file thread_foobar.h\n   which is included by this file dependent on config settings.\n   Stuff shared by all thread_*.h files is collected here. */\n\n#include \"Python.h\"\n#include \"pycore_pystate.h\"       // _PyInterpreterState_GET()\n#include \"pycore_structseq.h\"     // _PyStructSequence_FiniBuiltin()\n#include \"pycore_pythread.h\"\n\n#ifndef DONT_HAVE_STDIO_H\n#include <stdio.h>\n#endif\n\n#include <stdlib.h>\n\n\nstatic void PyThread__init_thread(void); /* Forward */\n\n#define initialized _PyRuntime.threads.initialized\n\nvoid\nPyThread_init_thread(void)\n{\n    if (initialized) {\n        return;\n    }\n    initialized = 1;\n    PyThread__init_thread();\n}\n\n#if defined(HAVE_PTHREAD_STUBS)\n#   define PYTHREAD_NAME \"pthread-stubs\"\n#   include \"thread_pthread_stubs.h\"\n#elif defined(_USE_PTHREADS)  /* AKA _PTHREADS */\n#   if defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)\n#     define PYTHREAD_NAME \"pthread-stubs\"\n#   else\n#     define PYTHREAD_NAME \"pthread\"\n#   endif\n#   include \"thread_pthread.h\"\n#elif defined(NT_THREADS)\n#   define PYTHREAD_NAME \"nt\"\n#   include \"thread_nt.h\"\n#else\n#   error \"Require native threads. See https://bugs.python.org/issue31370\"\n#endif\n\n\n/* return the current thread stack size */\nsize_t\nPyThread_get_stacksize(void)\n{\n    return _PyInterpreterState_GET()->threads.stacksize;\n}\n\n/* Only platforms defining a THREAD_SET_STACKSIZE() macro\n   in thread_<platform>.h support changing the stack size.\n   Return 0 if stack size is valid,\n      -1 if stack size value is invalid,\n      -2 if setting stack size is not supported. */\nint\nPyThread_set_stacksize(size_t size)\n{\n#if defined(THREAD_SET_STACKSIZE)\n    return THREAD_SET_STACKSIZE(size);\n#else\n    return -2;\n#endif\n}\n\n\n/* Thread Specific Storage (TSS) API\n\n   Cross-platform components of TSS API implementation.\n*/\n\nPy_tss_t *\nPyThread_tss_alloc(void)\n{\n    Py_tss_t *new_key = (Py_tss_t *)PyMem_RawMalloc(sizeof(Py_tss_t));\n    if (new_key == NULL) {\n        return NULL;\n    }\n    new_key->_is_initialized = 0;\n    return new_key;\n}\n\nvoid\nPyThread_tss_free(Py_tss_t *key)\n{\n    if (key != NULL) {\n        PyThread_tss_delete(key);\n        PyMem_RawFree((void *)key);\n    }\n}\n\nint\nPyThread_tss_is_created(Py_tss_t *key)\n{\n    assert(key != NULL);\n    return key->_is_initialized;\n}\n\n\nPyDoc_STRVAR(threadinfo__doc__,\n\"sys.thread_info\\n\\\n\\n\\\nA named tuple holding information about the thread implementation.\");\n\nstatic PyStructSequence_Field threadinfo_fields[] = {\n    {\"name\",    \"name of the thread implementation\"},\n    {\"lock\",    \"name of the lock implementation\"},\n    {\"version\", \"name and version of the thread library\"},\n    {0}\n};\n\nstatic PyStructSequence_Desc threadinfo_desc = {\n    \"sys.thread_info\",           /* name */\n    threadinfo__doc__,           /* doc */\n    threadinfo_fields,           /* fields */\n    3\n};\n\nstatic PyTypeObject ThreadInfoType;\n\nPyObject*\nPyThread_GetInfo(void)\n{\n    PyObject *threadinfo, *value;\n    int pos = 0;\n#if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \\\n     && defined(_CS_GNU_LIBPTHREAD_VERSION))\n    char buffer[255];\n    int len;\n#endif\n\n    PyInterpreterState *interp = _PyInterpreterState_GET();\n    if (_PyStructSequence_InitBuiltin(interp, &ThreadInfoType, &threadinfo_desc) < 0) {\n        return NULL;\n    }\n\n    threadinfo = PyStructSequence_New(&ThreadInfoType);\n    if (threadinfo == NULL)\n        return NULL;\n\n    value = PyUnicode_FromString(PYTHREAD_NAME);\n    if (value == NULL) {\n        Py_DECREF(threadinfo);\n        return NULL;\n    }\n    PyStructSequence_SET_ITEM(threadinfo, pos++, value);\n\n#ifdef HAVE_PTHREAD_STUBS\n    value = Py_NewRef(Py_None);\n#elif defined(_POSIX_THREADS)\n#ifdef USE_SEMAPHORES\n    value = PyUnicode_FromString(\"semaphore\");\n#else\n    value = PyUnicode_FromString(\"mutex+cond\");\n#endif\n    if (value == NULL) {\n        Py_DECREF(threadinfo);\n        return NULL;\n    }\n#else\n    value = Py_NewRef(Py_None);\n#endif\n    PyStructSequence_SET_ITEM(threadinfo, pos++, value);\n\n#if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \\\n     && defined(_CS_GNU_LIBPTHREAD_VERSION))\n    value = NULL;\n    len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));\n    if (1 < len && (size_t)len < sizeof(buffer)) {\n        value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);\n        if (value == NULL)\n            PyErr_Clear();\n    }\n    if (value == NULL)\n#endif\n    {\n        value = Py_NewRef(Py_None);\n    }\n    PyStructSequence_SET_ITEM(threadinfo, pos++, value);\n    return threadinfo;\n}\n\n\nvoid\n_PyThread_FiniType(PyInterpreterState *interp)\n{\n    _PyStructSequence_FiniBuiltin(interp, &ThreadInfoType);\n}\n"
  },
  {
    "path": "Thread_NT.h",
    "content": "#include \"pycore_interp.h\"    // _PyInterpreterState.threads.stacksize\n\n/* This code implemented by Dag.Gruneau@elsa.preseco.comm.se */\n/* Fast NonRecursiveMutex support by Yakov Markovitch, markovitch@iso.ru */\n/* Eliminated some memory leaks, gsw@agere.com */\n\n#include <windows.h>\n#include <limits.h>\n#ifdef HAVE_PROCESS_H\n#include <process.h>\n#endif\n\n/* options */\n#ifndef _PY_USE_CV_LOCKS\n#define _PY_USE_CV_LOCKS 1     /* use locks based on cond vars */\n#endif\n\n/* Now, define a non-recursive mutex using either condition variables\n * and critical sections (fast) or using operating system mutexes\n * (slow)\n */\n\n#if _PY_USE_CV_LOCKS\n\n#include \"condvar.h\"\n\ntypedef struct _NRMUTEX\n{\n    PyMUTEX_T cs;\n    PyCOND_T cv;\n    int locked;\n} NRMUTEX;\ntypedef NRMUTEX *PNRMUTEX;\n\nstatic PNRMUTEX\nAllocNonRecursiveMutex(void)\n{\n    PNRMUTEX m = (PNRMUTEX)PyMem_RawMalloc(sizeof(NRMUTEX));\n    if (!m)\n        return NULL;\n    if (PyCOND_INIT(&m->cv))\n        goto fail;\n    if (PyMUTEX_INIT(&m->cs)) {\n        PyCOND_FINI(&m->cv);\n        goto fail;\n    }\n    m->locked = 0;\n    return m;\nfail:\n    PyMem_RawFree(m);\n    return NULL;\n}\n\nstatic VOID\nFreeNonRecursiveMutex(PNRMUTEX mutex)\n{\n    if (mutex) {\n        PyCOND_FINI(&mutex->cv);\n        PyMUTEX_FINI(&mutex->cs);\n        PyMem_RawFree(mutex);\n    }\n}\n\nstatic DWORD\nEnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds)\n{\n    DWORD result = WAIT_OBJECT_0;\n    if (PyMUTEX_LOCK(&mutex->cs))\n        return WAIT_FAILED;\n    if (milliseconds == INFINITE) {\n        while (mutex->locked) {\n            if (PyCOND_WAIT(&mutex->cv, &mutex->cs)) {\n                result = WAIT_FAILED;\n                break;\n            }\n        }\n    } else if (milliseconds != 0) {\n        /* wait at least until the deadline */\n        _PyTime_t nanoseconds = _PyTime_FromNanoseconds((_PyTime_t)milliseconds * 1000000);\n        _PyTime_t deadline = _PyTime_Add(_PyTime_GetPerfCounter(), nanoseconds);\n        while (mutex->locked) {\n            _PyTime_t microseconds = _PyTime_AsMicroseconds(nanoseconds,\n                                                            _PyTime_ROUND_TIMEOUT);\n            if (PyCOND_TIMEDWAIT(&mutex->cv, &mutex->cs, microseconds) < 0) {\n                result = WAIT_FAILED;\n                break;\n            }\n            nanoseconds = deadline - _PyTime_GetPerfCounter();\n            if (nanoseconds <= 0) {\n                break;\n            }\n        }\n    }\n    if (!mutex->locked) {\n        mutex->locked = 1;\n        result = WAIT_OBJECT_0;\n    } else if (result == WAIT_OBJECT_0)\n        result = WAIT_TIMEOUT;\n    /* else, it is WAIT_FAILED */\n    PyMUTEX_UNLOCK(&mutex->cs); /* must ignore result here */\n    return result;\n}\n\nstatic BOOL\nLeaveNonRecursiveMutex(PNRMUTEX mutex)\n{\n    BOOL result;\n    if (PyMUTEX_LOCK(&mutex->cs))\n        return FALSE;\n    mutex->locked = 0;\n    /* condvar APIs return 0 on success. We need to return TRUE on success. */\n    result = !PyCOND_SIGNAL(&mutex->cv);\n    PyMUTEX_UNLOCK(&mutex->cs);\n    return result;\n}\n\n#else /* if ! _PY_USE_CV_LOCKS */\n\n/* NR-locks based on a kernel mutex */\n#define PNRMUTEX HANDLE\n\nstatic PNRMUTEX\nAllocNonRecursiveMutex(void)\n{\n    return CreateSemaphore(NULL, 1, 1, NULL);\n}\n\nstatic VOID\nFreeNonRecursiveMutex(PNRMUTEX mutex)\n{\n    /* No in-use check */\n    CloseHandle(mutex);\n}\n\nstatic DWORD\nEnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds)\n{\n    return WaitForSingleObjectEx(mutex, milliseconds, FALSE);\n}\n\nstatic BOOL\nLeaveNonRecursiveMutex(PNRMUTEX mutex)\n{\n    return ReleaseSemaphore(mutex, 1, NULL);\n}\n#endif /* _PY_USE_CV_LOCKS */\n\nunsigned long PyThread_get_thread_ident(void);\n\n#ifdef PY_HAVE_THREAD_NATIVE_ID\nunsigned long PyThread_get_thread_native_id(void);\n#endif\n\n/*\n * Initialization for the current runtime.\n */\nstatic void\nPyThread__init_thread(void)\n{\n    // Initialization of the C package should not be needed.\n}\n\n/*\n * Thread support.\n */\n\ntypedef struct {\n    void (*func)(void*);\n    void *arg;\n} callobj;\n\n/* thunker to call adapt between the function type used by the system's\nthread start function and the internally used one. */\nstatic unsigned __stdcall\nbootstrap(void *call)\n{\n    callobj *obj = (callobj*)call;\n    void (*func)(void*) = obj->func;\n    void *arg = obj->arg;\n    HeapFree(GetProcessHeap(), 0, obj);\n    func(arg);\n    return 0;\n}\n\nunsigned long\nPyThread_start_new_thread(void (*func)(void *), void *arg)\n{\n    HANDLE hThread;\n    unsigned threadID;\n    callobj *obj;\n\n    if (!initialized)\n        PyThread_init_thread();\n\n    obj = (callobj*)HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));\n    if (!obj)\n        return PYTHREAD_INVALID_THREAD_ID;\n    obj->func = func;\n    obj->arg = arg;\n    PyThreadState *tstate = _PyThreadState_GET();\n    size_t stacksize = tstate ? tstate->interp->threads.stacksize : 0;\n    hThread = (HANDLE)_beginthreadex(0,\n                      Py_SAFE_DOWNCAST(stacksize, Py_ssize_t, unsigned int),\n                      bootstrap, obj,\n                      0, &threadID);\n    if (hThread == 0) {\n        /* I've seen errno == EAGAIN here, which means \"there are\n         * too many threads\".\n         */\n        int e = errno;\n        threadID = (unsigned)-1;\n        HeapFree(GetProcessHeap(), 0, obj);\n    }\n    else {\n        CloseHandle(hThread);\n    }\n    return threadID;\n}\n\n/*\n * Return the thread Id instead of a handle. The Id is said to uniquely identify the\n * thread in the system\n */\nunsigned long\nPyThread_get_thread_ident(void)\n{\n    if (!initialized)\n        PyThread_init_thread();\n\n    return GetCurrentThreadId();\n}\n\n#ifdef PY_HAVE_THREAD_NATIVE_ID\n/*\n * Return the native Thread ID (TID) of the calling thread.\n * The native ID of a thread is valid and guaranteed to be unique system-wide\n * from the time the thread is created until the thread has been terminated.\n */\nunsigned long\nPyThread_get_thread_native_id(void)\n{\n    if (!initialized) {\n        PyThread_init_thread();\n    }\n\n    DWORD native_id;\n    native_id = GetCurrentThreadId();\n    return (unsigned long) native_id;\n}\n#endif\n\nvoid _Py_NO_RETURN\nPyThread_exit_thread(void)\n{\n    if (!initialized)\n        exit(0);\n    _endthreadex(0);\n}\n\n/*\n * Lock support. It has to be implemented as semaphores.\n * I [Dag] tried to implement it with mutex but I could find a way to\n * tell whether a thread already own the lock or not.\n */\nPyThread_type_lock\nPyThread_allocate_lock(void)\n{\n    PNRMUTEX mutex;\n\n    if (!initialized)\n        PyThread_init_thread();\n\n    mutex = AllocNonRecursiveMutex() ;\n\n    PyThread_type_lock aLock = (PyThread_type_lock) mutex;\n    assert(aLock);\n\n    return aLock;\n}\n\nvoid\nPyThread_free_lock(PyThread_type_lock aLock)\n{\n    FreeNonRecursiveMutex(aLock) ;\n}\n\n// WaitForSingleObject() accepts timeout in milliseconds in the range\n// [0; 0xFFFFFFFE] (DWORD type). INFINITE value (0xFFFFFFFF) means no\n// timeout. 0xFFFFFFFE milliseconds is around 49.7 days.\nconst DWORD TIMEOUT_MS_MAX = 0xFFFFFFFE;\n\n/*\n * Return 1 on success if the lock was acquired\n *\n * and 0 if the lock was not acquired. This means a 0 is returned\n * if the lock has already been acquired by this thread!\n */\nPyLockStatus\nPyThread_acquire_lock_timed(PyThread_type_lock aLock,\n                            PY_TIMEOUT_T microseconds, int intr_flag)\n{\n    assert(aLock);\n\n    /* Fow now, intr_flag does nothing on Windows, and lock acquires are\n     * uninterruptible.  */\n    PyLockStatus success;\n    PY_TIMEOUT_T milliseconds;\n\n    if (microseconds >= 0) {\n        milliseconds = microseconds / 1000;\n        // Round milliseconds away from zero\n        if (microseconds % 1000 > 0) {\n            milliseconds++;\n        }\n        if (milliseconds > (PY_TIMEOUT_T)TIMEOUT_MS_MAX) {\n            // bpo-41710: PyThread_acquire_lock_timed() cannot report timeout\n            // overflow to the caller, so clamp the timeout to\n            // [0, TIMEOUT_MS_MAX] milliseconds.\n            //\n            // _thread.Lock.acquire() and _thread.RLock.acquire() raise an\n            // OverflowError if microseconds is greater than PY_TIMEOUT_MAX.\n            milliseconds = TIMEOUT_MS_MAX;\n        }\n        assert(milliseconds != INFINITE);\n    }\n    else {\n        milliseconds = INFINITE;\n    }\n\n    if (EnterNonRecursiveMutex((PNRMUTEX)aLock,\n                               (DWORD)milliseconds) == WAIT_OBJECT_0) {\n        success = PY_LOCK_ACQUIRED;\n    }\n    else {\n        success = PY_LOCK_FAILURE;\n    }\n\n    return success;\n}\nint\nPyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)\n{\n    return PyThread_acquire_lock_timed(aLock, waitflag ? -1 : 0, 0);\n}\n\nvoid\nPyThread_release_lock(PyThread_type_lock aLock)\n{\n    assert(aLock);\n    (void)LeaveNonRecursiveMutex((PNRMUTEX) aLock);\n}\n\n/* minimum/maximum thread stack sizes supported */\n#define THREAD_MIN_STACKSIZE    0x8000          /* 32 KiB */\n#define THREAD_MAX_STACKSIZE    0x10000000      /* 256 MiB */\n\n/* set the thread stack size.\n * Return 0 if size is valid, -1 otherwise.\n */\nstatic int\n_pythread_nt_set_stacksize(size_t size)\n{\n    /* set to default */\n    if (size == 0) {\n        _PyInterpreterState_GET()->threads.stacksize = 0;\n        return 0;\n    }\n\n    /* valid range? */\n    if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {\n        _PyInterpreterState_GET()->threads.stacksize = size;\n        return 0;\n    }\n\n    return -1;\n}\n\n#define THREAD_SET_STACKSIZE(x) _pythread_nt_set_stacksize(x)\n\n\n/* Thread Local Storage (TLS) API\n\n   This API is DEPRECATED since Python 3.7.  See PEP 539 for details.\n*/\n\nint\nPyThread_create_key(void)\n{\n    DWORD result = TlsAlloc();\n    if (result == TLS_OUT_OF_INDEXES)\n        return -1;\n    return (int)result;\n}\n\nvoid\nPyThread_delete_key(int key)\n{\n    TlsFree(key);\n}\n\nint\nPyThread_set_key_value(int key, void *value)\n{\n    BOOL ok = TlsSetValue(key, value);\n    return ok ? 0 : -1;\n}\n\nvoid *\nPyThread_get_key_value(int key)\n{\n    /* because TLS is used in the Py_END_ALLOW_THREAD macro,\n     * it is necessary to preserve the windows error state, because\n     * it is assumed to be preserved across the call to the macro.\n     * Ideally, the macro should be fixed, but it is simpler to\n     * do it here.\n     */\n    DWORD error = GetLastError();\n    void *result = TlsGetValue(key);\n    SetLastError(error);\n    return result;\n}\n\nvoid\nPyThread_delete_key_value(int key)\n{\n    /* NULL is used as \"key missing\", and it is also the default\n     * given by TlsGetValue() if nothing has been set yet.\n     */\n    TlsSetValue(key, NULL);\n}\n\n\n/* reinitialization of TLS is not necessary after fork when using\n * the native TLS functions.  And forking isn't supported on Windows either.\n */\nvoid\nPyThread_ReInitTLS(void)\n{\n}\n\n\n/* Thread Specific Storage (TSS) API\n\n   Platform-specific components of TSS API implementation.\n*/\n\nint\nPyThread_tss_create(Py_tss_t *key)\n{\n    assert(key != NULL);\n    /* If the key has been created, function is silently skipped. */\n    if (key->_is_initialized) {\n        return 0;\n    }\n\n    DWORD result = TlsAlloc();\n    if (result == TLS_OUT_OF_INDEXES) {\n        return -1;\n    }\n    /* In Windows, platform-specific key type is DWORD. */\n    key->_key = result;\n    key->_is_initialized = 1;\n    return 0;\n}\n\nvoid\nPyThread_tss_delete(Py_tss_t *key)\n{\n    assert(key != NULL);\n    /* If the key has not been created, function is silently skipped. */\n    if (!key->_is_initialized) {\n        return;\n    }\n\n    TlsFree(key->_key);\n    key->_key = TLS_OUT_OF_INDEXES;\n    key->_is_initialized = 0;\n}\n\nint\nPyThread_tss_set(Py_tss_t *key, void *value)\n{\n    assert(key != NULL);\n    BOOL ok = TlsSetValue(key->_key, value);\n    return ok ? 0 : -1;\n}\n\nvoid *\nPyThread_tss_get(Py_tss_t *key)\n{\n    assert(key != NULL);\n    /* because TSS is used in the Py_END_ALLOW_THREAD macro,\n     * it is necessary to preserve the windows error state, because\n     * it is assumed to be preserved across the call to the macro.\n     * Ideally, the macro should be fixed, but it is simpler to\n     * do it here.\n     */\n    DWORD error = GetLastError();\n    void *result = TlsGetValue(key->_key);\n    SetLastError(error);\n    return result;\n}\n"
  },
  {
    "path": "Thread_Pthread.h",
    "content": "#include \"pycore_interp.h\"    // _PyInterpreterState.threads.stacksize\n\n/* Posix threads interface */\n\n#include <stdlib.h>\n#include <string.h>\n#if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)\n#define destructor xxdestructor\n#endif\n#ifndef HAVE_PTHREAD_STUBS\n#  include <pthread.h>\n#endif\n#if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)\n#undef destructor\n#endif\n#include <signal.h>\n\n#if defined(__linux__)\n#   include <sys/syscall.h>     /* syscall(SYS_gettid) */\n#elif defined(__FreeBSD__)\n#   include <pthread_np.h>      /* pthread_getthreadid_np() */\n#elif defined(__OpenBSD__)\n#   include <unistd.h>          /* getthrid() */\n#elif defined(_AIX)\n#   include <sys/thread.h>      /* thread_self() */\n#elif defined(__NetBSD__)\n#   include <lwp.h>             /* _lwp_self() */\n#elif defined(__DragonFly__)\n#   include <sys/lwp.h>         /* lwp_gettid() */\n#endif\n\n/* The POSIX spec requires that use of pthread_attr_setstacksize\n   be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */\n#ifdef _POSIX_THREAD_ATTR_STACKSIZE\n#ifndef THREAD_STACK_SIZE\n#define THREAD_STACK_SIZE       0       /* use default stack size */\n#endif\n\n/* The default stack size for new threads on BSD is small enough that\n * we'll get hard crashes instead of 'maximum recursion depth exceeded'\n * exceptions.\n *\n * The default stack size below is the empirically determined minimal stack\n * sizes where a simple recursive function doesn't cause a hard crash.\n *\n * For macOS the value of THREAD_STACK_SIZE is determined in configure.ac\n * as it also depends on the other configure options like chosen sanitizer\n * runtimes.\n */\n#if defined(__FreeBSD__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0\n#undef  THREAD_STACK_SIZE\n#define THREAD_STACK_SIZE       0x400000\n#endif\n#if defined(_AIX) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0\n#undef  THREAD_STACK_SIZE\n#define THREAD_STACK_SIZE       0x200000\n#endif\n/* bpo-38852: test_threading.test_recursion_limit() checks that 1000 recursive\n   Python calls (default recursion limit) doesn't crash, but raise a regular\n   RecursionError exception. In debug mode, Python function calls allocates\n   more memory on the stack, so use a stack of 8 MiB. */\n#if defined(__ANDROID__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0\n#   ifdef Py_DEBUG\n#   undef  THREAD_STACK_SIZE\n#   define THREAD_STACK_SIZE    0x800000\n#   endif\n#endif\n#if defined(__VXWORKS__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0\n#undef  THREAD_STACK_SIZE\n#define THREAD_STACK_SIZE       0x100000\n#endif\n/* for safety, ensure a viable minimum stacksize */\n#define THREAD_STACK_MIN        0x8000  /* 32 KiB */\n#else  /* !_POSIX_THREAD_ATTR_STACKSIZE */\n#ifdef THREAD_STACK_SIZE\n#error \"THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined\"\n#endif\n#endif\n\n/* The POSIX spec says that implementations supporting the sem_*\n   family of functions must indicate this by defining\n   _POSIX_SEMAPHORES. */\n#ifdef _POSIX_SEMAPHORES\n/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so\n   we need to add 0 to make it work there as well. */\n#if (_POSIX_SEMAPHORES+0) == -1\n#define HAVE_BROKEN_POSIX_SEMAPHORES\n#else\n#include <semaphore.h>\n#include <errno.h>\n#endif\n#endif\n\n\n/* Whether or not to use semaphores directly rather than emulating them with\n * mutexes and condition variables:\n */\n#if (defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES) && \\\n     (defined(HAVE_SEM_TIMEDWAIT) || defined(HAVE_SEM_CLOCKWAIT)))\n#  define USE_SEMAPHORES\n#else\n#  undef USE_SEMAPHORES\n#endif\n\n\n/* On platforms that don't use standard POSIX threads pthread_sigmask()\n * isn't present.  DEC threads uses sigprocmask() instead as do most\n * other UNIX International compliant systems that don't have the full\n * pthread implementation.\n */\n#if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)\n#  define SET_THREAD_SIGMASK pthread_sigmask\n#else\n#  define SET_THREAD_SIGMASK sigprocmask\n#endif\n\n\n/*\n * pthread_cond support\n */\n\n#define condattr_monotonic _PyRuntime.threads._condattr_monotonic.ptr\n\nstatic void\ninit_condattr(void)\n{\n#ifdef CONDATTR_MONOTONIC\n# define ca _PyRuntime.threads._condattr_monotonic.val\n    // XXX We need to check the return code?\n    pthread_condattr_init(&ca);\n    // XXX We need to run pthread_condattr_destroy() during runtime fini.\n    if (pthread_condattr_setclock(&ca, CLOCK_MONOTONIC) == 0) {\n        condattr_monotonic = &ca;  // Use monotonic clock\n    }\n# undef ca\n#endif  // CONDATTR_MONOTONIC\n}\n\nint\n_PyThread_cond_init(PyCOND_T *cond)\n{\n    return pthread_cond_init(cond, condattr_monotonic);\n}\n\n\nvoid\n_PyThread_cond_after(long long us, struct timespec *abs)\n{\n    _PyTime_t timeout = _PyTime_FromMicrosecondsClamp(us);\n    _PyTime_t t;\n#ifdef CONDATTR_MONOTONIC\n    if (condattr_monotonic) {\n        t = _PyTime_GetMonotonicClock();\n    }\n    else\n#endif\n    {\n        t = _PyTime_GetSystemClock();\n    }\n    t = _PyTime_Add(t, timeout);\n    _PyTime_AsTimespec_clamp(t, abs);\n}\n\n\n/* A pthread mutex isn't sufficient to model the Python lock type\n * because, according to Draft 5 of the docs (P1003.4a/D5), both of the\n * following are undefined:\n *  -> a thread tries to lock a mutex it already has locked\n *  -> a thread tries to unlock a mutex locked by a different thread\n * pthread mutexes are designed for serializing threads over short pieces\n * of code anyway, so wouldn't be an appropriate implementation of\n * Python's locks regardless.\n *\n * The pthread_lock struct implements a Python lock as a \"locked?\" bit\n * and a <condition, mutex> pair.  In general, if the bit can be acquired\n * instantly, it is, else the pair is used to block the thread until the\n * bit is cleared.     9 May 1994 tim@ksr.com\n */\n\ntypedef struct {\n    char             locked; /* 0=unlocked, 1=locked */\n    /* a <cond, mutex> pair to handle an acquire of a locked lock */\n    pthread_cond_t   lock_released;\n    pthread_mutex_t  mut;\n} pthread_lock;\n\n#define CHECK_STATUS(name)  if (status != 0) { perror(name); error = 1; }\n#define CHECK_STATUS_PTHREAD(name)  if (status != 0) { fprintf(stderr, \\\n    \"%s: %s\\n\", name, strerror(status)); error = 1; }\n\n/*\n * Initialization for the current runtime.\n */\nstatic void\nPyThread__init_thread(void)\n{\n    // The library is only initialized once in the process,\n    // regardless of how many times the Python runtime is initialized.\n    static int lib_initialized = 0;\n    if (!lib_initialized) {\n        lib_initialized = 1;\n#if defined(_AIX) && defined(__GNUC__)\n        extern void pthread_init(void);\n        pthread_init();\n#endif\n    }\n    init_condattr();\n}\n\n/*\n * Thread support.\n */\n\n/* bpo-33015: pythread_callback struct and pythread_wrapper() cast\n   \"void func(void *)\" to \"void* func(void *)\": always return NULL.\n\n   PyThread_start_new_thread() uses \"void func(void *)\" type, whereas\n   pthread_create() requires a void* return value. */\ntypedef struct {\n    void (*func) (void *);\n    void *arg;\n} pythread_callback;\n\nstatic void *\npythread_wrapper(void *arg)\n{\n    /* copy func and func_arg and free the temporary structure */\n    pythread_callback *callback = arg;\n    void (*func)(void *) = callback->func;\n    void *func_arg = callback->arg;\n    PyMem_RawFree(arg);\n\n    func(func_arg);\n    return NULL;\n}\n\nunsigned long\nPyThread_start_new_thread(void (*func)(void *), void *arg)\n{\n    pthread_t th;\n    int status;\n#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)\n    pthread_attr_t attrs;\n#endif\n#if defined(THREAD_STACK_SIZE)\n    size_t      tss;\n#endif\n\n    if (!initialized)\n        PyThread_init_thread();\n\n#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)\n    if (pthread_attr_init(&attrs) != 0)\n        return PYTHREAD_INVALID_THREAD_ID;\n#endif\n#if defined(THREAD_STACK_SIZE)\n    PyThreadState *tstate = _PyThreadState_GET();\n    size_t stacksize = tstate ? tstate->interp->threads.stacksize : 0;\n    tss = (stacksize != 0) ? stacksize : THREAD_STACK_SIZE;\n    if (tss != 0) {\n        if (pthread_attr_setstacksize(&attrs, tss) != 0) {\n            pthread_attr_destroy(&attrs);\n            return PYTHREAD_INVALID_THREAD_ID;\n        }\n    }\n#endif\n#if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)\n    pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);\n#endif\n\n    pythread_callback *callback = PyMem_RawMalloc(sizeof(pythread_callback));\n\n    if (callback == NULL) {\n      return PYTHREAD_INVALID_THREAD_ID;\n    }\n\n    callback->func = func;\n    callback->arg = arg;\n\n    status = pthread_create(&th,\n#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)\n                             &attrs,\n#else\n                             (pthread_attr_t*)NULL,\n#endif\n                             pythread_wrapper, callback);\n\n#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)\n    pthread_attr_destroy(&attrs);\n#endif\n\n    if (status != 0) {\n        PyMem_RawFree(callback);\n        return PYTHREAD_INVALID_THREAD_ID;\n    }\n\n    pthread_detach(th);\n\n#if SIZEOF_PTHREAD_T <= SIZEOF_LONG\n    return (unsigned long) th;\n#else\n    return (unsigned long) *(unsigned long *) &th;\n#endif\n}\n\n/* XXX This implementation is considered (to quote Tim Peters) \"inherently\n   hosed\" because:\n     - It does not guarantee the promise that a non-zero integer is returned.\n     - The cast to unsigned long is inherently unsafe.\n     - It is not clear that the 'volatile' (for AIX?) are any longer necessary.\n*/\nunsigned long\nPyThread_get_thread_ident(void)\n{\n    volatile pthread_t threadid;\n    if (!initialized)\n        PyThread_init_thread();\n    threadid = pthread_self();\n    return (unsigned long) threadid;\n}\n\n#ifdef PY_HAVE_THREAD_NATIVE_ID\nunsigned long\nPyThread_get_thread_native_id(void)\n{\n    if (!initialized)\n        PyThread_init_thread();\n#ifdef __APPLE__\n    uint64_t native_id;\n    (void) pthread_threadid_np(NULL, &native_id);\n#elif defined(__linux__)\n    pid_t native_id;\n    native_id = syscall(SYS_gettid);\n#elif defined(__FreeBSD__)\n    int native_id;\n    native_id = pthread_getthreadid_np();\n#elif defined(__OpenBSD__)\n    pid_t native_id;\n    native_id = getthrid();\n#elif defined(_AIX)\n    tid_t native_id;\n    native_id = thread_self();\n#elif defined(__NetBSD__)\n    lwpid_t native_id;\n    native_id = _lwp_self();\n#elif defined(__DragonFly__)\n    lwpid_t native_id;\n    native_id = lwp_gettid();\n#endif\n    return (unsigned long) native_id;\n}\n#endif\n\nvoid _Py_NO_RETURN\nPyThread_exit_thread(void)\n{\n    if (!initialized)\n        exit(0);\n    pthread_exit(0);\n}\n\n#ifdef USE_SEMAPHORES\n\n/*\n * Lock support.\n */\n\nPyThread_type_lock\nPyThread_allocate_lock(void)\n{\n    sem_t *lock;\n    int status, error = 0;\n\n    if (!initialized)\n        PyThread_init_thread();\n\n    lock = (sem_t *)PyMem_RawMalloc(sizeof(sem_t));\n\n    if (lock) {\n        status = sem_init(lock,0,1);\n        CHECK_STATUS(\"sem_init\");\n\n        if (error) {\n            PyMem_RawFree((void *)lock);\n            lock = NULL;\n        }\n    }\n\n    return (PyThread_type_lock)lock;\n}\n\nvoid\nPyThread_free_lock(PyThread_type_lock lock)\n{\n    sem_t *thelock = (sem_t *)lock;\n    int status, error = 0;\n\n    (void) error; /* silence unused-but-set-variable warning */\n\n    if (!thelock)\n        return;\n\n    status = sem_destroy(thelock);\n    CHECK_STATUS(\"sem_destroy\");\n\n    PyMem_RawFree((void *)thelock);\n}\n\n/*\n * As of February 2002, Cygwin thread implementations mistakenly report error\n * codes in the return value of the sem_ calls (like the pthread_ functions).\n * Correct implementations return -1 and put the code in errno. This supports\n * either.\n */\nstatic int\nfix_status(int status)\n{\n    return (status == -1) ? errno : status;\n}\n\nPyLockStatus\nPyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,\n                            int intr_flag)\n{\n    PyLockStatus success;\n    sem_t *thelock = (sem_t *)lock;\n    int status, error = 0;\n\n    (void) error; /* silence unused-but-set-variable warning */\n\n    _PyTime_t timeout;  // relative timeout\n    if (microseconds >= 0) {\n        // bpo-41710: PyThread_acquire_lock_timed() cannot report timeout\n        // overflow to the caller, so clamp the timeout to\n        // [_PyTime_MIN, _PyTime_MAX].\n        //\n        // _PyTime_MAX nanoseconds is around 292.3 years.\n        //\n        // _thread.Lock.acquire() and _thread.RLock.acquire() raise an\n        // OverflowError if microseconds is greater than PY_TIMEOUT_MAX.\n        timeout = _PyTime_FromMicrosecondsClamp(microseconds);\n    }\n    else {\n        timeout = _PyTime_FromNanoseconds(-1);\n    }\n\n#ifdef HAVE_SEM_CLOCKWAIT\n    struct timespec abs_timeout;\n    // Local scope for deadline\n    {\n        _PyTime_t deadline = _PyTime_Add(_PyTime_GetMonotonicClock(), timeout);\n        _PyTime_AsTimespec_clamp(deadline, &abs_timeout);\n    }\n#else\n    _PyTime_t deadline = 0;\n    if (timeout > 0 && !intr_flag) {\n        deadline = _PyDeadline_Init(timeout);\n    }\n#endif\n\n    while (1) {\n        if (timeout > 0) {\n#ifdef HAVE_SEM_CLOCKWAIT\n            status = fix_status(sem_clockwait(thelock, CLOCK_MONOTONIC,\n                                              &abs_timeout));\n#else\n            _PyTime_t abs_time = _PyTime_Add(_PyTime_GetSystemClock(),\n                                             timeout);\n            struct timespec ts;\n            _PyTime_AsTimespec_clamp(abs_time, &ts);\n            status = fix_status(sem_timedwait(thelock, &ts));\n#endif\n        }\n        else if (timeout == 0) {\n            status = fix_status(sem_trywait(thelock));\n        }\n        else {\n            status = fix_status(sem_wait(thelock));\n        }\n\n        /* Retry if interrupted by a signal, unless the caller wants to be\n           notified.  */\n        if (intr_flag || status != EINTR) {\n            break;\n        }\n\n        // sem_clockwait() uses an absolute timeout, there is no need\n        // to recompute the relative timeout.\n#ifndef HAVE_SEM_CLOCKWAIT\n        if (timeout > 0) {\n            /* wait interrupted by a signal (EINTR): recompute the timeout */\n            timeout = _PyDeadline_Get(deadline);\n            if (timeout < 0) {\n                status = ETIMEDOUT;\n                break;\n            }\n        }\n#endif\n    }\n\n    /* Don't check the status if we're stopping because of an interrupt.  */\n    if (!(intr_flag && status == EINTR)) {\n        if (timeout > 0) {\n            if (status != ETIMEDOUT) {\n#ifdef HAVE_SEM_CLOCKWAIT\n                CHECK_STATUS(\"sem_clockwait\");\n#else\n                CHECK_STATUS(\"sem_timedwait\");\n#endif\n            }\n        }\n        else if (timeout == 0) {\n            if (status != EAGAIN) {\n                CHECK_STATUS(\"sem_trywait\");\n            }\n        }\n        else {\n            CHECK_STATUS(\"sem_wait\");\n        }\n    }\n\n    if (status == 0) {\n        success = PY_LOCK_ACQUIRED;\n    } else if (intr_flag && status == EINTR) {\n        success = PY_LOCK_INTR;\n    } else {\n        success = PY_LOCK_FAILURE;\n    }\n\n    return success;\n}\n\nvoid\nPyThread_release_lock(PyThread_type_lock lock)\n{\n    sem_t *thelock = (sem_t *)lock;\n    int status, error = 0;\n\n    (void) error; /* silence unused-but-set-variable warning */\n\n    status = sem_post(thelock);\n    CHECK_STATUS(\"sem_post\");\n}\n\n#else /* USE_SEMAPHORES */\n\n/*\n * Lock support.\n */\nPyThread_type_lock\nPyThread_allocate_lock(void)\n{\n    pthread_lock *lock;\n    int status, error = 0;\n\n    if (!initialized)\n        PyThread_init_thread();\n\n    lock = (pthread_lock *) PyMem_RawCalloc(1, sizeof(pthread_lock));\n    if (lock) {\n        lock->locked = 0;\n\n        status = pthread_mutex_init(&lock->mut, NULL);\n        CHECK_STATUS_PTHREAD(\"pthread_mutex_init\");\n        /* Mark the pthread mutex underlying a Python mutex as\n           pure happens-before.  We can't simply mark the\n           Python-level mutex as a mutex because it can be\n           acquired and released in different threads, which\n           will cause errors. */\n        _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&lock->mut);\n\n        status = _PyThread_cond_init(&lock->lock_released);\n        CHECK_STATUS_PTHREAD(\"pthread_cond_init\");\n\n        if (error) {\n            PyMem_RawFree((void *)lock);\n            lock = 0;\n        }\n    }\n\n    return (PyThread_type_lock) lock;\n}\n\nvoid\nPyThread_free_lock(PyThread_type_lock lock)\n{\n    pthread_lock *thelock = (pthread_lock *)lock;\n    int status, error = 0;\n\n    (void) error; /* silence unused-but-set-variable warning */\n\n    /* some pthread-like implementations tie the mutex to the cond\n     * and must have the cond destroyed first.\n     */\n    status = pthread_cond_destroy( &thelock->lock_released );\n    CHECK_STATUS_PTHREAD(\"pthread_cond_destroy\");\n\n    status = pthread_mutex_destroy( &thelock->mut );\n    CHECK_STATUS_PTHREAD(\"pthread_mutex_destroy\");\n\n    PyMem_RawFree((void *)thelock);\n}\n\nPyLockStatus\nPyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,\n                            int intr_flag)\n{\n    PyLockStatus success = PY_LOCK_FAILURE;\n    pthread_lock *thelock = (pthread_lock *)lock;\n    int status, error = 0;\n\n    if (microseconds == 0) {\n        status = pthread_mutex_trylock( &thelock->mut );\n        if (status != EBUSY) {\n            CHECK_STATUS_PTHREAD(\"pthread_mutex_trylock[1]\");\n        }\n    }\n    else {\n        status = pthread_mutex_lock( &thelock->mut );\n        CHECK_STATUS_PTHREAD(\"pthread_mutex_lock[1]\");\n    }\n    if (status != 0) {\n        goto done;\n    }\n\n    if (thelock->locked == 0) {\n        success = PY_LOCK_ACQUIRED;\n        goto unlock;\n    }\n    if (microseconds == 0) {\n        goto unlock;\n    }\n\n    struct timespec abs_timeout;\n    if (microseconds > 0) {\n        _PyThread_cond_after(microseconds, &abs_timeout);\n    }\n    // Continue trying until we get the lock\n\n    // mut must be locked by me -- part of the condition protocol\n    while (1) {\n        if (microseconds > 0) {\n            status = pthread_cond_timedwait(&thelock->lock_released,\n                                            &thelock->mut, &abs_timeout);\n            if (status == 1) {\n                break;\n            }\n            if (status == ETIMEDOUT) {\n                break;\n            }\n            CHECK_STATUS_PTHREAD(\"pthread_cond_timedwait\");\n        }\n        else {\n            status = pthread_cond_wait(\n                &thelock->lock_released,\n                &thelock->mut);\n            CHECK_STATUS_PTHREAD(\"pthread_cond_wait\");\n        }\n\n        if (intr_flag && status == 0 && thelock->locked) {\n            // We were woken up, but didn't get the lock.  We probably received\n            // a signal.  Return PY_LOCK_INTR to allow the caller to handle\n            // it and retry.\n            success = PY_LOCK_INTR;\n            break;\n        }\n\n        if (status == 0 && !thelock->locked) {\n            success = PY_LOCK_ACQUIRED;\n            break;\n        }\n\n        // Wait got interrupted by a signal: retry\n    }\n\nunlock:\n    if (success == PY_LOCK_ACQUIRED) {\n        thelock->locked = 1;\n    }\n    status = pthread_mutex_unlock( &thelock->mut );\n    CHECK_STATUS_PTHREAD(\"pthread_mutex_unlock[1]\");\n\ndone:\n    if (error) {\n        success = PY_LOCK_FAILURE;\n    }\n    return success;\n}\n\nvoid\nPyThread_release_lock(PyThread_type_lock lock)\n{\n    pthread_lock *thelock = (pthread_lock *)lock;\n    int status, error = 0;\n\n    (void) error; /* silence unused-but-set-variable warning */\n\n    status = pthread_mutex_lock( &thelock->mut );\n    CHECK_STATUS_PTHREAD(\"pthread_mutex_lock[3]\");\n\n    thelock->locked = 0;\n\n    /* wake up someone (anyone, if any) waiting on the lock */\n    status = pthread_cond_signal( &thelock->lock_released );\n    CHECK_STATUS_PTHREAD(\"pthread_cond_signal\");\n\n    status = pthread_mutex_unlock( &thelock->mut );\n    CHECK_STATUS_PTHREAD(\"pthread_mutex_unlock[3]\");\n}\n\n#endif /* USE_SEMAPHORES */\n\nint\n_PyThread_at_fork_reinit(PyThread_type_lock *lock)\n{\n    PyThread_type_lock new_lock = PyThread_allocate_lock();\n    if (new_lock == NULL) {\n        return -1;\n    }\n\n    /* bpo-6721, bpo-40089: The old lock can be in an inconsistent state.\n       fork() can be called in the middle of an operation on the lock done by\n       another thread. So don't call PyThread_free_lock(*lock).\n\n       Leak memory on purpose. Don't release the memory either since the\n       address of a mutex is relevant. Putting two mutexes at the same address\n       can lead to problems. */\n\n    *lock = new_lock;\n    return 0;\n}\n\nint\nPyThread_acquire_lock(PyThread_type_lock lock, int waitflag)\n{\n    return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0, /*intr_flag=*/0);\n}\n\n/* set the thread stack size.\n * Return 0 if size is valid, -1 if size is invalid,\n * -2 if setting stack size is not supported.\n */\nstatic int\n_pythread_pthread_set_stacksize(size_t size)\n{\n#if defined(THREAD_STACK_SIZE)\n    pthread_attr_t attrs;\n    size_t tss_min;\n    int rc = 0;\n#endif\n\n    /* set to default */\n    if (size == 0) {\n        _PyInterpreterState_GET()->threads.stacksize = 0;\n        return 0;\n    }\n\n#if defined(THREAD_STACK_SIZE)\n#if defined(PTHREAD_STACK_MIN)\n    tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN\n                                                   : THREAD_STACK_MIN;\n#else\n    tss_min = THREAD_STACK_MIN;\n#endif\n    if (size >= tss_min) {\n        /* validate stack size by setting thread attribute */\n        if (pthread_attr_init(&attrs) == 0) {\n            rc = pthread_attr_setstacksize(&attrs, size);\n            pthread_attr_destroy(&attrs);\n            if (rc == 0) {\n                _PyInterpreterState_GET()->threads.stacksize = size;\n                return 0;\n            }\n        }\n    }\n    return -1;\n#else\n    return -2;\n#endif\n}\n\n#define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x)\n\n\n/* Thread Local Storage (TLS) API\n\n   This API is DEPRECATED since Python 3.7.  See PEP 539 for details.\n*/\n\n/* Issue #25658: On platforms where native TLS key is defined in a way that\n   cannot be safely cast to int, PyThread_create_key returns immediately a\n   failure status and other TLS functions all are no-ops.  This indicates\n   clearly that the old API is not supported on platforms where it cannot be\n   used reliably, and that no effort will be made to add such support.\n\n   Note: PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT will be unnecessary after\n   removing this API.\n*/\n\nint\nPyThread_create_key(void)\n{\n#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT\n    pthread_key_t key;\n    int fail = pthread_key_create(&key, NULL);\n    if (fail)\n        return -1;\n    if (key > INT_MAX) {\n        /* Issue #22206: handle integer overflow */\n        pthread_key_delete(key);\n        errno = ENOMEM;\n        return -1;\n    }\n    return (int)key;\n#else\n    return -1;  /* never return valid key value. */\n#endif\n}\n\nvoid\nPyThread_delete_key(int key)\n{\n#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT\n    pthread_key_delete(key);\n#endif\n}\n\nvoid\nPyThread_delete_key_value(int key)\n{\n#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT\n    pthread_setspecific(key, NULL);\n#endif\n}\n\nint\nPyThread_set_key_value(int key, void *value)\n{\n#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT\n    int fail = pthread_setspecific(key, value);\n    return fail ? -1 : 0;\n#else\n    return -1;\n#endif\n}\n\nvoid *\nPyThread_get_key_value(int key)\n{\n#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT\n    return pthread_getspecific(key);\n#else\n    return NULL;\n#endif\n}\n\n\nvoid\nPyThread_ReInitTLS(void)\n{\n}\n\n\n/* Thread Specific Storage (TSS) API\n\n   Platform-specific components of TSS API implementation.\n*/\n\nint\nPyThread_tss_create(Py_tss_t *key)\n{\n    assert(key != NULL);\n    /* If the key has been created, function is silently skipped. */\n    if (key->_is_initialized) {\n        return 0;\n    }\n\n    int fail = pthread_key_create(&(key->_key), NULL);\n    if (fail) {\n        return -1;\n    }\n    key->_is_initialized = 1;\n    return 0;\n}\n\nvoid\nPyThread_tss_delete(Py_tss_t *key)\n{\n    assert(key != NULL);\n    /* If the key has not been created, function is silently skipped. */\n    if (!key->_is_initialized) {\n        return;\n    }\n\n    pthread_key_delete(key->_key);\n    /* pthread has not provided the defined invalid value for the key. */\n    key->_is_initialized = 0;\n}\n\nint\nPyThread_tss_set(Py_tss_t *key, void *value)\n{\n    assert(key != NULL);\n    int fail = pthread_setspecific(key->_key, value);\n    return fail ? -1 : 0;\n}\n\nvoid *\nPyThread_tss_get(Py_tss_t *key)\n{\n    assert(key != NULL);\n    return pthread_getspecific(key->_key);\n}\n"
  },
  {
    "path": "Thread_Pthread_Dtubs.h",
    "content": "#include \"cpython/pthread_stubs.h\"\n\n// mutex\nint\npthread_mutex_init(pthread_mutex_t *restrict mutex,\n                   const pthread_mutexattr_t *restrict attr)\n{\n    return 0;\n}\n\nint\npthread_mutex_destroy(pthread_mutex_t *mutex)\n{\n    return 0;\n}\n\nint\npthread_mutex_trylock(pthread_mutex_t *mutex)\n{\n    return 0;\n}\n\nint\npthread_mutex_lock(pthread_mutex_t *mutex)\n{\n    return 0;\n}\n\nint\npthread_mutex_unlock(pthread_mutex_t *mutex)\n{\n    return 0;\n}\n\n// condition\nint\npthread_cond_init(pthread_cond_t *restrict cond,\n                  const pthread_condattr_t *restrict attr)\n{\n    return 0;\n}\n\nPyAPI_FUNC(int)pthread_cond_destroy(pthread_cond_t *cond)\n{\n    return 0;\n}\n\nint\npthread_cond_wait(pthread_cond_t *restrict cond,\n                  pthread_mutex_t *restrict mutex)\n{\n    return 0;\n}\n\nint\npthread_cond_timedwait(pthread_cond_t *restrict cond,\n                       pthread_mutex_t *restrict mutex,\n                       const struct timespec *restrict abstime)\n{\n    return 0;\n}\n\nint\npthread_cond_signal(pthread_cond_t *cond)\n{\n    return 0;\n}\n\nint\npthread_condattr_init(pthread_condattr_t *attr)\n{\n    return 0;\n}\n\nint\npthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id)\n{\n    return 0;\n}\n\n// pthread\nint\npthread_create(pthread_t *restrict thread,\n               const pthread_attr_t *restrict attr,\n               void *(*start_routine)(void *),\n               void *restrict arg)\n{\n    return EAGAIN;\n}\n\nint\npthread_detach(pthread_t thread)\n{\n    return 0;\n}\n\nPyAPI_FUNC(pthread_t) pthread_self(void)\n{\n    return 0;\n}\n\nint\npthread_exit(void *retval)\n{\n    exit(0);\n}\n\nint\npthread_attr_init(pthread_attr_t *attr)\n{\n    return 0;\n}\n\nint\npthread_attr_setstacksize(\n    pthread_attr_t *attr, size_t stacksize)\n{\n    return 0;\n}\n\nint\npthread_attr_destroy(pthread_attr_t *attr)\n{\n    return 0;\n}\n\n\ntypedef struct py_stub_tls_entry py_tls_entry;\n\n#define py_tls_entries (_PyRuntime.threads.stubs.tls_entries)\n\nint\npthread_key_create(pthread_key_t *key, void (*destr_function)(void *))\n{\n    if (!key) {\n        return EINVAL;\n    }\n    if (destr_function != NULL) {\n        Py_FatalError(\"pthread_key_create destructor is not supported\");\n    }\n    for (pthread_key_t idx = 0; idx < PTHREAD_KEYS_MAX; idx++) {\n        if (!py_tls_entries[idx].in_use) {\n            py_tls_entries[idx].in_use = true;\n            *key = idx;\n            return 0;\n        }\n    }\n    return EAGAIN;\n}\n\nint\npthread_key_delete(pthread_key_t key)\n{\n    if (key < 0 || key >= PTHREAD_KEYS_MAX || !py_tls_entries[key].in_use) {\n        return EINVAL;\n    }\n    py_tls_entries[key].in_use = false;\n    py_tls_entries[key].value = NULL;\n    return 0;\n}\n\n\nvoid *\npthread_getspecific(pthread_key_t key) {\n    if (key < 0 || key >= PTHREAD_KEYS_MAX || !py_tls_entries[key].in_use) {\n        return NULL;\n    }\n    return py_tls_entries[key].value;\n}\n\nint\npthread_setspecific(pthread_key_t key, const void *value)\n{\n    if (key < 0 || key >= PTHREAD_KEYS_MAX || !py_tls_entries[key].in_use) {\n        return EINVAL;\n    }\n    py_tls_entries[key].value = (void *)value;\n    return 0;\n}\n\n// let thread_pthread define the Python API\n#include \"thread_pthread.h\"\n"
  },
  {
    "path": "TraceBack.c",
    "content": "\n/* Traceback implementation */\n\n#include \"Python.h\"\n\n#include \"pycore_ast.h\"           // asdl_seq_*\n#include \"pycore_call.h\"          // _PyObject_CallMethodFormat()\n#include \"pycore_compile.h\"       // _PyAST_Optimize\n#include \"pycore_fileutils.h\"     // _Py_BEGIN_SUPPRESS_IPH\n#include \"pycore_frame.h\"         // _PyFrame_GetCode()\n#include \"pycore_interp.h\"        // PyInterpreterState.gc\n#include \"pycore_parser.h\"        // _PyParser_ASTFromString\n#include \"pycore_pyarena.h\"       // _PyArena_Free()\n#include \"pycore_pyerrors.h\"      // _PyErr_GetRaisedException()\n#include \"pycore_pystate.h\"       // _PyThreadState_GET()\n#include \"pycore_traceback.h\"     // EXCEPTION_TB_HEADER\n\n#include \"../Parser/pegen.h\"      // _PyPegen_byte_offset_to_character_offset()\n#include \"frameobject.h\"          // PyFrame_New()\n#include \"structmember.h\"         // PyMemberDef\n#include \"osdefs.h\"               // SEP\n#ifdef HAVE_FCNTL_H\n#  include <fcntl.h>\n#endif\n\n#define OFF(x) offsetof(PyTracebackObject, x)\n\n#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))\n#define MAX_STRING_LENGTH 500\n#define MAX_FRAME_DEPTH 100\n#define MAX_NTHREADS 100\n\n/* Function from Parser/tokenizer.c */\nextern char* _PyTokenizer_FindEncodingFilename(int, PyObject *);\n\n/*[clinic input]\nclass TracebackType \"PyTracebackObject *\" \"&PyTraceback_Type\"\n[clinic start generated code]*/\n/*[clinic end generated code: output=da39a3ee5e6b4b0d input=928fa06c10151120]*/\n\n#include \"clinic/traceback.c.h\"\n\nstatic PyObject *\ntb_create_raw(PyTracebackObject *next, PyFrameObject *frame, int lasti,\n              int lineno)\n{\n    PyTracebackObject *tb;\n    if ((next != NULL && !PyTraceBack_Check(next)) ||\n                    frame == NULL || !PyFrame_Check(frame)) {\n        PyErr_BadInternalCall();\n        return NULL;\n    }\n    tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);\n    if (tb != NULL) {\n        tb->tb_next = (PyTracebackObject*)Py_XNewRef(next);\n        tb->tb_frame = (PyFrameObject*)Py_XNewRef(frame);\n        tb->tb_lasti = lasti;\n        tb->tb_lineno = lineno;\n        PyObject_GC_Track(tb);\n    }\n    return (PyObject *)tb;\n}\n\n/*[clinic input]\n@classmethod\nTracebackType.__new__ as tb_new\n\n  tb_next: object\n  tb_frame: object(type='PyFrameObject *', subclass_of='&PyFrame_Type')\n  tb_lasti: int\n  tb_lineno: int\n\nCreate a new traceback object.\n[clinic start generated code]*/\n\nstatic PyObject *\ntb_new_impl(PyTypeObject *type, PyObject *tb_next, PyFrameObject *tb_frame,\n            int tb_lasti, int tb_lineno)\n/*[clinic end generated code: output=fa077debd72d861a input=01cbe8ec8783fca7]*/\n{\n    if (tb_next == Py_None) {\n        tb_next = NULL;\n    } else if (!PyTraceBack_Check(tb_next)) {\n        return PyErr_Format(PyExc_TypeError,\n                            \"expected traceback object or None, got '%s'\",\n                            Py_TYPE(tb_next)->tp_name);\n    }\n\n    return tb_create_raw((PyTracebackObject *)tb_next, tb_frame, tb_lasti,\n                         tb_lineno);\n}\n\nstatic PyObject *\ntb_dir(PyTracebackObject *self, PyObject *Py_UNUSED(ignored))\n{\n    return Py_BuildValue(\"[ssss]\", \"tb_frame\", \"tb_next\",\n                                   \"tb_lasti\", \"tb_lineno\");\n}\n\nstatic PyObject *\ntb_next_get(PyTracebackObject *self, void *Py_UNUSED(_))\n{\n    PyObject* ret = (PyObject*)self->tb_next;\n    if (!ret) {\n        ret = Py_None;\n    }\n    return Py_NewRef(ret);\n}\n\nstatic int\ntb_next_set(PyTracebackObject *self, PyObject *new_next, void *Py_UNUSED(_))\n{\n    if (!new_next) {\n        PyErr_Format(PyExc_TypeError, \"can't delete tb_next attribute\");\n        return -1;\n    }\n\n    /* We accept None or a traceback object, and map None -> NULL (inverse of\n       tb_next_get) */\n    if (new_next == Py_None) {\n        new_next = NULL;\n    } else if (!PyTraceBack_Check(new_next)) {\n        PyErr_Format(PyExc_TypeError,\n                     \"expected traceback object, got '%s'\",\n                     Py_TYPE(new_next)->tp_name);\n        return -1;\n    }\n\n    /* Check for loops */\n    PyTracebackObject *cursor = (PyTracebackObject *)new_next;\n    while (cursor) {\n        if (cursor == self) {\n            PyErr_Format(PyExc_ValueError, \"traceback loop detected\");\n            return -1;\n        }\n        cursor = cursor->tb_next;\n    }\n\n    Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(new_next));\n\n    return 0;\n}\n\n\nstatic PyMethodDef tb_methods[] = {\n   {\"__dir__\", _PyCFunction_CAST(tb_dir), METH_NOARGS},\n   {NULL, NULL, 0, NULL},\n};\n\nstatic PyMemberDef tb_memberlist[] = {\n    {\"tb_frame\",        T_OBJECT,       OFF(tb_frame),  READONLY|PY_AUDIT_READ},\n    {\"tb_lasti\",        T_INT,          OFF(tb_lasti),  READONLY},\n    {\"tb_lineno\",       T_INT,          OFF(tb_lineno), READONLY},\n    {NULL}      /* Sentinel */\n};\n\nstatic PyGetSetDef tb_getsetters[] = {\n    {\"tb_next\", (getter)tb_next_get, (setter)tb_next_set, NULL, NULL},\n    {NULL}      /* Sentinel */\n};\n\nstatic void\ntb_dealloc(PyTracebackObject *tb)\n{\n    PyObject_GC_UnTrack(tb);\n    Py_TRASHCAN_BEGIN(tb, tb_dealloc)\n    Py_XDECREF(tb->tb_next);\n    Py_XDECREF(tb->tb_frame);\n    PyObject_GC_Del(tb);\n    Py_TRASHCAN_END\n}\n\nstatic int\ntb_traverse(PyTracebackObject *tb, visitproc visit, void *arg)\n{\n    Py_VISIT(tb->tb_next);\n    Py_VISIT(tb->tb_frame);\n    return 0;\n}\n\nstatic int\ntb_clear(PyTracebackObject *tb)\n{\n    Py_CLEAR(tb->tb_next);\n    Py_CLEAR(tb->tb_frame);\n    return 0;\n}\n\nPyTypeObject PyTraceBack_Type = {\n    PyVarObject_HEAD_INIT(&PyType_Type, 0)\n    \"traceback\",\n    sizeof(PyTracebackObject),\n    0,\n    (destructor)tb_dealloc, /*tp_dealloc*/\n    0,                  /*tp_vectorcall_offset*/\n    0,    /*tp_getattr*/\n    0,                  /*tp_setattr*/\n    0,                  /*tp_as_async*/\n    0,                  /*tp_repr*/\n    0,                  /*tp_as_number*/\n    0,                  /*tp_as_sequence*/\n    0,                  /*tp_as_mapping*/\n    0,                  /* tp_hash */\n    0,                  /* tp_call */\n    0,                  /* tp_str */\n    PyObject_GenericGetAttr,                    /* tp_getattro */\n    0,                  /* tp_setattro */\n    0,                                          /* tp_as_buffer */\n    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */\n    tb_new__doc__,                              /* tp_doc */\n    (traverseproc)tb_traverse,                  /* tp_traverse */\n    (inquiry)tb_clear,                          /* tp_clear */\n    0,                                          /* tp_richcompare */\n    0,                                          /* tp_weaklistoffset */\n    0,                                          /* tp_iter */\n    0,                                          /* tp_iternext */\n    tb_methods,         /* tp_methods */\n    tb_memberlist,      /* tp_members */\n    tb_getsetters,                              /* tp_getset */\n    0,                                          /* tp_base */\n    0,                                          /* tp_dict */\n    0,                                          /* tp_descr_get */\n    0,                                          /* tp_descr_set */\n    0,                                          /* tp_dictoffset */\n    0,                                          /* tp_init */\n    0,                                          /* tp_alloc */\n    tb_new,                                     /* tp_new */\n};\n\n\nPyObject*\n_PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)\n{\n    assert(tb_next == NULL || PyTraceBack_Check(tb_next));\n    assert(frame != NULL);\n    int addr = _PyInterpreterFrame_LASTI(frame->f_frame) * sizeof(_Py_CODEUNIT);\n    return tb_create_raw((PyTracebackObject *)tb_next, frame, addr,\n                         PyFrame_GetLineNumber(frame));\n}\n\n\nint\nPyTraceBack_Here(PyFrameObject *frame)\n{\n    PyObject *exc = PyErr_GetRaisedException();\n    assert(PyExceptionInstance_Check(exc));\n    PyObject *tb = PyException_GetTraceback(exc);\n    PyObject *newtb = _PyTraceBack_FromFrame(tb, frame);\n    Py_XDECREF(tb);\n    if (newtb == NULL) {\n        _PyErr_ChainExceptions1(exc);\n        return -1;\n    }\n    PyException_SetTraceback(exc, newtb);\n    Py_XDECREF(newtb);\n    PyErr_SetRaisedException(exc);\n    return 0;\n}\n\n/* Insert a frame into the traceback for (funcname, filename, lineno). */\nvoid _PyTraceback_Add(const char *funcname, const char *filename, int lineno)\n{\n    PyObject *globals;\n    PyCodeObject *code;\n    PyFrameObject *frame;\n    PyThreadState *tstate = _PyThreadState_GET();\n\n    /* Save and clear the current exception. Python functions must not be\n       called with an exception set. Calling Python functions happens when\n       the codec of the filesystem encoding is implemented in pure Python. */\n    PyObject *exc = _PyErr_GetRaisedException(tstate);\n\n    globals = PyDict_New();\n    if (!globals)\n        goto error;\n    code = PyCode_NewEmpty(filename, funcname, lineno);\n    if (!code) {\n        Py_DECREF(globals);\n        goto error;\n    }\n    frame = PyFrame_New(tstate, code, globals, NULL);\n    Py_DECREF(globals);\n    Py_DECREF(code);\n    if (!frame)\n        goto error;\n    frame->f_lineno = lineno;\n\n    _PyErr_SetRaisedException(tstate, exc);\n    PyTraceBack_Here(frame);\n    Py_DECREF(frame);\n    return;\n\nerror:\n    _PyErr_ChainExceptions1(exc);\n}\n\nstatic PyObject *\n_Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io)\n{\n    Py_ssize_t i;\n    PyObject *binary;\n    PyObject *v;\n    Py_ssize_t npath;\n    size_t taillen;\n    PyObject *syspath;\n    PyObject *path;\n    const char* tail;\n    PyObject *filebytes;\n    const char* filepath;\n    Py_ssize_t len;\n    PyObject* result;\n    PyObject *open = NULL;\n\n    filebytes = PyUnicode_EncodeFSDefault(filename);\n    if (filebytes == NULL) {\n        PyErr_Clear();\n        return NULL;\n    }\n    filepath = PyBytes_AS_STRING(filebytes);\n\n    /* Search tail of filename in sys.path before giving up */\n    tail = strrchr(filepath, SEP);\n    if (tail == NULL)\n        tail = filepath;\n    else\n        tail++;\n    taillen = strlen(tail);\n\n    PyThreadState *tstate = _PyThreadState_GET();\n    syspath = _PySys_GetAttr(tstate, &_Py_ID(path));\n    if (syspath == NULL || !PyList_Check(syspath))\n        goto error;\n    npath = PyList_Size(syspath);\n\n    open = PyObject_GetAttr(io, &_Py_ID(open));\n    for (i = 0; i < npath; i++) {\n        v = PyList_GetItem(syspath, i);\n        if (v == NULL) {\n            PyErr_Clear();\n            break;\n        }\n        if (!PyUnicode_Check(v))\n            continue;\n        path = PyUnicode_EncodeFSDefault(v);\n        if (path == NULL) {\n            PyErr_Clear();\n            continue;\n        }\n        len = PyBytes_GET_SIZE(path);\n        if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) {\n            Py_DECREF(path);\n            continue; /* Too long */\n        }\n        strcpy(namebuf, PyBytes_AS_STRING(path));\n        Py_DECREF(path);\n        if (strlen(namebuf) != (size_t)len)\n            continue; /* v contains '\\0' */\n        if (len > 0 && namebuf[len-1] != SEP)\n            namebuf[len++] = SEP;\n        strcpy(namebuf+len, tail);\n\n        binary = _PyObject_CallMethodFormat(tstate, open, \"ss\", namebuf, \"rb\");\n        if (binary != NULL) {\n            result = binary;\n            goto finally;\n        }\n        PyErr_Clear();\n    }\n    goto error;\n\nerror:\n    result = NULL;\nfinally:\n    Py_XDECREF(open);\n    Py_DECREF(filebytes);\n    return result;\n}\n\n/* Writes indent spaces. Returns 0 on success and non-zero on failure.\n */\nint\n_Py_WriteIndent(int indent, PyObject *f)\n{\n    char buf[11] = \"          \";\n    assert(strlen(buf) == 10);\n    while (indent > 0) {\n        if (indent < 10) {\n            buf[indent] = '\\0';\n        }\n        if (PyFile_WriteString(buf, f) < 0) {\n            return -1;\n        }\n        indent -= 10;\n    }\n    return 0;\n}\n\n/* Writes indent spaces, followed by the margin if it is not `\\0`.\n   Returns 0 on success and non-zero on failure.\n */\nint\n_Py_WriteIndentedMargin(int indent, const char *margin, PyObject *f)\n{\n    if (_Py_WriteIndent(indent, f) < 0) {\n        return -1;\n    }\n    if (margin) {\n        if (PyFile_WriteString(margin, f) < 0) {\n            return -1;\n        }\n    }\n    return 0;\n}\n\nstatic int\ndisplay_source_line_with_margin(PyObject *f, PyObject *filename, int lineno, int indent,\n                                int margin_indent, const char *margin,\n                                int *truncation, PyObject **line)\n{\n    int fd;\n    int i;\n    char *found_encoding;\n    const char *encoding;\n    PyObject *io;\n    PyObject *binary;\n    PyObject *fob = NULL;\n    PyObject *lineobj = NULL;\n    PyObject *res;\n    char buf[MAXPATHLEN+1];\n    int kind;\n    const void *data;\n\n    /* open the file */\n    if (filename == NULL)\n        return 0;\n\n    /* Do not attempt to open things like <string> or <stdin> */\n    assert(PyUnicode_Check(filename));\n    if (PyUnicode_READ_CHAR(filename, 0) == '<') {\n        Py_ssize_t len = PyUnicode_GET_LENGTH(filename);\n        if (len > 0 && PyUnicode_READ_CHAR(filename, len - 1) == '>') {\n            return 0;\n        }\n    }\n\n    io = PyImport_ImportModule(\"io\");\n    if (io == NULL) {\n        return -1;\n    }\n\n    binary = _PyObject_CallMethod(io, &_Py_ID(open), \"Os\", filename, \"rb\");\n    if (binary == NULL) {\n        PyErr_Clear();\n\n        binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io);\n        if (binary == NULL) {\n            Py_DECREF(io);\n            return -1;\n        }\n    }\n\n    /* use the right encoding to decode the file as unicode */\n    fd = PyObject_AsFileDescriptor(binary);\n    if (fd < 0) {\n        Py_DECREF(io);\n        Py_DECREF(binary);\n        return 0;\n    }\n    found_encoding = _PyTokenizer_FindEncodingFilename(fd, filename);\n    if (found_encoding == NULL)\n        PyErr_Clear();\n    encoding = (found_encoding != NULL) ? found_encoding : \"utf-8\";\n    /* Reset position */\n    if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {\n        Py_DECREF(io);\n        Py_DECREF(binary);\n        PyMem_Free(found_encoding);\n        return 0;\n    }\n    fob = _PyObject_CallMethod(io, &_Py_ID(TextIOWrapper),\n                               \"Os\", binary, encoding);\n    Py_DECREF(io);\n    PyMem_Free(found_encoding);\n\n    if (fob == NULL) {\n        PyErr_Clear();\n\n        res = PyObject_CallMethodNoArgs(binary, &_Py_ID(close));\n        Py_DECREF(binary);\n        if (res)\n            Py_DECREF(res);\n        else\n            PyErr_Clear();\n        return 0;\n    }\n    Py_DECREF(binary);\n\n    /* get the line number lineno */\n    for (i = 0; i < lineno; i++) {\n        Py_XDECREF(lineobj);\n        lineobj = PyFile_GetLine(fob, -1);\n        if (!lineobj) {\n            PyErr_Clear();\n            break;\n        }\n    }\n    res = PyObject_CallMethodNoArgs(fob, &_Py_ID(close));\n    if (res) {\n        Py_DECREF(res);\n    }\n    else {\n        PyErr_Clear();\n    }\n    Py_DECREF(fob);\n    if (!lineobj || !PyUnicode_Check(lineobj)) {\n        Py_XDECREF(lineobj);\n        return -1;\n    }\n\n    if (line) {\n        *line = Py_NewRef(lineobj);\n    }\n\n    /* remove the indentation of the line */\n    kind = PyUnicode_KIND(lineobj);\n    data = PyUnicode_DATA(lineobj);\n    for (i=0; i < PyUnicode_GET_LENGTH(lineobj); i++) {\n        Py_UCS4 ch = PyUnicode_READ(kind, data, i);\n        if (ch != ' ' && ch != '\\t' && ch != '\\014')\n            break;\n    }\n    if (i) {\n        PyObject *truncated;\n        truncated = PyUnicode_Substring(lineobj, i, PyUnicode_GET_LENGTH(lineobj));\n        if (truncated) {\n            Py_SETREF(lineobj, truncated);\n        } else {\n            PyErr_Clear();\n        }\n    }\n\n    if (truncation != NULL) {\n        *truncation = i - indent;\n    }\n\n    if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) {\n        goto error;\n    }\n\n    /* Write some spaces before the line */\n    if (_Py_WriteIndent(indent, f) < 0) {\n        goto error;\n    }\n\n    /* finally display the line */\n    if (PyFile_WriteObject(lineobj, f, Py_PRINT_RAW) < 0) {\n        goto error;\n    }\n\n    if (PyFile_WriteString(\"\\n\", f) < 0) {\n        goto error;\n    }\n\n    Py_DECREF(lineobj);\n    return 0;\nerror:\n    Py_DECREF(lineobj);\n    return -1;\n}\n\nint\n_Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent,\n                      int *truncation, PyObject **line)\n{\n    return display_source_line_with_margin(f, filename, lineno, indent, 0,\n                                           NULL, truncation, line);\n}\n\n/* AST based Traceback Specialization\n *\n * When displaying a new traceback line, for certain syntactical constructs\n * (e.g a subscript, an arithmetic operation) we try to create a representation\n * that separates the primary source of error from the rest.\n *\n * Example specialization of BinOp nodes:\n *  Traceback (most recent call last):\n *    File \"/home/isidentical/cpython/cpython/t.py\", line 10, in <module>\n *      add_values(1, 2, 'x', 3, 4)\n *    File \"/home/isidentical/cpython/cpython/t.py\", line 2, in add_values\n *      return a + b + c + d + e\n *             ~~~~~~^~~\n *  TypeError: 'NoneType' object is not subscriptable\n */\n\n#define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\\t') || ((c) == '\\f'))\n\nstatic int\nextract_anchors_from_expr(const char *segment_str, expr_ty expr, Py_ssize_t *left_anchor, Py_ssize_t *right_anchor,\n                          char** primary_error_char, char** secondary_error_char)\n{\n    switch (expr->kind) {\n        case BinOp_kind: {\n            expr_ty left = expr->v.BinOp.left;\n            expr_ty right = expr->v.BinOp.right;\n            for (int i = left->end_col_offset; i < right->col_offset; i++) {\n                if (IS_WHITESPACE(segment_str[i])) {\n                    continue;\n                }\n\n                *left_anchor = i;\n                *right_anchor = i + 1;\n\n                // Check whether if this a two-character operator (e.g //)\n                if (i + 1 < right->col_offset && !IS_WHITESPACE(segment_str[i + 1])) {\n                    ++*right_anchor;\n                }\n\n                // Set the error characters\n                *primary_error_char = \"~\";\n                *secondary_error_char = \"^\";\n                break;\n            }\n            return 1;\n        }\n        case Subscript_kind: {\n            *left_anchor = expr->v.Subscript.value->end_col_offset;\n            *right_anchor = expr->v.Subscript.slice->end_col_offset + 1;\n\n            // Set the error characters\n            *primary_error_char = \"~\";\n            *secondary_error_char = \"^\";\n            return 1;\n        }\n        default:\n            return 0;\n    }\n}\n\nstatic int\nextract_anchors_from_stmt(const char *segment_str, stmt_ty statement, Py_ssize_t *left_anchor, Py_ssize_t *right_anchor,\n                          char** primary_error_char, char** secondary_error_char)\n{\n    switch (statement->kind) {\n        case Expr_kind: {\n            return extract_anchors_from_expr(segment_str, statement->v.Expr.value, left_anchor, right_anchor,\n                                             primary_error_char, secondary_error_char);\n        }\n        default:\n            return 0;\n    }\n}\n\nstatic int\nextract_anchors_from_line(PyObject *filename, PyObject *line,\n                          Py_ssize_t start_offset, Py_ssize_t end_offset,\n                          Py_ssize_t *left_anchor, Py_ssize_t *right_anchor,\n                          char** primary_error_char, char** secondary_error_char)\n{\n    int res = -1;\n    PyArena *arena = NULL;\n    PyObject *segment = PyUnicode_Substring(line, start_offset, end_offset);\n    if (!segment) {\n        goto done;\n    }\n\n    const char *segment_str = PyUnicode_AsUTF8(segment);\n    if (!segment_str) {\n        goto done;\n    }\n\n    arena = _PyArena_New();\n    if (!arena) {\n        goto done;\n    }\n\n    PyCompilerFlags flags = _PyCompilerFlags_INIT;\n\n    _PyASTOptimizeState state;\n    state.optimize = _Py_GetConfig()->optimization_level;\n    state.ff_features = 0;\n\n    mod_ty module = _PyParser_ASTFromString(segment_str, filename, Py_file_input,\n                                            &flags, arena);\n    if (!module) {\n        goto done;\n    }\n    if (!_PyAST_Optimize(module, arena, &state)) {\n        goto done;\n    }\n\n    assert(module->kind == Module_kind);\n    if (asdl_seq_LEN(module->v.Module.body) == 1) {\n        stmt_ty statement = asdl_seq_GET(module->v.Module.body, 0);\n        res = extract_anchors_from_stmt(segment_str, statement, left_anchor, right_anchor,\n                                        primary_error_char, secondary_error_char);\n    } else {\n        res = 0;\n    }\n\ndone:\n    if (res > 0) {\n        // Normalize the AST offsets to byte offsets and adjust them with the\n        // start of the actual line (instead of the source code segment).\n        assert(segment != NULL);\n        assert(*left_anchor >= 0);\n        assert(*right_anchor >= 0);\n        *left_anchor = _PyPegen_byte_offset_to_character_offset(segment, *left_anchor) + start_offset;\n        *right_anchor = _PyPegen_byte_offset_to_character_offset(segment, *right_anchor) + start_offset;\n    }\n    Py_XDECREF(segment);\n    if (arena) {\n        _PyArena_Free(arena);\n    }\n    return res;\n}\n\n#define _TRACEBACK_SOURCE_LINE_INDENT 4\n\nstatic inline int\nignore_source_errors(void) {\n    if (PyErr_Occurred()) {\n        if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {\n            return -1;\n        }\n        PyErr_Clear();\n    }\n    return 0;\n}\n\nstatic inline int\nprint_error_location_carets(PyObject *f, int offset, Py_ssize_t start_offset, Py_ssize_t end_offset,\n                            Py_ssize_t right_start_offset, Py_ssize_t left_end_offset,\n                            const char *primary, const char *secondary) {\n    int special_chars = (left_end_offset != -1 || right_start_offset != -1);\n    const char *str;\n    while (++offset <= end_offset) {\n        if (offset <= start_offset) {\n            str = \" \";\n        } else if (special_chars && left_end_offset < offset && offset <= right_start_offset) {\n            str = secondary;\n        } else {\n            str = primary;\n        }\n        if (PyFile_WriteString(str, f) < 0) {\n            return -1;\n        }\n    }\n    if (PyFile_WriteString(\"\\n\", f) < 0) {\n        return -1;\n    }\n    return 0;\n}\n\nstatic int\ntb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int lineno,\n               PyFrameObject *frame, PyObject *name, int margin_indent, const char *margin)\n{\n    if (filename == NULL || name == NULL) {\n        return -1;\n    }\n\n    if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) {\n        return -1;\n    }\n\n    PyObject *line = PyUnicode_FromFormat(\"  File \\\"%U\\\", line %d, in %U\\n\",\n                                          filename, lineno, name);\n    if (line == NULL) {\n        return -1;\n    }\n\n    int res = PyFile_WriteObject(line, f, Py_PRINT_RAW);\n    Py_DECREF(line);\n    if (res < 0) {\n        return -1;\n    }\n\n    int err = 0;\n\n    int truncation = _TRACEBACK_SOURCE_LINE_INDENT;\n    PyObject* source_line = NULL;\n    int rc = display_source_line_with_margin(\n            f, filename, lineno, _TRACEBACK_SOURCE_LINE_INDENT,\n            margin_indent, margin, &truncation, &source_line);\n    if (rc != 0 || !source_line) {\n        /* ignore errors since we can't report them, can we? */\n        err = ignore_source_errors();\n        goto done;\n    }\n\n    int code_offset = tb->tb_lasti;\n    PyCodeObject* code = frame->f_frame->f_code;\n    const Py_ssize_t source_line_len = PyUnicode_GET_LENGTH(source_line);\n\n    int start_line;\n    int end_line;\n    int start_col_byte_offset;\n    int end_col_byte_offset;\n    if (!PyCode_Addr2Location(code, code_offset, &start_line, &start_col_byte_offset,\n                              &end_line, &end_col_byte_offset)) {\n        goto done;\n    }\n\n    if (start_line < 0 || end_line < 0\n        || start_col_byte_offset < 0\n        || end_col_byte_offset < 0)\n    {\n        goto done;\n    }\n\n    // When displaying errors, we will use the following generic structure:\n    //\n    //  ERROR LINE ERROR LINE ERROR LINE ERROR LINE ERROR LINE ERROR LINE ERROR LINE\n    //        ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^~~~~~~~~~~~~~~~~~~~\n    //        |              |-> left_end_offset     |                  |-> end_offset\n    //        |-> start_offset                       |-> right_start_offset\n    //\n    // In general we will only have (start_offset, end_offset) but we can gather more information\n    // by analyzing the AST of the text between *start_offset* and *end_offset*. If this succeeds\n    // we could get *left_end_offset* and *right_start_offset* and some selection of characters for\n    // the different ranges (primary_error_char and secondary_error_char). If we cannot obtain the\n    // AST information or we cannot identify special ranges within it, then left_end_offset and\n    // right_end_offset will be set to -1.\n    //\n    // To keep the column indicators pertinent, they are not shown when the primary character\n    // spans the whole line.\n\n    // Convert the utf-8 byte offset to the actual character offset so we print the right number of carets.\n    assert(source_line);\n    Py_ssize_t start_offset = _PyPegen_byte_offset_to_character_offset(source_line, start_col_byte_offset);\n    if (start_offset < 0) {\n        err = ignore_source_errors() < 0;\n        goto done;\n    }\n\n    Py_ssize_t end_offset = _PyPegen_byte_offset_to_character_offset(source_line, end_col_byte_offset);\n    if (end_offset < 0) {\n        err = ignore_source_errors() < 0;\n        goto done;\n    }\n\n    Py_ssize_t left_end_offset = -1;\n    Py_ssize_t right_start_offset = -1;\n\n    char *primary_error_char = \"^\";\n    char *secondary_error_char = primary_error_char;\n\n    if (start_line == end_line) {\n        int res = extract_anchors_from_line(filename, source_line, start_offset, end_offset,\n                                            &left_end_offset, &right_start_offset,\n                                            &primary_error_char, &secondary_error_char);\n        if (res < 0 && ignore_source_errors() < 0) {\n            goto done;\n        }\n    }\n    else {\n        // If this is a multi-line expression, then we will highlight until\n        // the last non-whitespace character.\n        const char *source_line_str = PyUnicode_AsUTF8(source_line);\n        if (!source_line_str) {\n            goto done;\n        }\n\n        Py_ssize_t i = source_line_len;\n        while (--i >= 0) {\n            if (!IS_WHITESPACE(source_line_str[i])) {\n                break;\n            }\n        }\n\n        end_offset = i + 1;\n    }\n\n    // Elide indicators if primary char spans the frame line\n    Py_ssize_t stripped_line_len = source_line_len - truncation - _TRACEBACK_SOURCE_LINE_INDENT;\n    bool has_secondary_ranges = (left_end_offset != -1 || right_start_offset != -1);\n    if (end_offset - start_offset == stripped_line_len && !has_secondary_ranges) {\n        goto done;\n    }\n\n    if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) {\n        err = -1;\n        goto done;\n    }\n\n    if (print_error_location_carets(f, truncation, start_offset, end_offset,\n                                    right_start_offset, left_end_offset,\n                                    primary_error_char, secondary_error_char) < 0) {\n        err = -1;\n        goto done;\n    }\n\ndone:\n    Py_XDECREF(source_line);\n    return err;\n}\n\nstatic const int TB_RECURSIVE_CUTOFF = 3; // Also hardcoded in traceback.py.\n\nstatic int\ntb_print_line_repeated(PyObject *f, long cnt)\n{\n    cnt -= TB_RECURSIVE_CUTOFF;\n    PyObject *line = PyUnicode_FromFormat(\n        (cnt > 1)\n          ? \"  [Previous line repeated %ld more times]\\n\"\n          : \"  [Previous line repeated %ld more time]\\n\",\n        cnt);\n    if (line == NULL) {\n        return -1;\n    }\n    int err = PyFile_WriteObject(line, f, Py_PRINT_RAW);\n    Py_DECREF(line);\n    return err;\n}\n\nstatic int\ntb_printinternal(PyTracebackObject *tb, PyObject *f, long limit,\n                 int indent, const char *margin)\n{\n    PyCodeObject *code = NULL;\n    Py_ssize_t depth = 0;\n    PyObject *last_file = NULL;\n    int last_line = -1;\n    PyObject *last_name = NULL;\n    long cnt = 0;\n    PyTracebackObject *tb1 = tb;\n    while (tb1 != NULL) {\n        depth++;\n        tb1 = tb1->tb_next;\n    }\n    while (tb != NULL && depth > limit) {\n        depth--;\n        tb = tb->tb_next;\n    }\n    while (tb != NULL) {\n        code = PyFrame_GetCode(tb->tb_frame);\n        if (last_file == NULL ||\n            code->co_filename != last_file ||\n            last_line == -1 || tb->tb_lineno != last_line ||\n            last_name == NULL || code->co_name != last_name) {\n            if (cnt > TB_RECURSIVE_CUTOFF) {\n                if (tb_print_line_repeated(f, cnt) < 0) {\n                    goto error;\n                }\n            }\n            last_file = code->co_filename;\n            last_line = tb->tb_lineno;\n            last_name = code->co_name;\n            cnt = 0;\n        }\n        cnt++;\n        if (cnt <= TB_RECURSIVE_CUTOFF) {\n            if (tb_displayline(tb, f, code->co_filename, tb->tb_lineno,\n                               tb->tb_frame, code->co_name, indent, margin) < 0) {\n                goto error;\n            }\n\n            if (PyErr_CheckSignals() < 0) {\n                goto error;\n            }\n        }\n        Py_CLEAR(code);\n        tb = tb->tb_next;\n    }\n    if (cnt > TB_RECURSIVE_CUTOFF) {\n        if (tb_print_line_repeated(f, cnt) < 0) {\n            goto error;\n        }\n    }\n    return 0;\nerror:\n    Py_XDECREF(code);\n    return -1;\n}\n\n#define PyTraceBack_LIMIT 1000\n\nint\n_PyTraceBack_Print_Indented(PyObject *v, int indent, const char *margin,\n                            const char *header_margin, const char *header, PyObject *f)\n{\n    PyObject *limitv;\n    long limit = PyTraceBack_LIMIT;\n\n    if (v == NULL) {\n        return 0;\n    }\n    if (!PyTraceBack_Check(v)) {\n        PyErr_BadInternalCall();\n        return -1;\n    }\n    limitv = PySys_GetObject(\"tracebacklimit\");\n    if (limitv && PyLong_Check(limitv)) {\n        int overflow;\n        limit = PyLong_AsLongAndOverflow(limitv, &overflow);\n        if (overflow > 0) {\n            limit = LONG_MAX;\n        }\n        else if (limit <= 0) {\n            return 0;\n        }\n    }\n    if (_Py_WriteIndentedMargin(indent, header_margin, f) < 0) {\n        return -1;\n    }\n\n    if (PyFile_WriteString(header, f) < 0) {\n        return -1;\n    }\n\n    if (tb_printinternal((PyTracebackObject *)v, f, limit, indent, margin) < 0) {\n        return -1;\n    }\n\n    return 0;\n}\n\nint\nPyTraceBack_Print(PyObject *v, PyObject *f)\n{\n    int indent = 0;\n    const char *margin = NULL;\n    const char *header_margin = NULL;\n    const char *header = EXCEPTION_TB_HEADER;\n\n    return _PyTraceBack_Print_Indented(v, indent, margin, header_margin, header, f);\n}\n\n/* Format an integer in range [0; 0xffffffff] to decimal and write it\n   into the file fd.\n\n   This function is signal safe. */\n\nvoid\n_Py_DumpDecimal(int fd, size_t value)\n{\n    /* maximum number of characters required for output of %lld or %p.\n       We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits,\n       plus 1 for the null byte.  53/22 is an upper bound for log10(256). */\n    char buffer[1 + (sizeof(size_t)*53-1) / 22 + 1];\n    char *ptr, *end;\n\n    end = &buffer[Py_ARRAY_LENGTH(buffer) - 1];\n    ptr = end;\n    *ptr = '\\0';\n    do {\n        --ptr;\n        assert(ptr >= buffer);\n        *ptr = '0' + (value % 10);\n        value /= 10;\n    } while (value);\n\n    _Py_write_noraise(fd, ptr, end - ptr);\n}\n\n/* Format an integer as hexadecimal with width digits into fd file descriptor.\n   The function is signal safe. */\nvoid\n_Py_DumpHexadecimal(int fd, uintptr_t value, Py_ssize_t width)\n{\n    char buffer[sizeof(uintptr_t) * 2 + 1], *ptr, *end;\n    const Py_ssize_t size = Py_ARRAY_LENGTH(buffer) - 1;\n\n    if (width > size)\n        width = size;\n    /* it's ok if width is negative */\n\n    end = &buffer[size];\n    ptr = end;\n    *ptr = '\\0';\n    do {\n        --ptr;\n        assert(ptr >= buffer);\n        *ptr = Py_hexdigits[value & 15];\n        value >>= 4;\n    } while ((end - ptr) < width || value);\n\n    _Py_write_noraise(fd, ptr, end - ptr);\n}\n\nvoid\n_Py_DumpASCII(int fd, PyObject *text)\n{\n    PyASCIIObject *ascii = _PyASCIIObject_CAST(text);\n    Py_ssize_t i, size;\n    int truncated;\n    int kind;\n    void *data = NULL;\n    Py_UCS4 ch;\n\n    if (!PyUnicode_Check(text))\n        return;\n\n    size = ascii->length;\n    kind = ascii->state.kind;\n    if (ascii->state.compact) {\n        if (ascii->state.ascii)\n            data = ascii + 1;\n        else\n            data = _PyCompactUnicodeObject_CAST(text) + 1;\n    }\n    else {\n        data = _PyUnicodeObject_CAST(text)->data.any;\n        if (data == NULL)\n            return;\n    }\n\n    if (MAX_STRING_LENGTH < size) {\n        size = MAX_STRING_LENGTH;\n        truncated = 1;\n    }\n    else {\n        truncated = 0;\n    }\n\n    // Is an ASCII string?\n    if (ascii->state.ascii) {\n        assert(kind == PyUnicode_1BYTE_KIND);\n        char *str = data;\n\n        int need_escape = 0;\n        for (i=0; i < size; i++) {\n            ch = str[i];\n            if (!(' ' <= ch && ch <= 126)) {\n                need_escape = 1;\n                break;\n            }\n        }\n        if (!need_escape) {\n            // The string can be written with a single write() syscall\n            _Py_write_noraise(fd, str, size);\n            goto done;\n        }\n    }\n\n    for (i=0; i < size; i++) {\n        ch = PyUnicode_READ(kind, data, i);\n        if (' ' <= ch && ch <= 126) {\n            /* printable ASCII character */\n            char c = (char)ch;\n            _Py_write_noraise(fd, &c, 1);\n        }\n        else if (ch <= 0xff) {\n            PUTS(fd, \"\\\\x\");\n            _Py_DumpHexadecimal(fd, ch, 2);\n        }\n        else if (ch <= 0xffff) {\n            PUTS(fd, \"\\\\u\");\n            _Py_DumpHexadecimal(fd, ch, 4);\n        }\n        else {\n            PUTS(fd, \"\\\\U\");\n            _Py_DumpHexadecimal(fd, ch, 8);\n        }\n    }\n\ndone:\n    if (truncated) {\n        PUTS(fd, \"...\");\n    }\n}\n\n/* Write a frame into the file fd: \"File \"xxx\", line xxx in xxx\".\n\n   This function is signal safe. */\n\nstatic void\ndump_frame(int fd, _PyInterpreterFrame *frame)\n{\n    PyCodeObject *code = frame->f_code;\n    PUTS(fd, \"  File \");\n    if (code->co_filename != NULL\n        && PyUnicode_Check(code->co_filename))\n    {\n        PUTS(fd, \"\\\"\");\n        _Py_DumpASCII(fd, code->co_filename);\n        PUTS(fd, \"\\\"\");\n    } else {\n        PUTS(fd, \"???\");\n    }\n\n    int lineno = PyUnstable_InterpreterFrame_GetLine(frame);\n    PUTS(fd, \", line \");\n    if (lineno >= 0) {\n        _Py_DumpDecimal(fd, (size_t)lineno);\n    }\n    else {\n        PUTS(fd, \"???\");\n    }\n    PUTS(fd, \" in \");\n\n    if (code->co_name != NULL\n       && PyUnicode_Check(code->co_name)) {\n        _Py_DumpASCII(fd, code->co_name);\n    }\n    else {\n        PUTS(fd, \"???\");\n    }\n\n    PUTS(fd, \"\\n\");\n}\n\nstatic void\ndump_traceback(int fd, PyThreadState *tstate, int write_header)\n{\n    _PyInterpreterFrame *frame;\n    unsigned int depth;\n\n    if (write_header) {\n        PUTS(fd, \"Stack (most recent call first):\\n\");\n    }\n\n    frame = tstate->cframe->current_frame;\n    if (frame == NULL) {\n        PUTS(fd, \"  <no Python frame>\\n\");\n        return;\n    }\n\n    depth = 0;\n    while (1) {\n        if (MAX_FRAME_DEPTH <= depth) {\n            PUTS(fd, \"  ...\\n\");\n            break;\n        }\n        dump_frame(fd, frame);\n        frame = frame->previous;\n        if (frame == NULL) {\n            break;\n        }\n        if (frame->owner == FRAME_OWNED_BY_CSTACK) {\n            /* Trampoline frame */\n            frame = frame->previous;\n        }\n        if (frame == NULL) {\n            break;\n        }\n        /* Can't have more than one shim frame in a row */\n        assert(frame->owner != FRAME_OWNED_BY_CSTACK);\n        depth++;\n    }\n}\n\n/* Dump the traceback of a Python thread into fd. Use write() to write the\n   traceback and retry if write() is interrupted by a signal (failed with\n   EINTR), but don't call the Python signal handler.\n\n   The caller is responsible to call PyErr_CheckSignals() to call Python signal\n   handlers if signals were received. */\nvoid\n_Py_DumpTraceback(int fd, PyThreadState *tstate)\n{\n    dump_traceback(fd, tstate, 1);\n}\n\n/* Write the thread identifier into the file 'fd': \"Current thread 0xHHHH:\\\" if\n   is_current is true, \"Thread 0xHHHH:\\n\" otherwise.\n\n   This function is signal safe. */\n\nstatic void\nwrite_thread_id(int fd, PyThreadState *tstate, int is_current)\n{\n    if (is_current)\n        PUTS(fd, \"Current thread 0x\");\n    else\n        PUTS(fd, \"Thread 0x\");\n    _Py_DumpHexadecimal(fd,\n                        tstate->thread_id,\n                        sizeof(unsigned long) * 2);\n    PUTS(fd, \" (most recent call first):\\n\");\n}\n\n/* Dump the traceback of all Python threads into fd. Use write() to write the\n   traceback and retry if write() is interrupted by a signal (failed with\n   EINTR), but don't call the Python signal handler.\n\n   The caller is responsible to call PyErr_CheckSignals() to call Python signal\n   handlers if signals were received. */\nconst char*\n_Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,\n                         PyThreadState *current_tstate)\n{\n    PyThreadState *tstate;\n    unsigned int nthreads;\n\n    if (current_tstate == NULL) {\n        /* _Py_DumpTracebackThreads() is called from signal handlers by\n           faulthandler.\n\n           SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals\n           and are thus delivered to the thread that caused the fault. Get the\n           Python thread state of the current thread.\n\n           PyThreadState_Get() doesn't give the state of the thread that caused\n           the fault if the thread released the GIL, and so\n           _PyThreadState_GET() cannot be used. Read the thread specific\n           storage (TSS) instead: call PyGILState_GetThisThreadState(). */\n        current_tstate = PyGILState_GetThisThreadState();\n    }\n\n    if (interp == NULL) {\n        if (current_tstate == NULL) {\n            interp = _PyGILState_GetInterpreterStateUnsafe();\n            if (interp == NULL) {\n                /* We need the interpreter state to get Python threads */\n                return \"unable to get the interpreter state\";\n            }\n        }\n        else {\n            interp = current_tstate->interp;\n        }\n    }\n    assert(interp != NULL);\n\n    /* Get the current interpreter from the current thread */\n    tstate = PyInterpreterState_ThreadHead(interp);\n    if (tstate == NULL)\n        return \"unable to get the thread head state\";\n\n    /* Dump the traceback of each thread */\n    tstate = PyInterpreterState_ThreadHead(interp);\n    nthreads = 0;\n    _Py_BEGIN_SUPPRESS_IPH\n    do\n    {\n        if (nthreads != 0)\n            PUTS(fd, \"\\n\");\n        if (nthreads >= MAX_NTHREADS) {\n            PUTS(fd, \"...\\n\");\n            break;\n        }\n        write_thread_id(fd, tstate, tstate == current_tstate);\n        if (tstate == current_tstate && tstate->interp->gc.collecting) {\n            PUTS(fd, \"  Garbage-collecting\\n\");\n        }\n        dump_traceback(fd, tstate, 0);\n        tstate = PyThreadState_Next(tstate);\n        nthreads++;\n    } while (tstate != NULL);\n    _Py_END_SUPPRESS_IPH\n\n    return NULL;\n}\n"
  },
  {
    "path": "TraceMalloc.c",
    "content": "#include \"Python.h\"\n#include \"pycore_fileutils.h\"     // _Py_write_noraise()\n#include \"pycore_gc.h\"            // PyGC_Head\n#include \"pycore_hashtable.h\"     // _Py_hashtable_t\n#include \"pycore_object.h\"        // _PyType_PreHeaderSize\n#include \"pycore_pymem.h\"         // _Py_tracemalloc_config\n#include \"pycore_runtime.h\"       // _Py_ID()\n#include \"pycore_traceback.h\"\n#include <pycore_frame.h>\n#include \"frameobject.h\"          // _PyInterpreterFrame_GetLine\n\n#include <stdlib.h>               // malloc()\n\n#define tracemalloc_config _PyRuntime.tracemalloc.config\n\n_Py_DECLARE_STR(anon_unknown, \"<unknown>\");\n\n/* Forward declaration */\nstatic void* raw_malloc(size_t size);\nstatic void raw_free(void *ptr);\n\n#ifdef Py_DEBUG\n#  define TRACE_DEBUG\n#endif\n\n#define TO_PTR(key) ((const void *)(uintptr_t)(key))\n#define FROM_PTR(key) ((uintptr_t)(key))\n\n#define allocators _PyRuntime.tracemalloc.allocators\n\n\n#if defined(TRACE_RAW_MALLOC)\n/* This lock is needed because tracemalloc_free() is called without\n   the GIL held from PyMem_RawFree(). It cannot acquire the lock because it\n   would introduce a deadlock in _PyThreadState_DeleteCurrent(). */\n#  define tables_lock _PyRuntime.tracemalloc.tables_lock\n#  define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1)\n#  define TABLES_UNLOCK() PyThread_release_lock(tables_lock)\n#else\n   /* variables are protected by the GIL */\n#  define TABLES_LOCK()\n#  define TABLES_UNLOCK()\n#endif\n\n\n#define DEFAULT_DOMAIN 0\n\ntypedef struct tracemalloc_frame frame_t;\ntypedef struct tracemalloc_traceback traceback_t;\n\n#define TRACEBACK_SIZE(NFRAME) \\\n        (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))\n\n/* The maximum number of frames is either:\n - The maximum number of frames we can store in `traceback_t.nframe`\n - The maximum memory size_t we can allocate */\nstatic const unsigned long MAX_NFRAME = Py_MIN(UINT16_MAX, ((SIZE_MAX - sizeof(traceback_t)) / sizeof(frame_t) + 1));\n\n\n#define tracemalloc_empty_traceback _PyRuntime.tracemalloc.empty_traceback\n\n\n/* Trace of a memory block */\ntypedef struct {\n    /* Size of the memory block in bytes */\n    size_t size;\n\n    /* Traceback where the memory block was allocated */\n    traceback_t *traceback;\n} trace_t;\n\n\n#define tracemalloc_traced_memory _PyRuntime.tracemalloc.traced_memory\n#define tracemalloc_peak_traced_memory _PyRuntime.tracemalloc.peak_traced_memory\n#define tracemalloc_filenames _PyRuntime.tracemalloc.filenames\n#define tracemalloc_traceback _PyRuntime.tracemalloc.traceback\n#define tracemalloc_tracebacks _PyRuntime.tracemalloc.tracebacks\n#define tracemalloc_traces _PyRuntime.tracemalloc.traces\n#define tracemalloc_domains _PyRuntime.tracemalloc.domains\n\n\n#ifdef TRACE_DEBUG\nstatic void\ntracemalloc_error(const char *format, ...)\n{\n    va_list ap;\n    fprintf(stderr, \"tracemalloc: \");\n    va_start(ap, format);\n    vfprintf(stderr, format, ap);\n    va_end(ap);\n    fprintf(stderr, \"\\n\");\n    fflush(stderr);\n}\n#endif\n\n\n#if defined(TRACE_RAW_MALLOC)\n#define REENTRANT_THREADLOCAL\n\n#define tracemalloc_reentrant_key _PyRuntime.tracemalloc.reentrant_key\n\n/* Any non-NULL pointer can be used */\n#define REENTRANT Py_True\n\nstatic int\nget_reentrant(void)\n{\n    void *ptr;\n\n    assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));\n    ptr = PyThread_tss_get(&tracemalloc_reentrant_key);\n    if (ptr != NULL) {\n        assert(ptr == REENTRANT);\n        return 1;\n    }\n    else\n        return 0;\n}\n\nstatic void\nset_reentrant(int reentrant)\n{\n    assert(reentrant == 0 || reentrant == 1);\n    assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));\n\n    if (reentrant) {\n        assert(!get_reentrant());\n        PyThread_tss_set(&tracemalloc_reentrant_key, REENTRANT);\n    }\n    else {\n        assert(get_reentrant());\n        PyThread_tss_set(&tracemalloc_reentrant_key, NULL);\n    }\n}\n\n#else\n\n/* TRACE_RAW_MALLOC not defined: variable protected by the GIL */\nstatic int tracemalloc_reentrant = 0;\n\nstatic int\nget_reentrant(void)\n{\n    return tracemalloc_reentrant;\n}\n\nstatic void\nset_reentrant(int reentrant)\n{\n    assert(reentrant != tracemalloc_reentrant);\n    tracemalloc_reentrant = reentrant;\n}\n#endif\n\n\nstatic Py_uhash_t\nhashtable_hash_pyobject(const void *key)\n{\n    PyObject *obj = (PyObject *)key;\n    return PyObject_Hash(obj);\n}\n\n\nstatic int\nhashtable_compare_unicode(const void *key1, const void *key2)\n{\n    PyObject *obj1 = (PyObject *)key1;\n    PyObject *obj2 = (PyObject *)key2;\n    if (obj1 != NULL && obj2 != NULL) {\n        return (PyUnicode_Compare(obj1, obj2) == 0);\n    }\n    else {\n        return obj1 == obj2;\n    }\n}\n\n\nstatic Py_uhash_t\nhashtable_hash_uint(const void *key_raw)\n{\n    unsigned int key = (unsigned int)FROM_PTR(key_raw);\n    return (Py_uhash_t)key;\n}\n\n\nstatic _Py_hashtable_t *\nhashtable_new(_Py_hashtable_hash_func hash_func,\n              _Py_hashtable_compare_func compare_func,\n              _Py_hashtable_destroy_func key_destroy_func,\n              _Py_hashtable_destroy_func value_destroy_func)\n{\n    _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};\n    return _Py_hashtable_new_full(hash_func, compare_func,\n                                  key_destroy_func, value_destroy_func,\n                                  &hashtable_alloc);\n}\n\n\nstatic void*\nraw_malloc(size_t size)\n{\n    return allocators.raw.malloc(allocators.raw.ctx, size);\n}\n\nstatic void\nraw_free(void *ptr)\n{\n    allocators.raw.free(allocators.raw.ctx, ptr);\n}\n\n\nstatic Py_uhash_t\nhashtable_hash_traceback(const void *key)\n{\n    const traceback_t *traceback = (const traceback_t *)key;\n    return traceback->hash;\n}\n\n\nstatic int\nhashtable_compare_traceback(const void *key1, const void *key2)\n{\n    const traceback_t *traceback1 = (const traceback_t *)key1;\n    const traceback_t *traceback2 = (const traceback_t *)key2;\n\n    if (traceback1->nframe != traceback2->nframe) {\n        return 0;\n    }\n    if (traceback1->total_nframe != traceback2->total_nframe) {\n        return 0;\n    }\n\n    for (int i=0; i < traceback1->nframe; i++) {\n        const frame_t *frame1 = &traceback1->frames[i];\n        const frame_t *frame2 = &traceback2->frames[i];\n\n        if (frame1->lineno != frame2->lineno) {\n            return 0;\n        }\n        if (frame1->filename != frame2->filename) {\n            assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);\n            return 0;\n        }\n    }\n    return 1;\n}\n\n\nstatic void\ntracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)\n{\n    frame->filename = &_Py_STR(anon_unknown);\n    int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe);\n    if (lineno < 0) {\n        lineno = 0;\n    }\n    frame->lineno = (unsigned int)lineno;\n\n    PyObject *filename = pyframe->f_code->co_filename;\n\n    if (filename == NULL) {\n#ifdef TRACE_DEBUG\n        tracemalloc_error(\"failed to get the filename of the code object\");\n#endif\n        return;\n    }\n\n    if (!PyUnicode_Check(filename)) {\n#ifdef TRACE_DEBUG\n        tracemalloc_error(\"filename is not a unicode string\");\n#endif\n        return;\n    }\n    if (!PyUnicode_IS_READY(filename)) {\n        /* Don't make a Unicode string ready to avoid reentrant calls\n           to tracemalloc_malloc() or tracemalloc_realloc() */\n#ifdef TRACE_DEBUG\n        tracemalloc_error(\"filename is not a ready unicode string\");\n#endif\n        return;\n    }\n\n    /* intern the filename */\n    _Py_hashtable_entry_t *entry;\n    entry = _Py_hashtable_get_entry(tracemalloc_filenames, filename);\n    if (entry != NULL) {\n        filename = (PyObject *)entry->key;\n    }\n    else {\n        /* tracemalloc_filenames is responsible to keep a reference\n           to the filename */\n        if (_Py_hashtable_set(tracemalloc_filenames, Py_NewRef(filename),\n                              NULL) < 0) {\n            Py_DECREF(filename);\n#ifdef TRACE_DEBUG\n            tracemalloc_error(\"failed to intern the filename\");\n#endif\n            return;\n        }\n    }\n\n    /* the tracemalloc_filenames table keeps a reference to the filename */\n    frame->filename = filename;\n}\n\n\nstatic Py_uhash_t\ntraceback_hash(traceback_t *traceback)\n{\n    /* code based on tuplehash() of Objects/tupleobject.c */\n    Py_uhash_t x, y;  /* Unsigned for defined overflow behavior. */\n    int len = traceback->nframe;\n    Py_uhash_t mult = _PyHASH_MULTIPLIER;\n    frame_t *frame;\n\n    x = 0x345678UL;\n    frame = traceback->frames;\n    while (--len >= 0) {\n        y = (Py_uhash_t)PyObject_Hash(frame->filename);\n        y ^= (Py_uhash_t)frame->lineno;\n        frame++;\n\n        x = (x ^ y) * mult;\n        /* the cast might truncate len; that doesn't change hash stability */\n        mult += (Py_uhash_t)(82520UL + len + len);\n    }\n    x ^= traceback->total_nframe;\n    x += 97531UL;\n    return x;\n}\n\n\nstatic void\ntraceback_get_frames(traceback_t *traceback)\n{\n    PyThreadState *tstate = PyGILState_GetThisThreadState();\n    if (tstate == NULL) {\n#ifdef TRACE_DEBUG\n        tracemalloc_error(\"failed to get the current thread state\");\n#endif\n        return;\n    }\n\n    _PyInterpreterFrame *pyframe = _PyThreadState_GetFrame(tstate);\n    while (pyframe) {\n        if (traceback->nframe < tracemalloc_config.max_nframe) {\n            tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);\n            assert(traceback->frames[traceback->nframe].filename != NULL);\n            traceback->nframe++;\n        }\n        if (traceback->total_nframe < UINT16_MAX) {\n            traceback->total_nframe++;\n        }\n        pyframe = _PyFrame_GetFirstComplete(pyframe->previous);\n    }\n}\n\n\nstatic traceback_t *\ntraceback_new(void)\n{\n    traceback_t *traceback;\n    _Py_hashtable_entry_t *entry;\n\n    assert(PyGILState_Check());\n\n    /* get frames */\n    traceback = tracemalloc_traceback;\n    traceback->nframe = 0;\n    traceback->total_nframe = 0;\n    traceback_get_frames(traceback);\n    if (traceback->nframe == 0)\n        return &tracemalloc_empty_traceback;\n    traceback->hash = traceback_hash(traceback);\n\n    /* intern the traceback */\n    entry = _Py_hashtable_get_entry(tracemalloc_tracebacks, traceback);\n    if (entry != NULL) {\n        traceback = (traceback_t *)entry->key;\n    }\n    else {\n        traceback_t *copy;\n        size_t traceback_size;\n\n        traceback_size = TRACEBACK_SIZE(traceback->nframe);\n\n        copy = raw_malloc(traceback_size);\n        if (copy == NULL) {\n#ifdef TRACE_DEBUG\n            tracemalloc_error(\"failed to intern the traceback: malloc failed\");\n#endif\n            return NULL;\n        }\n        memcpy(copy, traceback, traceback_size);\n\n        if (_Py_hashtable_set(tracemalloc_tracebacks, copy, NULL) < 0) {\n            raw_free(copy);\n#ifdef TRACE_DEBUG\n            tracemalloc_error(\"failed to intern the traceback: putdata failed\");\n#endif\n            return NULL;\n        }\n        traceback = copy;\n    }\n    return traceback;\n}\n\n\nstatic _Py_hashtable_t*\ntracemalloc_create_traces_table(void)\n{\n    return hashtable_new(_Py_hashtable_hash_ptr,\n                         _Py_hashtable_compare_direct,\n                         NULL, raw_free);\n}\n\n\nstatic _Py_hashtable_t*\ntracemalloc_create_domains_table(void)\n{\n    return hashtable_new(hashtable_hash_uint,\n                         _Py_hashtable_compare_direct,\n                         NULL,\n                         (_Py_hashtable_destroy_func)_Py_hashtable_destroy);\n}\n\n\nstatic _Py_hashtable_t*\ntracemalloc_get_traces_table(unsigned int domain)\n{\n    if (domain == DEFAULT_DOMAIN) {\n        return tracemalloc_traces;\n    }\n    else {\n        return _Py_hashtable_get(tracemalloc_domains, TO_PTR(domain));\n    }\n}\n\n\nstatic void\ntracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)\n{\n    assert(tracemalloc_config.tracing);\n\n    _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain);\n    if (!traces) {\n        return;\n    }\n\n    trace_t *trace = _Py_hashtable_steal(traces, TO_PTR(ptr));\n    if (!trace) {\n        return;\n    }\n    assert(tracemalloc_traced_memory >= trace->size);\n    tracemalloc_traced_memory -= trace->size;\n    raw_free(trace);\n}\n\n#define REMOVE_TRACE(ptr) \\\n            tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))\n\n\nstatic int\ntracemalloc_add_trace(unsigned int domain, uintptr_t ptr,\n                      size_t size)\n{\n    assert(tracemalloc_config.tracing);\n\n    traceback_t *traceback = traceback_new();\n    if (traceback == NULL) {\n        return -1;\n    }\n\n    _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain);\n    if (traces == NULL) {\n        traces = tracemalloc_create_traces_table();\n        if (traces == NULL) {\n            return -1;\n        }\n\n        if (_Py_hashtable_set(tracemalloc_domains, TO_PTR(domain), traces) < 0) {\n            _Py_hashtable_destroy(traces);\n            return -1;\n        }\n    }\n\n    trace_t *trace = _Py_hashtable_get(traces, TO_PTR(ptr));\n    if (trace != NULL) {\n        /* the memory block is already tracked */\n        assert(tracemalloc_traced_memory >= trace->size);\n        tracemalloc_traced_memory -= trace->size;\n\n        trace->size = size;\n        trace->traceback = traceback;\n    }\n    else {\n        trace = raw_malloc(sizeof(trace_t));\n        if (trace == NULL) {\n            return -1;\n        }\n        trace->size = size;\n        trace->traceback = traceback;\n\n        int res = _Py_hashtable_set(traces, TO_PTR(ptr), trace);\n        if (res != 0) {\n            raw_free(trace);\n            return res;\n        }\n    }\n\n    assert(tracemalloc_traced_memory <= SIZE_MAX - size);\n    tracemalloc_traced_memory += size;\n    if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory) {\n        tracemalloc_peak_traced_memory = tracemalloc_traced_memory;\n    }\n    return 0;\n}\n\n#define ADD_TRACE(ptr, size) \\\n            tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)\n\n\nstatic void*\ntracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)\n{\n    PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;\n    void *ptr;\n\n    assert(elsize == 0 || nelem <= SIZE_MAX / elsize);\n\n    if (use_calloc)\n        ptr = alloc->calloc(alloc->ctx, nelem, elsize);\n    else\n        ptr = alloc->malloc(alloc->ctx, nelem * elsize);\n    if (ptr == NULL)\n        return NULL;\n\n    TABLES_LOCK();\n    if (ADD_TRACE(ptr, nelem * elsize) < 0) {\n        /* Failed to allocate a trace for the new memory block */\n        TABLES_UNLOCK();\n        alloc->free(alloc->ctx, ptr);\n        return NULL;\n    }\n    TABLES_UNLOCK();\n    return ptr;\n}\n\n\nstatic void*\ntracemalloc_realloc(void *ctx, void *ptr, size_t new_size)\n{\n    PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;\n    void *ptr2;\n\n    ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);\n    if (ptr2 == NULL)\n        return NULL;\n\n    if (ptr != NULL) {\n        /* an existing memory block has been resized */\n\n        TABLES_LOCK();\n\n        /* tracemalloc_add_trace() updates the trace if there is already\n           a trace at address ptr2 */\n        if (ptr2 != ptr) {\n            REMOVE_TRACE(ptr);\n        }\n\n        if (ADD_TRACE(ptr2, new_size) < 0) {\n            /* Memory allocation failed. The error cannot be reported to\n               the caller, because realloc() may already have shrunk the\n               memory block and so removed bytes.\n\n               This case is very unlikely: a hash entry has just been\n               released, so the hash table should have at least one free entry.\n\n               The GIL and the table lock ensures that only one thread is\n               allocating memory. */\n            Py_FatalError(\"tracemalloc_realloc() failed to allocate a trace\");\n        }\n        TABLES_UNLOCK();\n    }\n    else {\n        /* new allocation */\n\n        TABLES_LOCK();\n        if (ADD_TRACE(ptr2, new_size) < 0) {\n            /* Failed to allocate a trace for the new memory block */\n            TABLES_UNLOCK();\n            alloc->free(alloc->ctx, ptr2);\n            return NULL;\n        }\n        TABLES_UNLOCK();\n    }\n    return ptr2;\n}\n\n\nstatic void\ntracemalloc_free(void *ctx, void *ptr)\n{\n    PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;\n\n    if (ptr == NULL)\n        return;\n\n     /* GIL cannot be locked in PyMem_RawFree() because it would introduce\n        a deadlock in _PyThreadState_DeleteCurrent(). */\n\n    alloc->free(alloc->ctx, ptr);\n\n    TABLES_LOCK();\n    REMOVE_TRACE(ptr);\n    TABLES_UNLOCK();\n}\n\n\nstatic void*\ntracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)\n{\n    void *ptr;\n\n    if (get_reentrant()) {\n        PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;\n        if (use_calloc)\n            return alloc->calloc(alloc->ctx, nelem, elsize);\n        else\n            return alloc->malloc(alloc->ctx, nelem * elsize);\n    }\n\n    /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for\n       allocations larger than 512 bytes, don't trace the same memory\n       allocation twice. */\n    set_reentrant(1);\n\n    ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);\n\n    set_reentrant(0);\n    return ptr;\n}\n\n\nstatic void*\ntracemalloc_malloc_gil(void *ctx, size_t size)\n{\n    return tracemalloc_alloc_gil(0, ctx, 1, size);\n}\n\n\nstatic void*\ntracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)\n{\n    return tracemalloc_alloc_gil(1, ctx, nelem, elsize);\n}\n\n\nstatic void*\ntracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)\n{\n    void *ptr2;\n\n    if (get_reentrant()) {\n        /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().\n           Example: PyMem_RawRealloc() is called internally by pymalloc\n           (_PyObject_Malloc() and  _PyObject_Realloc()) to allocate a new\n           arena (new_arena()). */\n        PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;\n\n        ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);\n        if (ptr2 != NULL && ptr != NULL) {\n            TABLES_LOCK();\n            REMOVE_TRACE(ptr);\n            TABLES_UNLOCK();\n        }\n        return ptr2;\n    }\n\n    /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for\n       allocations larger than 512 bytes. Don't trace the same memory\n       allocation twice. */\n    set_reentrant(1);\n\n    ptr2 = tracemalloc_realloc(ctx, ptr, new_size);\n\n    set_reentrant(0);\n    return ptr2;\n}\n\n\n#ifdef TRACE_RAW_MALLOC\nstatic void*\ntracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)\n{\n    PyGILState_STATE gil_state;\n    void *ptr;\n\n    if (get_reentrant()) {\n        PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;\n        if (use_calloc)\n            return alloc->calloc(alloc->ctx, nelem, elsize);\n        else\n            return alloc->malloc(alloc->ctx, nelem * elsize);\n    }\n\n    /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()\n       indirectly which would call PyGILState_Ensure() if reentrant are not\n       disabled. */\n    set_reentrant(1);\n\n    gil_state = PyGILState_Ensure();\n    ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);\n    PyGILState_Release(gil_state);\n\n    set_reentrant(0);\n    return ptr;\n}\n\n\nstatic void*\ntracemalloc_raw_malloc(void *ctx, size_t size)\n{\n    return tracemalloc_raw_alloc(0, ctx, 1, size);\n}\n\n\nstatic void*\ntracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)\n{\n    return tracemalloc_raw_alloc(1, ctx, nelem, elsize);\n}\n\n\nstatic void*\ntracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)\n{\n    PyGILState_STATE gil_state;\n    void *ptr2;\n\n    if (get_reentrant()) {\n        /* Reentrant call to PyMem_RawRealloc(). */\n        PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;\n\n        ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);\n\n        if (ptr2 != NULL && ptr != NULL) {\n            TABLES_LOCK();\n            REMOVE_TRACE(ptr);\n            TABLES_UNLOCK();\n        }\n        return ptr2;\n    }\n\n    /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()\n       indirectly which would call PyGILState_Ensure() if reentrant calls are\n       not disabled. */\n    set_reentrant(1);\n\n    gil_state = PyGILState_Ensure();\n    ptr2 = tracemalloc_realloc(ctx, ptr, new_size);\n    PyGILState_Release(gil_state);\n\n    set_reentrant(0);\n    return ptr2;\n}\n#endif   /* TRACE_RAW_MALLOC */\n\n\nstatic void\ntracemalloc_clear_filename(void *value)\n{\n    PyObject *filename = (PyObject *)value;\n    Py_DECREF(filename);\n}\n\n\n/* reentrant flag must be set to call this function and GIL must be held */\nstatic void\ntracemalloc_clear_traces(void)\n{\n    /* The GIL protects variables against concurrent access */\n    assert(PyGILState_Check());\n\n    TABLES_LOCK();\n    _Py_hashtable_clear(tracemalloc_traces);\n    _Py_hashtable_clear(tracemalloc_domains);\n    tracemalloc_traced_memory = 0;\n    tracemalloc_peak_traced_memory = 0;\n    TABLES_UNLOCK();\n\n    _Py_hashtable_clear(tracemalloc_tracebacks);\n\n    _Py_hashtable_clear(tracemalloc_filenames);\n}\n\n\nint\n_PyTraceMalloc_Init(void)\n{\n    if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {\n        PyErr_SetString(PyExc_RuntimeError,\n                        \"the tracemalloc module has been unloaded\");\n        return -1;\n    }\n\n    if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)\n        return 0;\n\n    PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);\n\n#ifdef REENTRANT_THREADLOCAL\n    if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) {\n#ifdef MS_WINDOWS\n        PyErr_SetFromWindowsErr(0);\n#else\n        PyErr_SetFromErrno(PyExc_OSError);\n#endif\n        return -1;\n    }\n#endif\n\n#if defined(TRACE_RAW_MALLOC)\n    if (tables_lock == NULL) {\n        tables_lock = PyThread_allocate_lock();\n        if (tables_lock == NULL) {\n            PyErr_SetString(PyExc_RuntimeError, \"cannot allocate lock\");\n            return -1;\n        }\n    }\n#endif\n\n    tracemalloc_filenames = hashtable_new(hashtable_hash_pyobject,\n                                          hashtable_compare_unicode,\n                                          tracemalloc_clear_filename, NULL);\n\n    tracemalloc_tracebacks = hashtable_new(hashtable_hash_traceback,\n                                           hashtable_compare_traceback,\n                                           NULL, raw_free);\n\n    tracemalloc_traces = tracemalloc_create_traces_table();\n    tracemalloc_domains = tracemalloc_create_domains_table();\n\n    if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL\n       || tracemalloc_traces == NULL || tracemalloc_domains == NULL) {\n        PyErr_NoMemory();\n        return -1;\n    }\n\n    tracemalloc_empty_traceback.nframe = 1;\n    tracemalloc_empty_traceback.total_nframe = 1;\n    /* borrowed reference */\n    tracemalloc_empty_traceback.frames[0].filename = &_Py_STR(anon_unknown);\n    tracemalloc_empty_traceback.frames[0].lineno = 0;\n    tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);\n\n    tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;\n    return 0;\n}\n\n\nstatic void\ntracemalloc_deinit(void)\n{\n    if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)\n        return;\n    tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;\n\n    _PyTraceMalloc_Stop();\n\n    /* destroy hash tables */\n    _Py_hashtable_destroy(tracemalloc_domains);\n    _Py_hashtable_destroy(tracemalloc_traces);\n    _Py_hashtable_destroy(tracemalloc_tracebacks);\n    _Py_hashtable_destroy(tracemalloc_filenames);\n\n#if defined(TRACE_RAW_MALLOC)\n    if (tables_lock != NULL) {\n        PyThread_free_lock(tables_lock);\n        tables_lock = NULL;\n    }\n#endif\n\n#ifdef REENTRANT_THREADLOCAL\n    PyThread_tss_delete(&tracemalloc_reentrant_key);\n#endif\n}\n\n\nint\n_PyTraceMalloc_Start(int max_nframe)\n{\n    PyMemAllocatorEx alloc;\n    size_t size;\n\n    if (max_nframe < 1 || (unsigned long) max_nframe > MAX_NFRAME) {\n        PyErr_Format(PyExc_ValueError,\n                     \"the number of frames must be in range [1; %lu]\",\n                     MAX_NFRAME);\n        return -1;\n    }\n\n    if (_PyTraceMalloc_Init() < 0) {\n        return -1;\n    }\n\n    if (tracemalloc_config.tracing) {\n        /* hook already installed: do nothing */\n        return 0;\n    }\n\n    tracemalloc_config.max_nframe = max_nframe;\n\n    /* allocate a buffer to store a new traceback */\n    size = TRACEBACK_SIZE(max_nframe);\n    assert(tracemalloc_traceback == NULL);\n    tracemalloc_traceback = raw_malloc(size);\n    if (tracemalloc_traceback == NULL) {\n        PyErr_NoMemory();\n        return -1;\n    }\n\n#ifdef TRACE_RAW_MALLOC\n    alloc.malloc = tracemalloc_raw_malloc;\n    alloc.calloc = tracemalloc_raw_calloc;\n    alloc.realloc = tracemalloc_raw_realloc;\n    alloc.free = tracemalloc_free;\n\n    alloc.ctx = &allocators.raw;\n    PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);\n#endif\n\n    alloc.malloc = tracemalloc_malloc_gil;\n    alloc.calloc = tracemalloc_calloc_gil;\n    alloc.realloc = tracemalloc_realloc_gil;\n    alloc.free = tracemalloc_free;\n\n    alloc.ctx = &allocators.mem;\n    PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);\n    PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);\n\n    alloc.ctx = &allocators.obj;\n    PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);\n    PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);\n\n    /* everything is ready: start tracing Python memory allocations */\n    tracemalloc_config.tracing = 1;\n\n    return 0;\n}\n\n\nvoid\n_PyTraceMalloc_Stop(void)\n{\n    if (!tracemalloc_config.tracing)\n        return;\n\n    /* stop tracing Python memory allocations */\n    tracemalloc_config.tracing = 0;\n\n    /* unregister the hook on memory allocators */\n#ifdef TRACE_RAW_MALLOC\n    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);\n#endif\n    PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);\n    PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);\n\n    tracemalloc_clear_traces();\n\n    /* release memory */\n    raw_free(tracemalloc_traceback);\n    tracemalloc_traceback = NULL;\n}\n\n\n\nstatic PyObject*\nframe_to_pyobject(frame_t *frame)\n{\n    PyObject *frame_obj, *lineno_obj;\n\n    frame_obj = PyTuple_New(2);\n    if (frame_obj == NULL)\n        return NULL;\n\n    PyTuple_SET_ITEM(frame_obj, 0, Py_NewRef(frame->filename));\n\n    lineno_obj = PyLong_FromUnsignedLong(frame->lineno);\n    if (lineno_obj == NULL) {\n        Py_DECREF(frame_obj);\n        return NULL;\n    }\n    PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);\n\n    return frame_obj;\n}\n\n\nstatic PyObject*\ntraceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)\n{\n    PyObject *frames;\n\n    if (intern_table != NULL) {\n        frames = _Py_hashtable_get(intern_table, (const void *)traceback);\n        if (frames) {\n            return Py_NewRef(frames);\n        }\n    }\n\n    frames = PyTuple_New(traceback->nframe);\n    if (frames == NULL)\n        return NULL;\n\n    for (int i=0; i < traceback->nframe; i++) {\n        PyObject *frame = frame_to_pyobject(&traceback->frames[i]);\n        if (frame == NULL) {\n            Py_DECREF(frames);\n            return NULL;\n        }\n        PyTuple_SET_ITEM(frames, i, frame);\n    }\n\n    if (intern_table != NULL) {\n        if (_Py_hashtable_set(intern_table, traceback, frames) < 0) {\n            Py_DECREF(frames);\n            PyErr_NoMemory();\n            return NULL;\n        }\n        /* intern_table keeps a new reference to frames */\n        Py_INCREF(frames);\n    }\n    return frames;\n}\n\n\nstatic PyObject*\ntrace_to_pyobject(unsigned int domain, const trace_t *trace,\n                  _Py_hashtable_t *intern_tracebacks)\n{\n    PyObject *trace_obj = NULL;\n    PyObject *obj;\n\n    trace_obj = PyTuple_New(4);\n    if (trace_obj == NULL)\n        return NULL;\n\n    obj = PyLong_FromSize_t(domain);\n    if (obj == NULL) {\n        Py_DECREF(trace_obj);\n        return NULL;\n    }\n    PyTuple_SET_ITEM(trace_obj, 0, obj);\n\n    obj = PyLong_FromSize_t(trace->size);\n    if (obj == NULL) {\n        Py_DECREF(trace_obj);\n        return NULL;\n    }\n    PyTuple_SET_ITEM(trace_obj, 1, obj);\n\n    obj = traceback_to_pyobject(trace->traceback, intern_tracebacks);\n    if (obj == NULL) {\n        Py_DECREF(trace_obj);\n        return NULL;\n    }\n    PyTuple_SET_ITEM(trace_obj, 2, obj);\n\n    obj = PyLong_FromUnsignedLong(trace->traceback->total_nframe);\n    if (obj == NULL) {\n        Py_DECREF(trace_obj);\n        return NULL;\n    }\n    PyTuple_SET_ITEM(trace_obj, 3, obj);\n\n    return trace_obj;\n}\n\n\ntypedef struct {\n    _Py_hashtable_t *traces;\n    _Py_hashtable_t *domains;\n    _Py_hashtable_t *tracebacks;\n    PyObject *list;\n    unsigned int domain;\n} get_traces_t;\n\n\nstatic int\ntracemalloc_copy_trace(_Py_hashtable_t *traces,\n                       const void *key, const void *value,\n                       void *user_data)\n{\n    _Py_hashtable_t *traces2 = (_Py_hashtable_t *)user_data;\n\n    trace_t *trace = (trace_t *)value;\n\n    trace_t *trace2 = raw_malloc(sizeof(trace_t));\n    if (trace2 == NULL) {\n        return -1;\n    }\n    *trace2 = *trace;\n    if (_Py_hashtable_set(traces2, key, trace2) < 0) {\n        raw_free(trace2);\n        return -1;\n    }\n    return 0;\n}\n\n\nstatic _Py_hashtable_t*\ntracemalloc_copy_traces(_Py_hashtable_t *traces)\n{\n    _Py_hashtable_t *traces2 = tracemalloc_create_traces_table();\n    if (traces2 == NULL) {\n        return NULL;\n    }\n\n    int err = _Py_hashtable_foreach(traces,\n                                    tracemalloc_copy_trace,\n                                    traces2);\n    if (err) {\n        _Py_hashtable_destroy(traces2);\n        return NULL;\n    }\n    return traces2;\n}\n\n\nstatic int\ntracemalloc_copy_domain(_Py_hashtable_t *domains,\n                        const void *key, const void *value,\n                        void *user_data)\n{\n    _Py_hashtable_t *domains2 = (_Py_hashtable_t *)user_data;\n\n    unsigned int domain = (unsigned int)FROM_PTR(key);\n    _Py_hashtable_t *traces = (_Py_hashtable_t *)value;\n\n    _Py_hashtable_t *traces2 = tracemalloc_copy_traces(traces);\n    if (traces2 == NULL) {\n        return -1;\n    }\n    if (_Py_hashtable_set(domains2, TO_PTR(domain), traces2) < 0) {\n        _Py_hashtable_destroy(traces2);\n        return -1;\n    }\n    return 0;\n}\n\n\nstatic _Py_hashtable_t*\ntracemalloc_copy_domains(_Py_hashtable_t *domains)\n{\n    _Py_hashtable_t *domains2 = tracemalloc_create_domains_table();\n    if (domains2 == NULL) {\n        return NULL;\n    }\n\n    int err = _Py_hashtable_foreach(domains,\n                                    tracemalloc_copy_domain,\n                                    domains2);\n    if (err) {\n        _Py_hashtable_destroy(domains2);\n        return NULL;\n    }\n    return domains2;\n}\n\n\nstatic int\ntracemalloc_get_traces_fill(_Py_hashtable_t *traces,\n                            const void *key, const void *value,\n                            void *user_data)\n{\n    get_traces_t *get_traces = user_data;\n\n    const trace_t *trace = (const trace_t *)value;\n\n    PyObject *tuple = trace_to_pyobject(get_traces->domain, trace,\n                                        get_traces->tracebacks);\n    if (tuple == NULL) {\n        return 1;\n    }\n\n    int res = PyList_Append(get_traces->list, tuple);\n    Py_DECREF(tuple);\n    if (res < 0) {\n        return 1;\n    }\n\n    return 0;\n}\n\n\nstatic int\ntracemalloc_get_traces_domain(_Py_hashtable_t *domains,\n                              const void *key, const void *value,\n                              void *user_data)\n{\n    get_traces_t *get_traces = user_data;\n\n    unsigned int domain = (unsigned int)FROM_PTR(key);\n    _Py_hashtable_t *traces = (_Py_hashtable_t *)value;\n\n    get_traces->domain = domain;\n    return _Py_hashtable_foreach(traces,\n                                 tracemalloc_get_traces_fill,\n                                 get_traces);\n}\n\n\nstatic void\ntracemalloc_pyobject_decref(void *value)\n{\n    PyObject *obj = (PyObject *)value;\n    Py_DECREF(obj);\n}\n\n\nstatic traceback_t*\ntracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)\n{\n\n    if (!tracemalloc_config.tracing)\n        return NULL;\n\n    trace_t *trace;\n    TABLES_LOCK();\n    _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain);\n    if (traces) {\n        trace = _Py_hashtable_get(traces, TO_PTR(ptr));\n    }\n    else {\n        trace = NULL;\n    }\n    TABLES_UNLOCK();\n\n    if (!trace) {\n        return NULL;\n    }\n\n    return trace->traceback;\n}\n\n\n#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))\n\nstatic void\n_PyMem_DumpFrame(int fd, frame_t * frame)\n{\n    PUTS(fd, \"  File \\\"\");\n    _Py_DumpASCII(fd, frame->filename);\n    PUTS(fd, \"\\\", line \");\n    _Py_DumpDecimal(fd, frame->lineno);\n    PUTS(fd, \"\\n\");\n}\n\n/* Dump the traceback where a memory block was allocated into file descriptor\n   fd. The function may block on TABLES_LOCK() but it is unlikely. */\nvoid\n_PyMem_DumpTraceback(int fd, const void *ptr)\n{\n    traceback_t *traceback;\n    int i;\n\n    if (!tracemalloc_config.tracing) {\n        PUTS(fd, \"Enable tracemalloc to get the memory block \"\n                 \"allocation traceback\\n\\n\");\n        return;\n    }\n\n    traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);\n    if (traceback == NULL)\n        return;\n\n    PUTS(fd, \"Memory block allocated at (most recent call first):\\n\");\n    for (i=0; i < traceback->nframe; i++) {\n        _PyMem_DumpFrame(fd, &traceback->frames[i]);\n    }\n    PUTS(fd, \"\\n\");\n}\n\n#undef PUTS\n\n\nstatic int\ntracemalloc_get_tracemalloc_memory_cb(_Py_hashtable_t *domains,\n                                      const void *key, const void *value,\n                                      void *user_data)\n{\n    const _Py_hashtable_t *traces = value;\n    size_t *size = (size_t*)user_data;\n    *size += _Py_hashtable_size(traces);\n    return 0;\n}\n\nint\nPyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,\n                    size_t size)\n{\n    int res;\n    PyGILState_STATE gil_state;\n\n    if (!tracemalloc_config.tracing) {\n        /* tracemalloc is not tracing: do nothing */\n        return -2;\n    }\n\n    gil_state = PyGILState_Ensure();\n\n    TABLES_LOCK();\n    res = tracemalloc_add_trace(domain, ptr, size);\n    TABLES_UNLOCK();\n\n    PyGILState_Release(gil_state);\n    return res;\n}\n\n\nint\nPyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)\n{\n    if (!tracemalloc_config.tracing) {\n        /* tracemalloc is not tracing: do nothing */\n        return -2;\n    }\n\n    TABLES_LOCK();\n    tracemalloc_remove_trace(domain, ptr);\n    TABLES_UNLOCK();\n\n    return 0;\n}\n\n\nvoid\n_PyTraceMalloc_Fini(void)\n{\n    assert(PyGILState_Check());\n    tracemalloc_deinit();\n}\n\n\n/* If the object memory block is already traced, update its trace\n   with the current Python traceback.\n\n   Do nothing if tracemalloc is not tracing memory allocations\n   or if the object memory block is not already traced. */\nint\n_PyTraceMalloc_NewReference(PyObject *op)\n{\n    assert(PyGILState_Check());\n\n    if (!tracemalloc_config.tracing) {\n        /* tracemalloc is not tracing: do nothing */\n        return -1;\n    }\n\n    PyTypeObject *type = Py_TYPE(op);\n    const size_t presize = _PyType_PreHeaderSize(type);\n    uintptr_t ptr = (uintptr_t)((char *)op - presize);\n\n    int res = -1;\n\n    TABLES_LOCK();\n    trace_t *trace = _Py_hashtable_get(tracemalloc_traces, TO_PTR(ptr));\n    if (trace != NULL) {\n        /* update the traceback of the memory block */\n        traceback_t *traceback = traceback_new();\n        if (traceback != NULL) {\n            trace->traceback = traceback;\n            res = 0;\n        }\n    }\n    /* else: cannot track the object, its memory block size is unknown */\n    TABLES_UNLOCK();\n\n    return res;\n}\n\n\nPyObject*\n_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)\n{\n    traceback_t *traceback;\n\n    traceback = tracemalloc_get_traceback(domain, ptr);\n    if (traceback == NULL)\n        Py_RETURN_NONE;\n\n    return traceback_to_pyobject(traceback, NULL);\n}\n\nint\n_PyTraceMalloc_IsTracing(void)\n{\n    return tracemalloc_config.tracing;\n}\n\nvoid\n_PyTraceMalloc_ClearTraces(void)\n{\n\n    if (!tracemalloc_config.tracing) {\n        return;\n    }\n    set_reentrant(1);\n    tracemalloc_clear_traces();\n    set_reentrant(0);\n}\n\nPyObject *\n_PyTraceMalloc_GetTraces(void)\n{\n    get_traces_t get_traces;\n    get_traces.domain = DEFAULT_DOMAIN;\n    get_traces.traces = NULL;\n    get_traces.domains = NULL;\n    get_traces.tracebacks = NULL;\n    get_traces.list = PyList_New(0);\n    if (get_traces.list == NULL)\n        goto error;\n\n    if (!tracemalloc_config.tracing)\n        return get_traces.list;\n\n    /* the traceback hash table is used temporarily to intern traceback tuple\n       of (filename, lineno) tuples */\n    get_traces.tracebacks = hashtable_new(_Py_hashtable_hash_ptr,\n                                          _Py_hashtable_compare_direct,\n                                          NULL, tracemalloc_pyobject_decref);\n    if (get_traces.tracebacks == NULL) {\n        goto no_memory;\n    }\n\n    // Copy all traces so tracemalloc_get_traces_fill() doesn't have to disable\n    // temporarily tracemalloc which would impact other threads and so would\n    // miss allocations while get_traces() is called.\n    TABLES_LOCK();\n    get_traces.traces = tracemalloc_copy_traces(tracemalloc_traces);\n    TABLES_UNLOCK();\n\n    if (get_traces.traces == NULL) {\n        goto no_memory;\n    }\n\n    TABLES_LOCK();\n    get_traces.domains = tracemalloc_copy_domains(tracemalloc_domains);\n    TABLES_UNLOCK();\n\n    if (get_traces.domains == NULL) {\n        goto no_memory;\n    }\n\n    // Convert traces to a list of tuples\n    set_reentrant(1);\n    int err = _Py_hashtable_foreach(get_traces.traces,\n                                    tracemalloc_get_traces_fill,\n                                    &get_traces);\n    if (!err) {\n        err = _Py_hashtable_foreach(get_traces.domains,\n                                    tracemalloc_get_traces_domain,\n                                    &get_traces);\n    }\n    set_reentrant(0);\n    if (err) {\n        goto error;\n    }\n\n    goto finally;\n\nno_memory:\n    PyErr_NoMemory();\n\nerror:\n    Py_CLEAR(get_traces.list);\n\nfinally:\n    if (get_traces.tracebacks != NULL) {\n        _Py_hashtable_destroy(get_traces.tracebacks);\n    }\n    if (get_traces.traces != NULL) {\n        _Py_hashtable_destroy(get_traces.traces);\n    }\n    if (get_traces.domains != NULL) {\n        _Py_hashtable_destroy(get_traces.domains);\n    }\n\n    return get_traces.list;\n}\n\nPyObject *\n_PyTraceMalloc_GetObjectTraceback(PyObject *obj)\n/*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/\n{\n    PyTypeObject *type;\n    traceback_t *traceback;\n\n    type = Py_TYPE(obj);\n    const size_t presize = _PyType_PreHeaderSize(type);\n    uintptr_t ptr = (uintptr_t)((char *)obj - presize);\n\n    traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, ptr);\n    if (traceback == NULL) {\n        Py_RETURN_NONE;\n    }\n\n    return traceback_to_pyobject(traceback, NULL);\n}\n\nint _PyTraceMalloc_GetTracebackLimit(void) {\n    return tracemalloc_config.max_nframe;\n}\n\nsize_t\n_PyTraceMalloc_GetMemory(void) {\n\n    size_t size;\n\n    size = _Py_hashtable_size(tracemalloc_tracebacks);\n    size += _Py_hashtable_size(tracemalloc_filenames);\n\n    TABLES_LOCK();\n    size += _Py_hashtable_size(tracemalloc_traces);\n    _Py_hashtable_foreach(tracemalloc_domains,\n                          tracemalloc_get_tracemalloc_memory_cb, &size);\n    TABLES_UNLOCK();\n    return size;\n}\n\n\nPyObject *\n_PyTraceMalloc_GetTracedMemory(void)\n{\n    Py_ssize_t size, peak_size;\n\n    if (!tracemalloc_config.tracing)\n        return Py_BuildValue(\"ii\", 0, 0);\n\n    TABLES_LOCK();\n    size = tracemalloc_traced_memory;\n    peak_size = tracemalloc_peak_traced_memory;\n    TABLES_UNLOCK();\n\n    return Py_BuildValue(\"nn\", size, peak_size);\n}\n\nvoid\n_PyTraceMalloc_ResetPeak(void)\n{\n    if (!tracemalloc_config.tracing) {\n        return;\n    }\n    TABLES_LOCK();\n    tracemalloc_peak_traced_memory = tracemalloc_traced_memory;\n    TABLES_UNLOCK();\n}\n"
  }
]