[Python-checkins] cpython: Issue #22869: Split pythonrun into two modules

nick.coghlan python-checkins at python.org
Thu Nov 20 12:40:30 CET 2014


https://hg.python.org/cpython/rev/b9775a92c1d0
changeset:   93515:b9775a92c1d0
parent:      93513:23ab1197df0b
user:        Nick Coghlan <ncoghlan at gmail.com>
date:        Thu Nov 20 21:39:37 2014 +1000
summary:
  Issue #22869: Split pythonrun into two modules

- interpreter startup and shutdown code moved to a new
  pylifecycle.c module
- Py_OptimizeFlag moved into the new module with the other
  global flags

files:
  Include/Python.h       |     1 +
  Include/object.h       |     7 +
  Include/pydebug.h      |     2 +
  Include/pyerrors.h     |     1 +
  Include/pylifecycle.h  |   124 ++
  Include/pythonrun.h    |   110 --
  Lib/_pyio.py           |     2 +-
  Makefile.pre.in        |     2 +
  Misc/NEWS              |     3 +
  Modules/atexitmodule.c |     2 +-
  Modules/signalmodule.c |     2 +-
  Objects/object.c       |    16 +
  Python/compile.c       |     2 -
  Python/pylifecycle.c   |  1540 ++++++++++++++++++++++++++++
  Python/pythonrun.c     |  1472 +--------------------------
  Python/sysmodule.c     |     2 +-
  16 files changed, 1701 insertions(+), 1587 deletions(-)


diff --git a/Include/Python.h b/Include/Python.h
--- a/Include/Python.h
+++ b/Include/Python.h
@@ -112,6 +112,7 @@
 #include "pyarena.h"
 #include "modsupport.h"
 #include "pythonrun.h"
+#include "pylifecycle.h"
 #include "ceval.h"
 #include "sysmodule.h"
 #include "intrcheck.h"
diff --git a/Include/object.h b/Include/object.h
--- a/Include/object.h
+++ b/Include/object.h
@@ -65,6 +65,7 @@
 #error Py_LIMITED_API is incompatible with Py_DEBUG, Py_TRACE_REFS, and Py_REF_DEBUG
 #endif
 
+
 #ifdef Py_TRACE_REFS
 /* Define pointers to support a doubly-linked list of all live heap objects. */
 #define _PyObject_HEAD_EXTRA            \
@@ -710,11 +711,17 @@
                 _Py_NegativeRefcount(__FILE__, __LINE__,        \
                                      (PyObject *)(OP));         \
 }
+/* Py_REF_DEBUG also controls the display of refcounts and memory block
+ * allocations at the interactive prompt and at interpreter shutdown
+ */
+PyAPI_FUNC(void) _PyDebug_PrintTotalRefs(void);
+#define _PY_DEBUG_PRINT_TOTAL_REFS() _PyDebug_PrintTotalRefs()
 #else
 #define _Py_INC_REFTOTAL
 #define _Py_DEC_REFTOTAL
 #define _Py_REF_DEBUG_COMMA
 #define _Py_CHECK_REFCNT(OP)    /* a semicolon */;
+#define _PY_DEBUG_PRINT_TOTAL_REFS()
 #endif /* Py_REF_DEBUG */
 
 #ifdef COUNT_ALLOCS
diff --git a/Include/pydebug.h b/Include/pydebug.h
--- a/Include/pydebug.h
+++ b/Include/pydebug.h
@@ -5,6 +5,8 @@
 extern "C" {
 #endif
 
+/* These global variable are defined in pylifecycle.c */
+/* XXX (ncoghlan): move these declarations to pylifecycle.h? */
 PyAPI_DATA(int) Py_DebugFlag;
 PyAPI_DATA(int) Py_VerboseFlag;
 PyAPI_DATA(int) Py_QuietFlag;
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -99,6 +99,7 @@
 #define _Py_NO_RETURN
 #endif
 
+/* Defined in Python/pylifecycle.c */
 PyAPI_FUNC(void) Py_FatalError(const char *message) _Py_NO_RETURN;
 
 #if defined(Py_DEBUG) || defined(Py_LIMITED_API)
diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h
new file mode 100644
--- /dev/null
+++ b/Include/pylifecycle.h
@@ -0,0 +1,124 @@
+
+/* Interfaces to configure, query, create & destroy the Python runtime */
+
+#ifndef Py_PYLIFECYCLE_H
+#define Py_PYLIFECYCLE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PyAPI_FUNC(void) Py_SetProgramName(wchar_t *);
+PyAPI_FUNC(wchar_t *) Py_GetProgramName(void);
+
+PyAPI_FUNC(void) Py_SetPythonHome(wchar_t *);
+PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void);
+
+#ifndef Py_LIMITED_API
+/* Only used by applications that embed the interpreter and need to
+ * override the standard encoding determination mechanism
+ */
+PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding,
+                                             const char *errors);
+#endif
+
+PyAPI_FUNC(void) Py_Initialize(void);
+PyAPI_FUNC(void) Py_InitializeEx(int);
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(void) _Py_InitializeEx_Private(int, int);
+#endif
+PyAPI_FUNC(void) Py_Finalize(void);
+PyAPI_FUNC(int) Py_IsInitialized(void);
+PyAPI_FUNC(PyThreadState *) Py_NewInterpreter(void);
+PyAPI_FUNC(void) Py_EndInterpreter(PyThreadState *);
+
+
+/* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level
+ * exit functions.
+ */
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(void) _Py_PyAtExit(void (*func)(void));
+#endif
+PyAPI_FUNC(int) Py_AtExit(void (*func)(void));
+
+PyAPI_FUNC(void) Py_Exit(int);
+
+/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL. */
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(void) _Py_RestoreSignals(void);
+
+PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *);
+#endif
+
+/* Bootstrap __main__ (defined in Modules/main.c) */
+PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv);
+
+/* In getpath.c */
+PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void);
+PyAPI_FUNC(wchar_t *) Py_GetPrefix(void);
+PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
+PyAPI_FUNC(wchar_t *) Py_GetPath(void);
+PyAPI_FUNC(void)      Py_SetPath(const wchar_t *);
+#ifdef MS_WINDOWS
+int _Py_CheckPython3();
+#endif
+
+/* In their own files */
+PyAPI_FUNC(const char *) Py_GetVersion(void);
+PyAPI_FUNC(const char *) Py_GetPlatform(void);
+PyAPI_FUNC(const char *) Py_GetCopyright(void);
+PyAPI_FUNC(const char *) Py_GetCompiler(void);
+PyAPI_FUNC(const char *) Py_GetBuildInfo(void);
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(const char *) _Py_hgidentifier(void);
+PyAPI_FUNC(const char *) _Py_hgversion(void);
+#endif
+
+/* Internal -- various one-time initializations */
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
+PyAPI_FUNC(PyObject *) _PySys_Init(void);
+PyAPI_FUNC(void) _PyImport_Init(void);
+PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod);
+PyAPI_FUNC(void) _PyImportHooks_Init(void);
+PyAPI_FUNC(int) _PyFrame_Init(void);
+PyAPI_FUNC(int) _PyFloat_Init(void);
+PyAPI_FUNC(int) PyByteArray_Init(void);
+PyAPI_FUNC(void) _PyRandom_Init(void);
+#endif
+
+/* Various internal finalizers */
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(void) _PyExc_Fini(void);
+PyAPI_FUNC(void) _PyImport_Fini(void);
+PyAPI_FUNC(void) PyMethod_Fini(void);
+PyAPI_FUNC(void) PyFrame_Fini(void);
+PyAPI_FUNC(void) PyCFunction_Fini(void);
+PyAPI_FUNC(void) PyDict_Fini(void);
+PyAPI_FUNC(void) PyTuple_Fini(void);
+PyAPI_FUNC(void) PyList_Fini(void);
+PyAPI_FUNC(void) PySet_Fini(void);
+PyAPI_FUNC(void) PyBytes_Fini(void);
+PyAPI_FUNC(void) PyByteArray_Fini(void);
+PyAPI_FUNC(void) PyFloat_Fini(void);
+PyAPI_FUNC(void) PyOS_FiniInterrupts(void);
+PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void);
+PyAPI_FUNC(void) _PyGC_Fini(void);
+PyAPI_FUNC(void) PySlice_Fini(void);
+PyAPI_FUNC(void) _PyType_Fini(void);
+PyAPI_FUNC(void) _PyRandom_Fini(void);
+
+PyAPI_DATA(PyThreadState *) _Py_Finalizing;
+#endif
+
+/* Signals */
+typedef void (*PyOS_sighandler_t)(int);
+PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int);
+PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t);
+
+/* Random */
+PyAPI_FUNC(int) _PyOS_URandom (void *buffer, Py_ssize_t size);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_PYLIFECYCLE_H */
diff --git a/Include/pythonrun.h b/Include/pythonrun.h
--- a/Include/pythonrun.h
+++ b/Include/pythonrun.h
@@ -22,30 +22,6 @@
 } PyCompilerFlags;
 #endif
 
-PyAPI_FUNC(void) Py_SetProgramName(wchar_t *);
-PyAPI_FUNC(wchar_t *) Py_GetProgramName(void);
-
-PyAPI_FUNC(void) Py_SetPythonHome(wchar_t *);
-PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void);
-
-#ifndef Py_LIMITED_API
-/* Only used by applications that embed the interpreter and need to
- * override the standard encoding determination mechanism
- */
-PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding,
-                                             const char *errors);
-#endif
-
-PyAPI_FUNC(void) Py_Initialize(void);
-PyAPI_FUNC(void) Py_InitializeEx(int);
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(void) _Py_InitializeEx_Private(int, int);
-#endif
-PyAPI_FUNC(void) Py_Finalize(void);
-PyAPI_FUNC(int) Py_IsInitialized(void);
-PyAPI_FUNC(PyThreadState *) Py_NewInterpreter(void);
-PyAPI_FUNC(void) Py_EndInterpreter(PyThreadState *);
-
 #ifndef Py_LIMITED_API
 PyAPI_FUNC(int) PyRun_SimpleStringFlags(const char *, PyCompilerFlags *);
 PyAPI_FUNC(int) PyRun_AnyFileFlags(FILE *, const char *, PyCompilerFlags *);
@@ -166,26 +142,6 @@
 PyAPI_FUNC(void) PyErr_PrintEx(int);
 PyAPI_FUNC(void) PyErr_Display(PyObject *, PyObject *, PyObject *);
 
-/* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level
- * exit functions.
- */
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(void) _Py_PyAtExit(void (*func)(void));
-#endif
-PyAPI_FUNC(int) Py_AtExit(void (*func)(void));
-
-PyAPI_FUNC(void) Py_Exit(int);
-
-/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL. */
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(void) _Py_RestoreSignals(void);
-
-PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *);
-#endif
-
-/* Bootstrap */
-PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv);
-
 #ifndef Py_LIMITED_API
 /* Use macros for a bunch of old variants */
 #define PyRun_String(str, s, g, l) PyRun_StringFlags(str, s, g, l, NULL)
@@ -207,64 +163,6 @@
     PyRun_FileExFlags(fp, p, s, g, l, 0, flags)
 #endif
 
-/* In getpath.c */
-PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void);
-PyAPI_FUNC(wchar_t *) Py_GetPrefix(void);
-PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
-PyAPI_FUNC(wchar_t *) Py_GetPath(void);
-PyAPI_FUNC(void)      Py_SetPath(const wchar_t *);
-#ifdef MS_WINDOWS
-int _Py_CheckPython3();
-#endif
-
-/* In their own files */
-PyAPI_FUNC(const char *) Py_GetVersion(void);
-PyAPI_FUNC(const char *) Py_GetPlatform(void);
-PyAPI_FUNC(const char *) Py_GetCopyright(void);
-PyAPI_FUNC(const char *) Py_GetCompiler(void);
-PyAPI_FUNC(const char *) Py_GetBuildInfo(void);
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(const char *) _Py_hgidentifier(void);
-PyAPI_FUNC(const char *) _Py_hgversion(void);
-#endif
-
-/* Internal -- various one-time initializations */
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
-PyAPI_FUNC(PyObject *) _PySys_Init(void);
-PyAPI_FUNC(void) _PyImport_Init(void);
-PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod);
-PyAPI_FUNC(void) _PyImportHooks_Init(void);
-PyAPI_FUNC(int) _PyFrame_Init(void);
-PyAPI_FUNC(int) _PyFloat_Init(void);
-PyAPI_FUNC(int) PyByteArray_Init(void);
-PyAPI_FUNC(void) _PyRandom_Init(void);
-#endif
-
-/* Various internal finalizers */
-#ifndef Py_LIMITED_API
-PyAPI_FUNC(void) _PyExc_Fini(void);
-PyAPI_FUNC(void) _PyImport_Fini(void);
-PyAPI_FUNC(void) PyMethod_Fini(void);
-PyAPI_FUNC(void) PyFrame_Fini(void);
-PyAPI_FUNC(void) PyCFunction_Fini(void);
-PyAPI_FUNC(void) PyDict_Fini(void);
-PyAPI_FUNC(void) PyTuple_Fini(void);
-PyAPI_FUNC(void) PyList_Fini(void);
-PyAPI_FUNC(void) PySet_Fini(void);
-PyAPI_FUNC(void) PyBytes_Fini(void);
-PyAPI_FUNC(void) PyByteArray_Fini(void);
-PyAPI_FUNC(void) PyFloat_Fini(void);
-PyAPI_FUNC(void) PyOS_FiniInterrupts(void);
-PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void);
-PyAPI_FUNC(void) _PyGC_Fini(void);
-PyAPI_FUNC(void) PySlice_Fini(void);
-PyAPI_FUNC(void) _PyType_Fini(void);
-PyAPI_FUNC(void) _PyRandom_Fini(void);
-
-PyAPI_DATA(PyThreadState *) _Py_Finalizing;
-#endif
-
 /* Stuff with no proper home (yet) */
 #ifndef Py_LIMITED_API
 PyAPI_FUNC(char *) PyOS_Readline(FILE *, FILE *, const char *);
@@ -290,14 +188,6 @@
 PyAPI_FUNC(int) PyOS_CheckStack(void);
 #endif
 
-/* Signals */
-typedef void (*PyOS_sighandler_t)(int);
-PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int);
-PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t);
-
-/* Random */
-PyAPI_FUNC(int) _PyOS_URandom (void *buffer, Py_ssize_t size);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -257,7 +257,7 @@
     Trick so that open won't become a bound method when stored
     as a class variable (as dbm.dumb does).
 
-    See initstdio() in Python/pythonrun.c.
+    See initstdio() in Python/pylifecycle.c.
     """
     __doc__ = DocDescriptor()
 
diff --git a/Makefile.pre.in b/Makefile.pre.in
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -389,6 +389,7 @@
 		Python/pyctype.o \
 		Python/pyfpe.o \
 		Python/pyhash.o \
+		Python/pylifecycle.o \
 		Python/pymath.o \
 		Python/pystate.o \
 		Python/pythonrun.o \
@@ -909,6 +910,7 @@
 		$(srcdir)/Include/pyerrors.h \
 		$(srcdir)/Include/pyfpe.h \
 		$(srcdir)/Include/pyhash.h \
+		$(srcdir)/Include/pylifecycle.h \
 		$(srcdir)/Include/pymath.h \
 		$(srcdir)/Include/pygetopt.h \
 		$(srcdir)/Include/pymacro.h \
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #22869: Move the interpreter startup & shutdown code to a new
+  dedicated pylifecycle.c module
+
 - Issue #22847: Improve method cache efficiency.
 
 - Issue #22335: Fix crash when trying to enlarge a bytearray to 0x7fffffff
diff --git a/Modules/atexitmodule.c b/Modules/atexitmodule.c
--- a/Modules/atexitmodule.c
+++ b/Modules/atexitmodule.c
@@ -60,7 +60,7 @@
     modstate->ncallbacks = 0;
 }
 
-/* Installed into pythonrun.c's atexit mechanism */
+/* Installed into pylifecycle.c's atexit mechanism */
 
 static void
 atexit_callfuncs(void)
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -304,7 +304,7 @@
     if (sig_num != SIGCHLD)
 #endif
     /* If the handler was not set up with sigaction, reinstall it.  See
-     * Python/pythonrun.c for the implementation of PyOS_setsig which
+     * Python/pylifecycle.c for the implementation of PyOS_setsig which
      * makes this true.  See also issue8354. */
     PyOS_setsig(sig_num, signal_handler);
 #endif
diff --git a/Objects/object.c b/Objects/object.c
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -33,6 +33,22 @@
         total -= o->ob_refcnt;
     return total;
 }
+
+void
+_PyDebug_PrintTotalRefs(void) {
+    PyObject *xoptions, *value;
+    _Py_IDENTIFIER(showrefcount);
+
+    xoptions = PySys_GetXOptions();
+    if (xoptions == NULL)
+        return;
+    value = _PyDict_GetItemId(xoptions, &PyId_showrefcount);
+    if (value == Py_True)
+        fprintf(stderr,
+                "[%" PY_FORMAT_SIZE_T "d refs, "
+                "%" PY_FORMAT_SIZE_T "d blocks]\n",
+                _Py_GetRefTotal(), _Py_GetAllocatedBlocks());
+}
 #endif /* Py_REF_DEBUG */
 
 /* Object allocation routines used by NEWOBJ and NEWVAROBJ macros.
diff --git a/Python/compile.c b/Python/compile.c
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -30,8 +30,6 @@
 #include "symtable.h"
 #include "opcode.h"
 
-int Py_OptimizeFlag = 0;
-
 #define DEFAULT_BLOCK_SIZE 16
 #define DEFAULT_BLOCKS 8
 #define DEFAULT_CODE_SIZE 128
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
new file mode 100644
--- /dev/null
+++ b/Python/pylifecycle.c
@@ -0,0 +1,1540 @@
+
+/* Python interpreter top-level routines, including init/exit */
+
+#include "Python.h"
+
+#include "Python-ast.h"
+#undef Yield /* undefine macro conflicting with winbase.h */
+#include "grammar.h"
+#include "node.h"
+#include "token.h"
+#include "parsetok.h"
+#include "errcode.h"
+#include "code.h"
+#include "symtable.h"
+#include "ast.h"
+#include "marshal.h"
+#include "osdefs.h"
+#include <locale.h>
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef MS_WINDOWS
+#include "malloc.h" /* for alloca */
+#endif
+
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+
+#ifdef MS_WINDOWS
+#undef BYTE
+#include "windows.h"
+#endif
+
+_Py_IDENTIFIER(flush);
+_Py_IDENTIFIER(name);
+_Py_IDENTIFIER(stdin);
+_Py_IDENTIFIER(stdout);
+_Py_IDENTIFIER(stderr);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern wchar_t *Py_GetPath(void);
+
+extern grammar _PyParser_Grammar; /* From graminit.c */
+
+/* Forward */
+static void initmain(PyInterpreterState *interp);
+static int initfsencoding(PyInterpreterState *interp);
+static void initsite(void);
+static int initstdio(void);
+static void initsigs(void);
+static void call_py_exitfuncs(void);
+static void wait_for_thread_shutdown(void);
+static void call_ll_exitfuncs(void);
+extern int _PyUnicode_Init(void);
+extern int _PyStructSequence_Init(void);
+extern void _PyUnicode_Fini(void);
+extern int _PyLong_Init(void);
+extern void PyLong_Fini(void);
+extern int _PyFaulthandler_Init(void);
+extern void _PyFaulthandler_Fini(void);
+extern void _PyHash_Fini(void);
+extern int _PyTraceMalloc_Init(void);
+extern int _PyTraceMalloc_Fini(void);
+
+#ifdef WITH_THREAD
+extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *);
+extern void _PyGILState_Fini(void);
+#endif /* WITH_THREAD */
+
+/* Global configuration variable declarations are in pydebug.h */
+/* XXX (ncoghlan): move those declarations to pylifecycle.h? */
+int Py_DebugFlag; /* Needed by parser.c */
+int Py_VerboseFlag; /* Needed by import.c */
+int Py_QuietFlag; /* Needed by sysmodule.c */
+int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */
+int Py_InspectFlag; /* Needed to determine whether to exit at SystemExit */
+int Py_OptimizeFlag = 0; /* Needed by compile.c */
+int Py_NoSiteFlag; /* Suppress 'import site' */
+int Py_BytesWarningFlag; /* Warn on str(bytes) and str(buffer) */
+int Py_UseClassExceptionsFlag = 1; /* Needed by bltinmodule.c: deprecated */
+int Py_FrozenFlag; /* Needed by getpath.c */
+int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
+int Py_DontWriteBytecodeFlag; /* Suppress writing bytecode files (*.py[co]) */
+int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
+int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
+int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
+int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */
+
+PyThreadState *_Py_Finalizing = NULL;
+
+/* Hack to force loading of object files */
+int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) = \
+    PyOS_mystrnicmp; /* Python/pystrcmp.o */
+
+/* PyModule_GetWarningsModule is no longer necessary as of 2.6
+since _warnings is builtin.  This API should not be used. */
+PyObject *
+PyModule_GetWarningsModule(void)
+{
+    return PyImport_ImportModule("warnings");
+}
+
+static int initialized = 0;
+
+/* API to access the initialized flag -- useful for esoteric use */
+
+int
+Py_IsInitialized(void)
+{
+    return initialized;
+}
+
+/* Helper to allow an embedding application to override the normal
+ * mechanism that attempts to figure out an appropriate IO encoding
+ */
+
+static char *_Py_StandardStreamEncoding = NULL;
+static char *_Py_StandardStreamErrors = NULL;
+
+int
+Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
+{
+    if (Py_IsInitialized()) {
+        /* This is too late to have any effect */
+        return -1;
+    }
+    /* Can't call PyErr_NoMemory() on errors, as Python hasn't been
+     * initialised yet.
+     *
+     * However, the raw memory allocators are initialised appropriately
+     * as C static variables, so _PyMem_RawStrdup is OK even though
+     * Py_Initialize hasn't been called yet.
+     */
+    if (encoding) {
+        _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding);
+        if (!_Py_StandardStreamEncoding) {
+            return -2;
+        }
+    }
+    if (errors) {
+        _Py_StandardStreamErrors = _PyMem_RawStrdup(errors);
+        if (!_Py_StandardStreamErrors) {
+            if (_Py_StandardStreamEncoding) {
+                PyMem_RawFree(_Py_StandardStreamEncoding);
+            }
+            return -3;
+        }
+    }
+    return 0;
+}
+
+/* Global initializations.  Can be undone by Py_Finalize().  Don't
+   call this twice without an intervening Py_Finalize() call.  When
+   initializations fail, a fatal error is issued and the function does
+   not return.  On return, the first thread and interpreter state have
+   been created.
+
+   Locking: you must hold the interpreter lock while calling this.
+   (If the lock has not yet been initialized, that's equivalent to
+   having the lock, but you cannot use multiple threads.)
+
+*/
+
+static int
+add_flag(int flag, const char *envs)
+{
+    int env = atoi(envs);
+    if (flag < env)
+        flag = env;
+    if (flag < 1)
+        flag = 1;
+    return flag;
+}
+
+static char*
+get_codec_name(const char *encoding)
+{
+    char *name_utf8, *name_str;
+    PyObject *codec, *name = NULL;
+
+    codec = _PyCodec_Lookup(encoding);
+    if (!codec)
+        goto error;
+
+    name = _PyObject_GetAttrId(codec, &PyId_name);
+    Py_CLEAR(codec);
+    if (!name)
+        goto error;
+
+    name_utf8 = _PyUnicode_AsString(name);
+    if (name_utf8 == NULL)
+        goto error;
+    name_str = _PyMem_RawStrdup(name_utf8);
+    Py_DECREF(name);
+    if (name_str == NULL) {
+        PyErr_NoMemory();
+        return NULL;
+    }
+    return name_str;
+
+error:
+    Py_XDECREF(codec);
+    Py_XDECREF(name);
+    return NULL;
+}
+
+static char*
+get_locale_encoding(void)
+{
+#ifdef MS_WINDOWS
+    char codepage[100];
+    PyOS_snprintf(codepage, sizeof(codepage), "cp%d", GetACP());
+    return get_codec_name(codepage);
+#elif defined(HAVE_LANGINFO_H) && defined(CODESET)
+    char* codeset = nl_langinfo(CODESET);
+    if (!codeset || codeset[0] == '\0') {
+        PyErr_SetString(PyExc_ValueError, "CODESET is not set or empty");
+        return NULL;
+    }
+    return get_codec_name(codeset);
+#else
+    PyErr_SetNone(PyExc_NotImplementedError);
+    return NULL;
+#endif
+}
+
+static void
+import_init(PyInterpreterState *interp, PyObject *sysmod)
+{
+    PyObject *importlib;
+    PyObject *impmod;
+    PyObject *sys_modules;
+    PyObject *value;
+
+    /* Import _importlib through its frozen version, _frozen_importlib. */
+    if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
+        Py_FatalError("Py_Initialize: can't import _frozen_importlib");
+    }
+    else if (Py_VerboseFlag) {
+        PySys_FormatStderr("import _frozen_importlib # frozen\n");
+    }
+    importlib = PyImport_AddModule("_frozen_importlib");
+    if (importlib == NULL) {
+        Py_FatalError("Py_Initialize: couldn't get _frozen_importlib from "
+                      "sys.modules");
+    }
+    interp->importlib = importlib;
+    Py_INCREF(interp->importlib);
+
+    /* Install _importlib as __import__ */
+    impmod = PyInit_imp();
+    if (impmod == NULL) {
+        Py_FatalError("Py_Initialize: can't import imp");
+    }
+    else if (Py_VerboseFlag) {
+        PySys_FormatStderr("import imp # builtin\n");
+    }
+    sys_modules = PyImport_GetModuleDict();
+    if (Py_VerboseFlag) {
+        PySys_FormatStderr("import sys # builtin\n");
+    }
+    if (PyDict_SetItemString(sys_modules, "_imp", impmod) < 0) {
+        Py_FatalError("Py_Initialize: can't save _imp to sys.modules");
+    }
+
+    value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod);
+    if (value == NULL) {
+        PyErr_Print();
+        Py_FatalError("Py_Initialize: importlib install failed");
+    }
+    Py_DECREF(value);
+    Py_DECREF(impmod);
+
+    _PyImportZip_Init();
+}
+
+
+void
+_Py_InitializeEx_Private(int install_sigs, int install_importlib)
+{
+    PyInterpreterState *interp;
+    PyThreadState *tstate;
+    PyObject *bimod, *sysmod, *pstderr;
+    char *p;
+    extern void _Py_ReadyTypes(void);
+
+    if (initialized)
+        return;
+    initialized = 1;
+    _Py_Finalizing = NULL;
+
+#if defined(HAVE_LANGINFO_H) && defined(HAVE_SETLOCALE)
+    /* Set up the LC_CTYPE locale, so we can obtain
+       the locale's charset without having to switch
+       locales. */
+    setlocale(LC_CTYPE, "");
+#endif
+
+    if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0')
+        Py_DebugFlag = add_flag(Py_DebugFlag, p);
+    if ((p = Py_GETENV("PYTHONVERBOSE")) && *p != '\0')
+        Py_VerboseFlag = add_flag(Py_VerboseFlag, p);
+    if ((p = Py_GETENV("PYTHONOPTIMIZE")) && *p != '\0')
+        Py_OptimizeFlag = add_flag(Py_OptimizeFlag, p);
+    if ((p = Py_GETENV("PYTHONDONTWRITEBYTECODE")) && *p != '\0')
+        Py_DontWriteBytecodeFlag = add_flag(Py_DontWriteBytecodeFlag, p);
+    /* The variable is only tested for existence here; _PyRandom_Init will
+       check its value further. */
+    if ((p = Py_GETENV("PYTHONHASHSEED")) && *p != '\0')
+        Py_HashRandomizationFlag = add_flag(Py_HashRandomizationFlag, p);
+
+    _PyRandom_Init();
+
+    interp = PyInterpreterState_New();
+    if (interp == NULL)
+        Py_FatalError("Py_Initialize: can't make first interpreter");
+
+    tstate = PyThreadState_New(interp);
+    if (tstate == NULL)
+        Py_FatalError("Py_Initialize: can't make first thread");
+    (void) PyThreadState_Swap(tstate);
+
+#ifdef WITH_THREAD
+    /* We can't call _PyEval_FiniThreads() in Py_Finalize because
+       destroying the GIL might fail when it is being referenced from
+       another running thread (see issue #9901).
+       Instead we destroy the previously created GIL here, which ensures
+       that we can call Py_Initialize / Py_Finalize multiple times. */
+    _PyEval_FiniThreads();
+
+    /* Auto-thread-state API */
+    _PyGILState_Init(interp, tstate);
+#endif /* WITH_THREAD */
+
+    _Py_ReadyTypes();
+
+    if (!_PyFrame_Init())
+        Py_FatalError("Py_Initialize: can't init frames");
+
+    if (!_PyLong_Init())
+        Py_FatalError("Py_Initialize: can't init longs");
+
+    if (!PyByteArray_Init())
+        Py_FatalError("Py_Initialize: can't init bytearray");
+
+    if (!_PyFloat_Init())
+        Py_FatalError("Py_Initialize: can't init float");
+
+    interp->modules = PyDict_New();
+    if (interp->modules == NULL)
+        Py_FatalError("Py_Initialize: can't make modules dictionary");
+
+    /* Init Unicode implementation; relies on the codec registry */
+    if (_PyUnicode_Init() < 0)
+        Py_FatalError("Py_Initialize: can't initialize unicode");
+    if (_PyStructSequence_Init() < 0)
+        Py_FatalError("Py_Initialize: can't initialize structseq");
+
+    bimod = _PyBuiltin_Init();
+    if (bimod == NULL)
+        Py_FatalError("Py_Initialize: can't initialize builtins modules");
+    _PyImport_FixupBuiltin(bimod, "builtins");
+    interp->builtins = PyModule_GetDict(bimod);
+    if (interp->builtins == NULL)
+        Py_FatalError("Py_Initialize: can't initialize builtins dict");
+    Py_INCREF(interp->builtins);
+
+    /* initialize builtin exceptions */
+    _PyExc_Init(bimod);
+
+    sysmod = _PySys_Init();
+    if (sysmod == NULL)
+        Py_FatalError("Py_Initialize: can't initialize sys");
+    interp->sysdict = PyModule_GetDict(sysmod);
+    if (interp->sysdict == NULL)
+        Py_FatalError("Py_Initialize: can't initialize sys dict");
+    Py_INCREF(interp->sysdict);
+    _PyImport_FixupBuiltin(sysmod, "sys");
+    PySys_SetPath(Py_GetPath());
+    PyDict_SetItemString(interp->sysdict, "modules",
+                         interp->modules);
+
+    /* Set up a preliminary stderr printer until we have enough
+       infrastructure for the io module in place. */
+    pstderr = PyFile_NewStdPrinter(fileno(stderr));
+    if (pstderr == NULL)
+        Py_FatalError("Py_Initialize: can't set preliminary stderr");
+    _PySys_SetObjectId(&PyId_stderr, pstderr);
+    PySys_SetObject("__stderr__", pstderr);
+    Py_DECREF(pstderr);
+
+    _PyImport_Init();
+
+    _PyImportHooks_Init();
+
+    /* Initialize _warnings. */
+    _PyWarnings_Init();
+
+    if (!install_importlib)
+        return;
+
+    import_init(interp, sysmod);
+
+    /* initialize the faulthandler module */
+    if (_PyFaulthandler_Init())
+        Py_FatalError("Py_Initialize: can't initialize faulthandler");
+
+    if (_PyTime_Init() < 0)
+        Py_FatalError("Py_Initialize: can't initialize time");
+
+    if (initfsencoding(interp) < 0)
+        Py_FatalError("Py_Initialize: unable to load the file system codec");
+
+    if (install_sigs)
+        initsigs(); /* Signal handling stuff, including initintr() */
+
+    if (_PyTraceMalloc_Init() < 0)
+        Py_FatalError("Py_Initialize: can't initialize tracemalloc");
+
+    initmain(interp); /* Module __main__ */
+    if (initstdio() < 0)
+        Py_FatalError(
+            "Py_Initialize: can't initialize sys standard streams");
+
+    /* Initialize warnings. */
+    if (PySys_HasWarnOptions()) {
+        PyObject *warnings_module = PyImport_ImportModule("warnings");
+        if (warnings_module == NULL) {
+            fprintf(stderr, "'import warnings' failed; traceback:\n");
+            PyErr_Print();
+        }
+        Py_XDECREF(warnings_module);
+    }
+
+    if (!Py_NoSiteFlag)
+        initsite(); /* Module site */
+}
+
+void
+Py_InitializeEx(int install_sigs)
+{
+    _Py_InitializeEx_Private(install_sigs, 1);
+}
+
+void
+Py_Initialize(void)
+{
+    Py_InitializeEx(1);
+}
+
+
+#ifdef COUNT_ALLOCS
+extern void dump_counts(FILE*);
+#endif
+
+/* Flush stdout and stderr */
+
+static int
+file_is_closed(PyObject *fobj)
+{
+    int r;
+    PyObject *tmp = PyObject_GetAttrString(fobj, "closed");
+    if (tmp == NULL) {
+        PyErr_Clear();
+        return 0;
+    }
+    r = PyObject_IsTrue(tmp);
+    Py_DECREF(tmp);
+    if (r < 0)
+        PyErr_Clear();
+    return r > 0;
+}
+
+static void
+flush_std_files(void)
+{
+    PyObject *fout = _PySys_GetObjectId(&PyId_stdout);
+    PyObject *ferr = _PySys_GetObjectId(&PyId_stderr);
+    PyObject *tmp;
+
+    if (fout != NULL && fout != Py_None && !file_is_closed(fout)) {
+        tmp = _PyObject_CallMethodId(fout, &PyId_flush, "");
+        if (tmp == NULL)
+            PyErr_WriteUnraisable(fout);
+        else
+            Py_DECREF(tmp);
+    }
+
+    if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) {
+        tmp = _PyObject_CallMethodId(ferr, &PyId_flush, "");
+        if (tmp == NULL)
+            PyErr_Clear();
+        else
+            Py_DECREF(tmp);
+    }
+}
+
+/* Undo the effect of Py_Initialize().
+
+   Beware: if multiple interpreter and/or thread states exist, these
+   are not wiped out; only the current thread and interpreter state
+   are deleted.  But since everything else is deleted, those other
+   interpreter and thread states should no longer be used.
+
+   (XXX We should do better, e.g. wipe out all interpreters and
+   threads.)
+
+   Locking: as above.
+
+*/
+
+void
+Py_Finalize(void)
+{
+    PyInterpreterState *interp;
+    PyThreadState *tstate;
+
+    if (!initialized)
+        return;
+
+    wait_for_thread_shutdown();
+
+    /* The interpreter is still entirely intact at this point, and the
+     * exit funcs may be relying on that.  In particular, if some thread
+     * or exit func is still waiting to do an import, the import machinery
+     * expects Py_IsInitialized() to return true.  So don't say the
+     * interpreter is uninitialized until after the exit funcs have run.
+     * Note that Threading.py uses an exit func to do a join on all the
+     * threads created thru it, so this also protects pending imports in
+     * the threads created via Threading.
+     */
+    call_py_exitfuncs();
+
+    /* Get current thread state and interpreter pointer */
+    tstate = PyThreadState_GET();
+    interp = tstate->interp;
+
+    /* Remaining threads (e.g. daemon threads) will automatically exit
+       after taking the GIL (in PyEval_RestoreThread()). */
+    _Py_Finalizing = tstate;
+    initialized = 0;
+
+    /* Flush stdout+stderr */
+    flush_std_files();
+
+    /* Disable signal handling */
+    PyOS_FiniInterrupts();
+
+    /* Collect garbage.  This may call finalizers; it's nice to call these
+     * before all modules are destroyed.
+     * XXX If a __del__ or weakref callback is triggered here, and tries to
+     * XXX import a module, bad things can happen, because Python no
+     * XXX longer believes it's initialized.
+     * XXX     Fatal Python error: Interpreter not initialized (version mismatch?)
+     * XXX is easy to provoke that way.  I've also seen, e.g.,
+     * XXX     Exception exceptions.ImportError: 'No module named sha'
+     * XXX         in <function callback at 0x008F5718> ignored
+     * XXX but I'm unclear on exactly how that one happens.  In any case,
+     * XXX I haven't seen a real-life report of either of these.
+     */
+    PyGC_Collect();
+#ifdef COUNT_ALLOCS
+    /* With COUNT_ALLOCS, it helps to run GC multiple times:
+       each collection might release some types from the type
+       list, so they become garbage. */
+    while (PyGC_Collect() > 0)
+        /* nothing */;
+#endif
+    /* Destroy all modules */
+    PyImport_Cleanup();
+
+    /* Flush stdout+stderr (again, in case more was printed) */
+    flush_std_files();
+
+    /* Collect final garbage.  This disposes of cycles created by
+     * class definitions, for example.
+     * XXX This is disabled because it caused too many problems.  If
+     * XXX a __del__ or weakref callback triggers here, Python code has
+     * XXX a hard time running, because even the sys module has been
+     * XXX cleared out (sys.stdout is gone, sys.excepthook is gone, etc).
+     * XXX One symptom is a sequence of information-free messages
+     * XXX coming from threads (if a __del__ or callback is invoked,
+     * XXX other threads can execute too, and any exception they encounter
+     * XXX triggers a comedy of errors as subsystem after subsystem
+     * XXX fails to find what it *expects* to find in sys to help report
+     * XXX the exception and consequent unexpected failures).  I've also
+     * XXX seen segfaults then, after adding print statements to the
+     * XXX Python code getting called.
+     */
+#if 0
+    PyGC_Collect();
+#endif
+
+    /* Disable tracemalloc after all Python objects have been destroyed,
+       so it is possible to use tracemalloc in objects destructor. */
+    _PyTraceMalloc_Fini();
+
+    /* Destroy the database used by _PyImport_{Fixup,Find}Extension */
+    _PyImport_Fini();
+
+    /* Cleanup typeobject.c's internal caches. */
+    _PyType_Fini();
+
+    /* unload faulthandler module */
+    _PyFaulthandler_Fini();
+
+    /* Debugging stuff */
+#ifdef COUNT_ALLOCS
+    dump_counts(stdout);
+#endif
+    /* dump hash stats */
+    _PyHash_Fini();
+
+    _PY_DEBUG_PRINT_TOTAL_REFS();
+
+#ifdef Py_TRACE_REFS
+    /* Display all objects still alive -- this can invoke arbitrary
+     * __repr__ overrides, so requires a mostly-intact interpreter.
+     * Alas, a lot of stuff may still be alive now that will be cleaned
+     * up later.
+     */
+    if (Py_GETENV("PYTHONDUMPREFS"))
+        _Py_PrintReferences(stderr);
+#endif /* Py_TRACE_REFS */
+
+    /* Clear interpreter state and all thread states. */
+    PyInterpreterState_Clear(interp);
+
+    /* Now we decref the exception classes.  After this point nothing
+       can raise an exception.  That's okay, because each Fini() method
+       below has been checked to make sure no exceptions are ever
+       raised.
+    */
+
+    _PyExc_Fini();
+
+    /* Sundry finalizers */
+    PyMethod_Fini();
+    PyFrame_Fini();
+    PyCFunction_Fini();
+    PyTuple_Fini();
+    PyList_Fini();
+    PySet_Fini();
+    PyBytes_Fini();
+    PyByteArray_Fini();
+    PyLong_Fini();
+    PyFloat_Fini();
+    PyDict_Fini();
+    PySlice_Fini();
+    _PyGC_Fini();
+    _PyRandom_Fini();
+
+    /* Cleanup Unicode implementation */
+    _PyUnicode_Fini();
+
+    /* reset file system default encoding */
+    if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
+        PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
+        Py_FileSystemDefaultEncoding = NULL;
+    }
+
+    /* XXX Still allocated:
+       - various static ad-hoc pointers to interned strings
+       - int and float free list blocks
+       - whatever various modules and libraries allocate
+    */
+
+    PyGrammar_RemoveAccelerators(&_PyParser_Grammar);
+
+    /* Cleanup auto-thread-state */
+#ifdef WITH_THREAD
+    _PyGILState_Fini();
+#endif /* WITH_THREAD */
+
+    /* Delete current thread. After this, many C API calls become crashy. */
+    PyThreadState_Swap(NULL);
+    PyInterpreterState_Delete(interp);
+
+#ifdef Py_TRACE_REFS
+    /* Display addresses (& refcnts) of all objects still alive.
+     * An address can be used to find the repr of the object, printed
+     * above by _Py_PrintReferences.
+     */
+    if (Py_GETENV("PYTHONDUMPREFS"))
+        _Py_PrintReferenceAddresses(stderr);
+#endif /* Py_TRACE_REFS */
+#ifdef PYMALLOC_DEBUG
+    if (Py_GETENV("PYTHONMALLOCSTATS"))
+        _PyObject_DebugMallocStats(stderr);
+#endif
+
+    call_ll_exitfuncs();
+}
+
+/* Create and initialize a new interpreter and thread, and return the
+   new thread.  This requires that Py_Initialize() has been called
+   first.
+
+   Unsuccessful initialization yields a NULL pointer.  Note that *no*
+   exception information is available even in this case -- the
+   exception information is held in the thread, and there is no
+   thread.
+
+   Locking: as above.
+
+*/
+
+PyThreadState *
+Py_NewInterpreter(void)
+{
+    PyInterpreterState *interp;
+    PyThreadState *tstate, *save_tstate;
+    PyObject *bimod, *sysmod;
+
+    if (!initialized)
+        Py_FatalError("Py_NewInterpreter: call Py_Initialize first");
+
+    interp = PyInterpreterState_New();
+    if (interp == NULL)
+        return NULL;
+
+    tstate = PyThreadState_New(interp);
+    if (tstate == NULL) {
+        PyInterpreterState_Delete(interp);
+        return NULL;
+    }
+
+    save_tstate = PyThreadState_Swap(tstate);
+
+    /* XXX The following is lax in error checking */
+
+    interp->modules = PyDict_New();
+
+    bimod = _PyImport_FindBuiltin("builtins");
+    if (bimod != NULL) {
+        interp->builtins = PyModule_GetDict(bimod);
+        if (interp->builtins == NULL)
+            goto handle_error;
+        Py_INCREF(interp->builtins);
+    }
+
+    /* initialize builtin exceptions */
+    _PyExc_Init(bimod);
+
+    sysmod = _PyImport_FindBuiltin("sys");
+    if (bimod != NULL && sysmod != NULL) {
+        PyObject *pstderr;
+
+        interp->sysdict = PyModule_GetDict(sysmod);
+        if (interp->sysdict == NULL)
+            goto handle_error;
+        Py_INCREF(interp->sysdict);
+        PySys_SetPath(Py_GetPath());
+        PyDict_SetItemString(interp->sysdict, "modules",
+                             interp->modules);
+        /* Set up a preliminary stderr printer until we have enough
+           infrastructure for the io module in place. */
+        pstderr = PyFile_NewStdPrinter(fileno(stderr));
+        if (pstderr == NULL)
+            Py_FatalError("Py_Initialize: can't set preliminary stderr");
+        _PySys_SetObjectId(&PyId_stderr, pstderr);
+        PySys_SetObject("__stderr__", pstderr);
+        Py_DECREF(pstderr);
+
+        _PyImportHooks_Init();
+
+        import_init(interp, sysmod);
+
+        if (initfsencoding(interp) < 0)
+            goto handle_error;
+
+        if (initstdio() < 0)
+            Py_FatalError(
+            "Py_Initialize: can't initialize sys standard streams");
+        initmain(interp);
+        if (!Py_NoSiteFlag)
+            initsite();
+    }
+
+    if (!PyErr_Occurred())
+        return tstate;
+
+handle_error:
+    /* Oops, it didn't work.  Undo it all. */
+
+    PyErr_PrintEx(0);
+    PyThreadState_Clear(tstate);
+    PyThreadState_Swap(save_tstate);
+    PyThreadState_Delete(tstate);
+    PyInterpreterState_Delete(interp);
+
+    return NULL;
+}
+
+/* Delete an interpreter and its last thread.  This requires that the
+   given thread state is current, that the thread has no remaining
+   frames, and that it is its interpreter's only remaining thread.
+   It is a fatal error to violate these constraints.
+
+   (Py_Finalize() doesn't have these constraints -- it zaps
+   everything, regardless.)
+
+   Locking: as above.
+
+*/
+
+void
+Py_EndInterpreter(PyThreadState *tstate)
+{
+    PyInterpreterState *interp = tstate->interp;
+
+    if (tstate != PyThreadState_GET())
+        Py_FatalError("Py_EndInterpreter: thread is not current");
+    if (tstate->frame != NULL)
+        Py_FatalError("Py_EndInterpreter: thread still has a frame");
+
+    wait_for_thread_shutdown();
+
+    if (tstate != interp->tstate_head || tstate->next != NULL)
+        Py_FatalError("Py_EndInterpreter: not the last thread");
+
+    PyImport_Cleanup();
+    PyInterpreterState_Clear(interp);
+    PyThreadState_Swap(NULL);
+    PyInterpreterState_Delete(interp);
+}
+
+#ifdef MS_WINDOWS
+static wchar_t *progname = L"python";
+#else
+static wchar_t *progname = L"python3";
+#endif
+
+void
+Py_SetProgramName(wchar_t *pn)
+{
+    if (pn && *pn)
+        progname = pn;
+}
+
+wchar_t *
+Py_GetProgramName(void)
+{
+    return progname;
+}
+
+static wchar_t *default_home = NULL;
+static wchar_t env_home[MAXPATHLEN+1];
+
+void
+Py_SetPythonHome(wchar_t *home)
+{
+    default_home = home;
+}
+
+wchar_t *
+Py_GetPythonHome(void)
+{
+    wchar_t *home = default_home;
+    if (home == NULL && !Py_IgnoreEnvironmentFlag) {
+        char* chome = Py_GETENV("PYTHONHOME");
+        if (chome) {
+            size_t size = Py_ARRAY_LENGTH(env_home);
+            size_t r = mbstowcs(env_home, chome, size);
+            if (r != (size_t)-1 && r < size)
+                home = env_home;
+        }
+
+    }
+    return home;
+}
+
+/* Create __main__ module */
+
+static void
+initmain(PyInterpreterState *interp)
+{
+    PyObject *m, *d, *loader;
+    m = PyImport_AddModule("__main__");
+    if (m == NULL)
+        Py_FatalError("can't create __main__ module");
+    d = PyModule_GetDict(m);
+    if (PyDict_GetItemString(d, "__builtins__") == NULL) {
+        PyObject *bimod = PyImport_ImportModule("builtins");
+        if (bimod == NULL) {
+            Py_FatalError("Failed to retrieve builtins module");
+        }
+        if (PyDict_SetItemString(d, "__builtins__", bimod) < 0) {
+            Py_FatalError("Failed to initialize __main__.__builtins__");
+        }
+        Py_DECREF(bimod);
+    }
+    /* Main is a little special - imp.is_builtin("__main__") will return
+     * False, but BuiltinImporter is still the most appropriate initial
+     * setting for its __loader__ attribute. A more suitable value will
+     * be set if __main__ gets further initialized later in the startup
+     * process.
+     */
+    loader = PyDict_GetItemString(d, "__loader__");
+    if (loader == NULL || loader == Py_None) {
+        PyObject *loader = PyObject_GetAttrString(interp->importlib,
+                                                  "BuiltinImporter");
+        if (loader == NULL) {
+            Py_FatalError("Failed to retrieve BuiltinImporter");
+        }
+        if (PyDict_SetItemString(d, "__loader__", loader) < 0) {
+            Py_FatalError("Failed to initialize __main__.__loader__");
+        }
+        Py_DECREF(loader);
+    }
+}
+
+static int
+initfsencoding(PyInterpreterState *interp)
+{
+    PyObject *codec;
+
+    if (Py_FileSystemDefaultEncoding == NULL)
+    {
+        Py_FileSystemDefaultEncoding = get_locale_encoding();
+        if (Py_FileSystemDefaultEncoding == NULL)
+            Py_FatalError("Py_Initialize: Unable to get the locale encoding");
+
+        Py_HasFileSystemDefaultEncoding = 0;
+        interp->fscodec_initialized = 1;
+        return 0;
+    }
+
+    /* the encoding is mbcs, utf-8 or ascii */
+    codec = _PyCodec_Lookup(Py_FileSystemDefaultEncoding);
+    if (!codec) {
+        /* Such error can only occurs in critical situations: no more
+         * memory, import a module of the standard library failed,
+         * etc. */
+        return -1;
+    }
+    Py_DECREF(codec);
+    interp->fscodec_initialized = 1;
+    return 0;
+}
+
+/* Import the site module (not into __main__ though) */
+
+static void
+initsite(void)
+{
+    PyObject *m;
+    m = PyImport_ImportModule("site");
+    if (m == NULL) {
+        fprintf(stderr, "Failed to import the site module\n");
+        PyErr_Print();
+        Py_Finalize();
+        exit(1);
+    }
+    else {
+        Py_DECREF(m);
+    }
+}
+
+static PyObject*
+create_stdio(PyObject* io,
+    int fd, int write_mode, char* name,
+    char* encoding, char* errors)
+{
+    PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res;
+    const char* mode;
+    const char* newline;
+    PyObject *line_buffering;
+    int buffering, isatty;
+    _Py_IDENTIFIER(open);
+    _Py_IDENTIFIER(isatty);
+    _Py_IDENTIFIER(TextIOWrapper);
+    _Py_IDENTIFIER(mode);
+
+    /* stdin is always opened in buffered mode, first because it shouldn't
+       make a difference in common use cases, second because TextIOWrapper
+       depends on the presence of a read1() method which only exists on
+       buffered streams.
+    */
+    if (Py_UnbufferedStdioFlag && write_mode)
+        buffering = 0;
+    else
+        buffering = -1;
+    if (write_mode)
+        mode = "wb";
+    else
+        mode = "rb";
+    buf = _PyObject_CallMethodId(io, &PyId_open, "isiOOOi",
+                                 fd, mode, buffering,
+                                 Py_None, Py_None, Py_None, 0);
+    if (buf == NULL)
+        goto error;
+
+    if (buffering) {
+        _Py_IDENTIFIER(raw);
+        raw = _PyObject_GetAttrId(buf, &PyId_raw);
+        if (raw == NULL)
+            goto error;
+    }
+    else {
+        raw = buf;
+        Py_INCREF(raw);
+    }
+
+    text = PyUnicode_FromString(name);
+    if (text == NULL || _PyObject_SetAttrId(raw, &PyId_name, text) < 0)
+        goto error;
+    res = _PyObject_CallMethodId(raw, &PyId_isatty, "");
+    if (res == NULL)
+        goto error;
+    isatty = PyObject_IsTrue(res);
+    Py_DECREF(res);
+    if (isatty == -1)
+        goto error;
+    if (isatty || Py_UnbufferedStdioFlag)
+        line_buffering = Py_True;
+    else
+        line_buffering = Py_False;
+
+    Py_CLEAR(raw);
+    Py_CLEAR(text);
+
+#ifdef MS_WINDOWS
+    /* sys.stdin: enable universal newline mode, translate "\r\n" and "\r"
+       newlines to "\n".
+       sys.stdout and sys.stderr: translate "\n" to "\r\n". */
+    newline = NULL;
+#else
+    /* sys.stdin: split lines at "\n".
+       sys.stdout and sys.stderr: don't translate newlines (use "\n"). */
+    newline = "\n";
+#endif
+
+    stream = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "OsssO",
+                                    buf, encoding, errors,
+                                    newline, line_buffering);
+    Py_CLEAR(buf);
+    if (stream == NULL)
+        goto error;
+
+    if (write_mode)
+        mode = "w";
+    else
+        mode = "r";
+    text = PyUnicode_FromString(mode);
+    if (!text || _PyObject_SetAttrId(stream, &PyId_mode, text) < 0)
+        goto error;
+    Py_CLEAR(text);
+    return stream;
+
+error:
+    Py_XDECREF(buf);
+    Py_XDECREF(stream);
+    Py_XDECREF(text);
+    Py_XDECREF(raw);
+    return NULL;
+}
+
+static int
+is_valid_fd(int fd)
+{
+    int dummy_fd;
+    if (fd < 0 || !_PyVerify_fd(fd))
+        return 0;
+    dummy_fd = dup(fd);
+    if (dummy_fd < 0)
+        return 0;
+    close(dummy_fd);
+    return 1;
+}
+
+/* Initialize sys.stdin, stdout, stderr and builtins.open */
+static int
+initstdio(void)
+{
+    PyObject *iomod = NULL, *wrapper;
+    PyObject *bimod = NULL;
+    PyObject *m;
+    PyObject *std = NULL;
+    int status = 0, fd;
+    PyObject * encoding_attr;
+    char *pythonioencoding = NULL, *encoding, *errors;
+
+    /* Hack to avoid a nasty recursion issue when Python is invoked
+       in verbose mode: pre-import the Latin-1 and UTF-8 codecs */
+    if ((m = PyImport_ImportModule("encodings.utf_8")) == NULL) {
+        goto error;
+    }
+    Py_DECREF(m);
+
+    if (!(m = PyImport_ImportModule("encodings.latin_1"))) {
+        goto error;
+    }
+    Py_DECREF(m);
+
+    if (!(bimod = PyImport_ImportModule("builtins"))) {
+        goto error;
+    }
+
+    if (!(iomod = PyImport_ImportModule("io"))) {
+        goto error;
+    }
+    if (!(wrapper = PyObject_GetAttrString(iomod, "OpenWrapper"))) {
+        goto error;
+    }
+
+    /* Set builtins.open */
+    if (PyObject_SetAttrString(bimod, "open", wrapper) == -1) {
+        Py_DECREF(wrapper);
+        goto error;
+    }
+    Py_DECREF(wrapper);
+
+    encoding = _Py_StandardStreamEncoding;
+    errors = _Py_StandardStreamErrors;
+    if (!encoding || !errors) {
+        if (!errors) {
+            /* When the LC_CTYPE locale is the POSIX locale ("C locale"),
+               stdin and stdout use the surrogateescape error handler by
+               default, instead of the strict error handler. */
+            char *loc = setlocale(LC_CTYPE, NULL);
+            if (loc != NULL && strcmp(loc, "C") == 0)
+                errors = "surrogateescape";
+        }
+
+        pythonioencoding = Py_GETENV("PYTHONIOENCODING");
+        if (pythonioencoding) {
+            char *err;
+            pythonioencoding = _PyMem_Strdup(pythonioencoding);
+            if (pythonioencoding == NULL) {
+                PyErr_NoMemory();
+                goto error;
+            }
+            err = strchr(pythonioencoding, ':');
+            if (err) {
+                *err = '\0';
+                err++;
+                if (*err && !_Py_StandardStreamErrors) {
+                    errors = err;
+                }
+            }
+            if (*pythonioencoding && !encoding) {
+                encoding = pythonioencoding;
+            }
+        }
+    }
+
+    /* Set sys.stdin */
+    fd = fileno(stdin);
+    /* Under some conditions stdin, stdout and stderr may not be connected
+     * and fileno() may point to an invalid file descriptor. For example
+     * GUI apps don't have valid standard streams by default.
+     */
+    if (!is_valid_fd(fd)) {
+        std = Py_None;
+        Py_INCREF(std);
+    }
+    else {
+        std = create_stdio(iomod, fd, 0, "<stdin>", encoding, errors);
+        if (std == NULL)
+            goto error;
+    } /* if (fd < 0) */
+    PySys_SetObject("__stdin__", std);
+    _PySys_SetObjectId(&PyId_stdin, std);
+    Py_DECREF(std);
+
+    /* Set sys.stdout */
+    fd = fileno(stdout);
+    if (!is_valid_fd(fd)) {
+        std = Py_None;
+        Py_INCREF(std);
+    }
+    else {
+        std = create_stdio(iomod, fd, 1, "<stdout>", encoding, errors);
+        if (std == NULL)
+            goto error;
+    } /* if (fd < 0) */
+    PySys_SetObject("__stdout__", std);
+    _PySys_SetObjectId(&PyId_stdout, std);
+    Py_DECREF(std);
+
+#if 1 /* Disable this if you have trouble debugging bootstrap stuff */
+    /* Set sys.stderr, replaces the preliminary stderr */
+    fd = fileno(stderr);
+    if (!is_valid_fd(fd)) {
+        std = Py_None;
+        Py_INCREF(std);
+    }
+    else {
+        std = create_stdio(iomod, fd, 1, "<stderr>", encoding, "backslashreplace");
+        if (std == NULL)
+            goto error;
+    } /* if (fd < 0) */
+
+    /* Same as hack above, pre-import stderr's codec to avoid recursion
+       when import.c tries to write to stderr in verbose mode. */
+    encoding_attr = PyObject_GetAttrString(std, "encoding");
+    if (encoding_attr != NULL) {
+        const char * std_encoding;
+        std_encoding = _PyUnicode_AsString(encoding_attr);
+        if (std_encoding != NULL) {
+            PyObject *codec_info = _PyCodec_Lookup(std_encoding);
+            Py_XDECREF(codec_info);
+        }
+        Py_DECREF(encoding_attr);
+    }
+    PyErr_Clear();  /* Not a fatal error if codec isn't available */
+
+    if (PySys_SetObject("__stderr__", std) < 0) {
+        Py_DECREF(std);
+        goto error;
+    }
+    if (_PySys_SetObjectId(&PyId_stderr, std) < 0) {
+        Py_DECREF(std);
+        goto error;
+    }
+    Py_DECREF(std);
+#endif
+
+    if (0) {
+  error:
+        status = -1;
+    }
+
+    /* We won't need them anymore. */
+    if (_Py_StandardStreamEncoding) {
+        PyMem_RawFree(_Py_StandardStreamEncoding);
+        _Py_StandardStreamEncoding = NULL;
+    }
+    if (_Py_StandardStreamErrors) {
+        PyMem_RawFree(_Py_StandardStreamErrors);
+        _Py_StandardStreamErrors = NULL;
+    }
+    PyMem_Free(pythonioencoding);
+    Py_XDECREF(bimod);
+    Py_XDECREF(iomod);
+    return status;
+}
+
+
+/* Print fatal error message and abort */
+
+void
+Py_FatalError(const char *msg)
+{
+    const int fd = fileno(stderr);
+    PyThreadState *tstate;
+
+    fprintf(stderr, "Fatal Python error: %s\n", msg);
+    fflush(stderr); /* it helps in Windows debug build */
+    if (PyErr_Occurred()) {
+        PyErr_PrintEx(0);
+    }
+    else {
+        tstate = _Py_atomic_load_relaxed(&_PyThreadState_Current);
+        if (tstate != NULL) {
+            fputc('\n', stderr);
+            fflush(stderr);
+            _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
+        }
+        _PyFaulthandler_Fini();
+    }
+
+#ifdef MS_WINDOWS
+    {
+        size_t len = strlen(msg);
+        WCHAR* buffer;
+        size_t i;
+
+        /* Convert the message to wchar_t. This uses a simple one-to-one
+        conversion, assuming that the this error message actually uses ASCII
+        only. If this ceases to be true, we will have to convert. */
+        buffer = alloca( (len+1) * (sizeof *buffer));
+        for( i=0; i<=len; ++i)
+            buffer[i] = msg[i];
+        OutputDebugStringW(L"Fatal Python error: ");
+        OutputDebugStringW(buffer);
+        OutputDebugStringW(L"\n");
+    }
+#ifdef _DEBUG
+    DebugBreak();
+#endif
+#endif /* MS_WINDOWS */
+    abort();
+}
+
+/* Clean up and exit */
+
+#ifdef WITH_THREAD
+#include "pythread.h"
+#endif
+
+static void (*pyexitfunc)(void) = NULL;
+/* For the atexit module. */
+void _Py_PyAtExit(void (*func)(void))
+{
+    pyexitfunc = func;
+}
+
+static void
+call_py_exitfuncs(void)
+{
+    if (pyexitfunc == NULL)
+        return;
+
+    (*pyexitfunc)();
+    PyErr_Clear();
+}
+
+/* Wait until threading._shutdown completes, provided
+   the threading module was imported in the first place.
+   The shutdown routine will wait until all non-daemon
+   "threading" threads have completed. */
+static void
+wait_for_thread_shutdown(void)
+{
+#ifdef WITH_THREAD
+    _Py_IDENTIFIER(_shutdown);
+    PyObject *result;
+    PyThreadState *tstate = PyThreadState_GET();
+    PyObject *threading = PyMapping_GetItemString(tstate->interp->modules,
+                                                  "threading");
+    if (threading == NULL) {
+        /* threading not imported */
+        PyErr_Clear();
+        return;
+    }
+    result = _PyObject_CallMethodId(threading, &PyId__shutdown, "");
+    if (result == NULL) {
+        PyErr_WriteUnraisable(threading);
+    }
+    else {
+        Py_DECREF(result);
+    }
+    Py_DECREF(threading);
+#endif
+}
+
+#define NEXITFUNCS 32
+static void (*exitfuncs[NEXITFUNCS])(void);
+static int nexitfuncs = 0;
+
+int Py_AtExit(void (*func)(void))
+{
+    if (nexitfuncs >= NEXITFUNCS)
+        return -1;
+    exitfuncs[nexitfuncs++] = func;
+    return 0;
+}
+
+static void
+call_ll_exitfuncs(void)
+{
+    while (nexitfuncs > 0)
+        (*exitfuncs[--nexitfuncs])();
+
+    fflush(stdout);
+    fflush(stderr);
+}
+
+void
+Py_Exit(int sts)
+{
+    Py_Finalize();
+
+    exit(sts);
+}
+
+static void
+initsigs(void)
+{
+#ifdef SIGPIPE
+    PyOS_setsig(SIGPIPE, SIG_IGN);
+#endif
+#ifdef SIGXFZ
+    PyOS_setsig(SIGXFZ, SIG_IGN);
+#endif
+#ifdef SIGXFSZ
+    PyOS_setsig(SIGXFSZ, SIG_IGN);
+#endif
+    PyOS_InitInterrupts(); /* May imply initsignal() */
+    if (PyErr_Occurred()) {
+        Py_FatalError("Py_Initialize: can't import signal");
+    }
+}
+
+
+/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL.
+ *
+ * All of the code in this function must only use async-signal-safe functions,
+ * listed at `man 7 signal` or
+ * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
+ */
+void
+_Py_RestoreSignals(void)
+{
+#ifdef SIGPIPE
+    PyOS_setsig(SIGPIPE, SIG_DFL);
+#endif
+#ifdef SIGXFZ
+    PyOS_setsig(SIGXFZ, SIG_DFL);
+#endif
+#ifdef SIGXFSZ
+    PyOS_setsig(SIGXFSZ, SIG_DFL);
+#endif
+}
+
+
+/*
+ * The file descriptor fd is considered ``interactive'' if either
+ *   a) isatty(fd) is TRUE, or
+ *   b) the -i flag was given, and the filename associated with
+ *      the descriptor is NULL or "<stdin>" or "???".
+ */
+int
+Py_FdIsInteractive(FILE *fp, const char *filename)
+{
+    if (isatty((int)fileno(fp)))
+        return 1;
+    if (!Py_InteractiveFlag)
+        return 0;
+    return (filename == NULL) ||
+           (strcmp(filename, "<stdin>") == 0) ||
+           (strcmp(filename, "???") == 0);
+}
+
+
+#if defined(USE_STACKCHECK)
+#if defined(WIN32) && defined(_MSC_VER)
+
+/* Stack checking for Microsoft C */
+
+#include <malloc.h>
+#include <excpt.h>
+
+/*
+ * Return non-zero when we run out of memory on the stack; zero otherwise.
+ */
+int
+PyOS_CheckStack(void)
+{
+    __try {
+        /* alloca throws a stack overflow exception if there's
+           not enough space left on the stack */
+        alloca(PYOS_STACK_MARGIN * sizeof(void*));
+        return 0;
+    } __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ?
+                    EXCEPTION_EXECUTE_HANDLER :
+            EXCEPTION_CONTINUE_SEARCH) {
+        int errcode = _resetstkoflw();
+        if (errcode == 0)
+        {
+            Py_FatalError("Could not reset the stack!");
+        }
+    }
+    return 1;
+}
+
+#endif /* WIN32 && _MSC_VER */
+
+/* Alternate implementations can be added here... */
+
+#endif /* USE_STACKCHECK */
+
+
+/* Wrappers around sigaction() or signal(). */
+
+PyOS_sighandler_t
+PyOS_getsig(int sig)
+{
+#ifdef HAVE_SIGACTION
+    struct sigaction context;
+    if (sigaction(sig, NULL, &context) == -1)
+        return SIG_ERR;
+    return context.sa_handler;
+#else
+    PyOS_sighandler_t handler;
+/* Special signal handling for the secure CRT in Visual Studio 2005 */
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+    switch (sig) {
+    /* Only these signals are valid */
+    case SIGINT:
+    case SIGILL:
+    case SIGFPE:
+    case SIGSEGV:
+    case SIGTERM:
+    case SIGBREAK:
+    case SIGABRT:
+        break;
+    /* Don't call signal() with other values or it will assert */
+    default:
+        return SIG_ERR;
+    }
+#endif /* _MSC_VER && _MSC_VER >= 1400 */
+    handler = signal(sig, SIG_IGN);
+    if (handler != SIG_ERR)
+        signal(sig, handler);
+    return handler;
+#endif
+}
+
+/*
+ * All of the code in this function must only use async-signal-safe functions,
+ * listed at `man 7 signal` or
+ * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
+ */
+PyOS_sighandler_t
+PyOS_setsig(int sig, PyOS_sighandler_t handler)
+{
+#ifdef HAVE_SIGACTION
+    /* Some code in Modules/signalmodule.c depends on sigaction() being
+     * used here if HAVE_SIGACTION is defined.  Fix that if this code
+     * changes to invalidate that assumption.
+     */
+    struct sigaction context, ocontext;
+    context.sa_handler = handler;
+    sigemptyset(&context.sa_mask);
+    context.sa_flags = 0;
+    if (sigaction(sig, &context, &ocontext) == -1)
+        return SIG_ERR;
+    return ocontext.sa_handler;
+#else
+    PyOS_sighandler_t oldhandler;
+    oldhandler = signal(sig, handler);
+#ifdef HAVE_SIGINTERRUPT
+    siginterrupt(sig, 1);
+#endif
+    return oldhandler;
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -40,7 +40,6 @@
 _Py_IDENTIFIER(last_traceback);
 _Py_IDENTIFIER(last_type);
 _Py_IDENTIFIER(last_value);
-_Py_IDENTIFIER(name);
 _Py_IDENTIFIER(ps1);
 _Py_IDENTIFIER(ps2);
 _Py_IDENTIFIER(stdin);
@@ -48,43 +47,13 @@
 _Py_IDENTIFIER(stderr);
 _Py_static_string(PyId_string, "<string>");
 
-#ifdef Py_REF_DEBUG
-static
-void _print_total_refs(void) {
-    PyObject *xoptions, *value;
-    _Py_IDENTIFIER(showrefcount);
-
-    xoptions = PySys_GetXOptions();
-    if (xoptions == NULL)
-        return;
-    value = _PyDict_GetItemId(xoptions, &PyId_showrefcount);
-    if (value == Py_True)
-        fprintf(stderr,
-                "[%" PY_FORMAT_SIZE_T "d refs, "
-                "%" PY_FORMAT_SIZE_T "d blocks]\n",
-                _Py_GetRefTotal(), _Py_GetAllocatedBlocks());
-}
-#endif
-
-#ifndef Py_REF_DEBUG
-#define PRINT_TOTAL_REFS()
-#else /* Py_REF_DEBUG */
-#define PRINT_TOTAL_REFS() _print_total_refs()
-#endif
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-extern wchar_t *Py_GetPath(void);
-
 extern grammar _PyParser_Grammar; /* From graminit.c */
 
 /* Forward */
-static void initmain(PyInterpreterState *interp);
-static int initfsencoding(PyInterpreterState *interp);
-static void initsite(void);
-static int initstdio(void);
 static void flush_io(void);
 static PyObject *run_mod(mod_ty, PyObject *, PyObject *, PyObject *,
                           PyCompilerFlags *, PyArena *);
@@ -92,1192 +61,6 @@
                               PyCompilerFlags *);
 static void err_input(perrdetail *);
 static void err_free(perrdetail *);
-static void initsigs(void);
-static void call_py_exitfuncs(void);
-static void wait_for_thread_shutdown(void);
-static void call_ll_exitfuncs(void);
-extern int _PyUnicode_Init(void);
-extern int _PyStructSequence_Init(void);
-extern void _PyUnicode_Fini(void);
-extern int _PyLong_Init(void);
-extern void PyLong_Fini(void);
-extern int _PyFaulthandler_Init(void);
-extern void _PyFaulthandler_Fini(void);
-extern void _PyHash_Fini(void);
-extern int _PyTraceMalloc_Init(void);
-extern int _PyTraceMalloc_Fini(void);
-
-#ifdef WITH_THREAD
-extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *);
-extern void _PyGILState_Fini(void);
-#endif /* WITH_THREAD */
-
-int Py_DebugFlag; /* Needed by parser.c */
-int Py_VerboseFlag; /* Needed by import.c */
-int Py_QuietFlag; /* Needed by sysmodule.c */
-int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */
-int Py_InspectFlag; /* Needed to determine whether to exit at SystemExit */
-int Py_NoSiteFlag; /* Suppress 'import site' */
-int Py_BytesWarningFlag; /* Warn on str(bytes) and str(buffer) */
-int Py_DontWriteBytecodeFlag; /* Suppress writing bytecode files (*.py[co]) */
-int Py_UseClassExceptionsFlag = 1; /* Needed by bltinmodule.c: deprecated */
-int Py_FrozenFlag; /* Needed by getpath.c */
-int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
-int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
-int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
-int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
-int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */
-
-PyThreadState *_Py_Finalizing = NULL;
-
-/* Hack to force loading of object files */
-int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) = \
-    PyOS_mystrnicmp; /* Python/pystrcmp.o */
-
-/* PyModule_GetWarningsModule is no longer necessary as of 2.6
-since _warnings is builtin.  This API should not be used. */
-PyObject *
-PyModule_GetWarningsModule(void)
-{
-    return PyImport_ImportModule("warnings");
-}
-
-static int initialized = 0;
-
-/* API to access the initialized flag -- useful for esoteric use */
-
-int
-Py_IsInitialized(void)
-{
-    return initialized;
-}
-
-/* Helper to allow an embedding application to override the normal
- * mechanism that attempts to figure out an appropriate IO encoding
- */
-
-static char *_Py_StandardStreamEncoding = NULL;
-static char *_Py_StandardStreamErrors = NULL;
-
-int
-Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
-{
-    if (Py_IsInitialized()) {
-        /* This is too late to have any effect */
-        return -1;
-    }
-    /* Can't call PyErr_NoMemory() on errors, as Python hasn't been
-     * initialised yet.
-     *
-     * However, the raw memory allocators are initialised appropriately
-     * as C static variables, so _PyMem_RawStrdup is OK even though
-     * Py_Initialize hasn't been called yet.
-     */
-    if (encoding) {
-        _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding);
-        if (!_Py_StandardStreamEncoding) {
-            return -2;
-        }
-    }
-    if (errors) {
-        _Py_StandardStreamErrors = _PyMem_RawStrdup(errors);
-        if (!_Py_StandardStreamErrors) {
-            if (_Py_StandardStreamEncoding) {
-                PyMem_RawFree(_Py_StandardStreamEncoding);
-            }
-            return -3;
-        }
-    }
-    return 0;
-}
-
-/* Global initializations.  Can be undone by Py_Finalize().  Don't
-   call this twice without an intervening Py_Finalize() call.  When
-   initializations fail, a fatal error is issued and the function does
-   not return.  On return, the first thread and interpreter state have
-   been created.
-
-   Locking: you must hold the interpreter lock while calling this.
-   (If the lock has not yet been initialized, that's equivalent to
-   having the lock, but you cannot use multiple threads.)
-
-*/
-
-static int
-add_flag(int flag, const char *envs)
-{
-    int env = atoi(envs);
-    if (flag < env)
-        flag = env;
-    if (flag < 1)
-        flag = 1;
-    return flag;
-}
-
-static char*
-get_codec_name(const char *encoding)
-{
-    char *name_utf8, *name_str;
-    PyObject *codec, *name = NULL;
-
-    codec = _PyCodec_Lookup(encoding);
-    if (!codec)
-        goto error;
-
-    name = _PyObject_GetAttrId(codec, &PyId_name);
-    Py_CLEAR(codec);
-    if (!name)
-        goto error;
-
-    name_utf8 = _PyUnicode_AsString(name);
-    if (name_utf8 == NULL)
-        goto error;
-    name_str = _PyMem_RawStrdup(name_utf8);
-    Py_DECREF(name);
-    if (name_str == NULL) {
-        PyErr_NoMemory();
-        return NULL;
-    }
-    return name_str;
-
-error:
-    Py_XDECREF(codec);
-    Py_XDECREF(name);
-    return NULL;
-}
-
-static char*
-get_locale_encoding(void)
-{
-#ifdef MS_WINDOWS
-    char codepage[100];
-    PyOS_snprintf(codepage, sizeof(codepage), "cp%d", GetACP());
-    return get_codec_name(codepage);
-#elif defined(HAVE_LANGINFO_H) && defined(CODESET)
-    char* codeset = nl_langinfo(CODESET);
-    if (!codeset || codeset[0] == '\0') {
-        PyErr_SetString(PyExc_ValueError, "CODESET is not set or empty");
-        return NULL;
-    }
-    return get_codec_name(codeset);
-#else
-    PyErr_SetNone(PyExc_NotImplementedError);
-    return NULL;
-#endif
-}
-
-static void
-import_init(PyInterpreterState *interp, PyObject *sysmod)
-{
-    PyObject *importlib;
-    PyObject *impmod;
-    PyObject *sys_modules;
-    PyObject *value;
-
-    /* Import _importlib through its frozen version, _frozen_importlib. */
-    if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
-        Py_FatalError("Py_Initialize: can't import _frozen_importlib");
-    }
-    else if (Py_VerboseFlag) {
-        PySys_FormatStderr("import _frozen_importlib # frozen\n");
-    }
-    importlib = PyImport_AddModule("_frozen_importlib");
-    if (importlib == NULL) {
-        Py_FatalError("Py_Initialize: couldn't get _frozen_importlib from "
-                      "sys.modules");
-    }
-    interp->importlib = importlib;
-    Py_INCREF(interp->importlib);
-
-    /* Install _importlib as __import__ */
-    impmod = PyInit_imp();
-    if (impmod == NULL) {
-        Py_FatalError("Py_Initialize: can't import imp");
-    }
-    else if (Py_VerboseFlag) {
-        PySys_FormatStderr("import imp # builtin\n");
-    }
-    sys_modules = PyImport_GetModuleDict();
-    if (Py_VerboseFlag) {
-        PySys_FormatStderr("import sys # builtin\n");
-    }
-    if (PyDict_SetItemString(sys_modules, "_imp", impmod) < 0) {
-        Py_FatalError("Py_Initialize: can't save _imp to sys.modules");
-    }
-
-    value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod);
-    if (value == NULL) {
-        PyErr_Print();
-        Py_FatalError("Py_Initialize: importlib install failed");
-    }
-    Py_DECREF(value);
-    Py_DECREF(impmod);
-
-    _PyImportZip_Init();
-}
-
-
-void
-_Py_InitializeEx_Private(int install_sigs, int install_importlib)
-{
-    PyInterpreterState *interp;
-    PyThreadState *tstate;
-    PyObject *bimod, *sysmod, *pstderr;
-    char *p;
-    extern void _Py_ReadyTypes(void);
-
-    if (initialized)
-        return;
-    initialized = 1;
-    _Py_Finalizing = NULL;
-
-#if defined(HAVE_LANGINFO_H) && defined(HAVE_SETLOCALE)
-    /* Set up the LC_CTYPE locale, so we can obtain
-       the locale's charset without having to switch
-       locales. */
-    setlocale(LC_CTYPE, "");
-#endif
-
-    if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0')
-        Py_DebugFlag = add_flag(Py_DebugFlag, p);
-    if ((p = Py_GETENV("PYTHONVERBOSE")) && *p != '\0')
-        Py_VerboseFlag = add_flag(Py_VerboseFlag, p);
-    if ((p = Py_GETENV("PYTHONOPTIMIZE")) && *p != '\0')
-        Py_OptimizeFlag = add_flag(Py_OptimizeFlag, p);
-    if ((p = Py_GETENV("PYTHONDONTWRITEBYTECODE")) && *p != '\0')
-        Py_DontWriteBytecodeFlag = add_flag(Py_DontWriteBytecodeFlag, p);
-    /* The variable is only tested for existence here; _PyRandom_Init will
-       check its value further. */
-    if ((p = Py_GETENV("PYTHONHASHSEED")) && *p != '\0')
-        Py_HashRandomizationFlag = add_flag(Py_HashRandomizationFlag, p);
-
-    _PyRandom_Init();
-
-    interp = PyInterpreterState_New();
-    if (interp == NULL)
-        Py_FatalError("Py_Initialize: can't make first interpreter");
-
-    tstate = PyThreadState_New(interp);
-    if (tstate == NULL)
-        Py_FatalError("Py_Initialize: can't make first thread");
-    (void) PyThreadState_Swap(tstate);
-
-#ifdef WITH_THREAD
-    /* We can't call _PyEval_FiniThreads() in Py_Finalize because
-       destroying the GIL might fail when it is being referenced from
-       another running thread (see issue #9901).
-       Instead we destroy the previously created GIL here, which ensures
-       that we can call Py_Initialize / Py_Finalize multiple times. */
-    _PyEval_FiniThreads();
-
-    /* Auto-thread-state API */
-    _PyGILState_Init(interp, tstate);
-#endif /* WITH_THREAD */
-
-    _Py_ReadyTypes();
-
-    if (!_PyFrame_Init())
-        Py_FatalError("Py_Initialize: can't init frames");
-
-    if (!_PyLong_Init())
-        Py_FatalError("Py_Initialize: can't init longs");
-
-    if (!PyByteArray_Init())
-        Py_FatalError("Py_Initialize: can't init bytearray");
-
-    if (!_PyFloat_Init())
-        Py_FatalError("Py_Initialize: can't init float");
-
-    interp->modules = PyDict_New();
-    if (interp->modules == NULL)
-        Py_FatalError("Py_Initialize: can't make modules dictionary");
-
-    /* Init Unicode implementation; relies on the codec registry */
-    if (_PyUnicode_Init() < 0)
-        Py_FatalError("Py_Initialize: can't initialize unicode");
-    if (_PyStructSequence_Init() < 0)
-        Py_FatalError("Py_Initialize: can't initialize structseq");
-
-    bimod = _PyBuiltin_Init();
-    if (bimod == NULL)
-        Py_FatalError("Py_Initialize: can't initialize builtins modules");
-    _PyImport_FixupBuiltin(bimod, "builtins");
-    interp->builtins = PyModule_GetDict(bimod);
-    if (interp->builtins == NULL)
-        Py_FatalError("Py_Initialize: can't initialize builtins dict");
-    Py_INCREF(interp->builtins);
-
-    /* initialize builtin exceptions */
-    _PyExc_Init(bimod);
-
-    sysmod = _PySys_Init();
-    if (sysmod == NULL)
-        Py_FatalError("Py_Initialize: can't initialize sys");
-    interp->sysdict = PyModule_GetDict(sysmod);
-    if (interp->sysdict == NULL)
-        Py_FatalError("Py_Initialize: can't initialize sys dict");
-    Py_INCREF(interp->sysdict);
-    _PyImport_FixupBuiltin(sysmod, "sys");
-    PySys_SetPath(Py_GetPath());
-    PyDict_SetItemString(interp->sysdict, "modules",
-                         interp->modules);
-
-    /* Set up a preliminary stderr printer until we have enough
-       infrastructure for the io module in place. */
-    pstderr = PyFile_NewStdPrinter(fileno(stderr));
-    if (pstderr == NULL)
-        Py_FatalError("Py_Initialize: can't set preliminary stderr");
-    _PySys_SetObjectId(&PyId_stderr, pstderr);
-    PySys_SetObject("__stderr__", pstderr);
-    Py_DECREF(pstderr);
-
-    _PyImport_Init();
-
-    _PyImportHooks_Init();
-
-    /* Initialize _warnings. */
-    _PyWarnings_Init();
-
-    if (!install_importlib)
-        return;
-
-    import_init(interp, sysmod);
-
-    /* initialize the faulthandler module */
-    if (_PyFaulthandler_Init())
-        Py_FatalError("Py_Initialize: can't initialize faulthandler");
-
-    if (_PyTime_Init() < 0)
-        Py_FatalError("Py_Initialize: can't initialize time");
-
-    if (initfsencoding(interp) < 0)
-        Py_FatalError("Py_Initialize: unable to load the file system codec");
-
-    if (install_sigs)
-        initsigs(); /* Signal handling stuff, including initintr() */
-
-    if (_PyTraceMalloc_Init() < 0)
-        Py_FatalError("Py_Initialize: can't initialize tracemalloc");
-
-    initmain(interp); /* Module __main__ */
-    if (initstdio() < 0)
-        Py_FatalError(
-            "Py_Initialize: can't initialize sys standard streams");
-
-    /* Initialize warnings. */
-    if (PySys_HasWarnOptions()) {
-        PyObject *warnings_module = PyImport_ImportModule("warnings");
-        if (warnings_module == NULL) {
-            fprintf(stderr, "'import warnings' failed; traceback:\n");
-            PyErr_Print();
-        }
-        Py_XDECREF(warnings_module);
-    }
-
-    if (!Py_NoSiteFlag)
-        initsite(); /* Module site */
-}
-
-void
-Py_InitializeEx(int install_sigs)
-{
-    _Py_InitializeEx_Private(install_sigs, 1);
-}
-
-void
-Py_Initialize(void)
-{
-    Py_InitializeEx(1);
-}
-
-
-#ifdef COUNT_ALLOCS
-extern void dump_counts(FILE*);
-#endif
-
-/* Flush stdout and stderr */
-
-static int
-file_is_closed(PyObject *fobj)
-{
-    int r;
-    PyObject *tmp = PyObject_GetAttrString(fobj, "closed");
-    if (tmp == NULL) {
-        PyErr_Clear();
-        return 0;
-    }
-    r = PyObject_IsTrue(tmp);
-    Py_DECREF(tmp);
-    if (r < 0)
-        PyErr_Clear();
-    return r > 0;
-}
-
-static void
-flush_std_files(void)
-{
-    PyObject *fout = _PySys_GetObjectId(&PyId_stdout);
-    PyObject *ferr = _PySys_GetObjectId(&PyId_stderr);
-    PyObject *tmp;
-
-    if (fout != NULL && fout != Py_None && !file_is_closed(fout)) {
-        tmp = _PyObject_CallMethodId(fout, &PyId_flush, "");
-        if (tmp == NULL)
-            PyErr_WriteUnraisable(fout);
-        else
-            Py_DECREF(tmp);
-    }
-
-    if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) {
-        tmp = _PyObject_CallMethodId(ferr, &PyId_flush, "");
-        if (tmp == NULL)
-            PyErr_Clear();
-        else
-            Py_DECREF(tmp);
-    }
-}
-
-/* Undo the effect of Py_Initialize().
-
-   Beware: if multiple interpreter and/or thread states exist, these
-   are not wiped out; only the current thread and interpreter state
-   are deleted.  But since everything else is deleted, those other
-   interpreter and thread states should no longer be used.
-
-   (XXX We should do better, e.g. wipe out all interpreters and
-   threads.)
-
-   Locking: as above.
-
-*/
-
-void
-Py_Finalize(void)
-{
-    PyInterpreterState *interp;
-    PyThreadState *tstate;
-
-    if (!initialized)
-        return;
-
-    wait_for_thread_shutdown();
-
-    /* The interpreter is still entirely intact at this point, and the
-     * exit funcs may be relying on that.  In particular, if some thread
-     * or exit func is still waiting to do an import, the import machinery
-     * expects Py_IsInitialized() to return true.  So don't say the
-     * interpreter is uninitialized until after the exit funcs have run.
-     * Note that Threading.py uses an exit func to do a join on all the
-     * threads created thru it, so this also protects pending imports in
-     * the threads created via Threading.
-     */
-    call_py_exitfuncs();
-
-    /* Get current thread state and interpreter pointer */
-    tstate = PyThreadState_GET();
-    interp = tstate->interp;
-
-    /* Remaining threads (e.g. daemon threads) will automatically exit
-       after taking the GIL (in PyEval_RestoreThread()). */
-    _Py_Finalizing = tstate;
-    initialized = 0;
-
-    /* Flush stdout+stderr */
-    flush_std_files();
-
-    /* Disable signal handling */
-    PyOS_FiniInterrupts();
-
-    /* Collect garbage.  This may call finalizers; it's nice to call these
-     * before all modules are destroyed.
-     * XXX If a __del__ or weakref callback is triggered here, and tries to
-     * XXX import a module, bad things can happen, because Python no
-     * XXX longer believes it's initialized.
-     * XXX     Fatal Python error: Interpreter not initialized (version mismatch?)
-     * XXX is easy to provoke that way.  I've also seen, e.g.,
-     * XXX     Exception exceptions.ImportError: 'No module named sha'
-     * XXX         in <function callback at 0x008F5718> ignored
-     * XXX but I'm unclear on exactly how that one happens.  In any case,
-     * XXX I haven't seen a real-life report of either of these.
-     */
-    PyGC_Collect();
-#ifdef COUNT_ALLOCS
-    /* With COUNT_ALLOCS, it helps to run GC multiple times:
-       each collection might release some types from the type
-       list, so they become garbage. */
-    while (PyGC_Collect() > 0)
-        /* nothing */;
-#endif
-    /* Destroy all modules */
-    PyImport_Cleanup();
-
-    /* Flush stdout+stderr (again, in case more was printed) */
-    flush_std_files();
-
-    /* Collect final garbage.  This disposes of cycles created by
-     * class definitions, for example.
-     * XXX This is disabled because it caused too many problems.  If
-     * XXX a __del__ or weakref callback triggers here, Python code has
-     * XXX a hard time running, because even the sys module has been
-     * XXX cleared out (sys.stdout is gone, sys.excepthook is gone, etc).
-     * XXX One symptom is a sequence of information-free messages
-     * XXX coming from threads (if a __del__ or callback is invoked,
-     * XXX other threads can execute too, and any exception they encounter
-     * XXX triggers a comedy of errors as subsystem after subsystem
-     * XXX fails to find what it *expects* to find in sys to help report
-     * XXX the exception and consequent unexpected failures).  I've also
-     * XXX seen segfaults then, after adding print statements to the
-     * XXX Python code getting called.
-     */
-#if 0
-    PyGC_Collect();
-#endif
-
-    /* Disable tracemalloc after all Python objects have been destroyed,
-       so it is possible to use tracemalloc in objects destructor. */
-    _PyTraceMalloc_Fini();
-
-    /* Destroy the database used by _PyImport_{Fixup,Find}Extension */
-    _PyImport_Fini();
-
-    /* Cleanup typeobject.c's internal caches. */
-    _PyType_Fini();
-
-    /* unload faulthandler module */
-    _PyFaulthandler_Fini();
-
-    /* Debugging stuff */
-#ifdef COUNT_ALLOCS
-    dump_counts(stdout);
-#endif
-    /* dump hash stats */
-    _PyHash_Fini();
-
-    PRINT_TOTAL_REFS();
-
-#ifdef Py_TRACE_REFS
-    /* Display all objects still alive -- this can invoke arbitrary
-     * __repr__ overrides, so requires a mostly-intact interpreter.
-     * Alas, a lot of stuff may still be alive now that will be cleaned
-     * up later.
-     */
-    if (Py_GETENV("PYTHONDUMPREFS"))
-        _Py_PrintReferences(stderr);
-#endif /* Py_TRACE_REFS */
-
-    /* Clear interpreter state and all thread states. */
-    PyInterpreterState_Clear(interp);
-
-    /* Now we decref the exception classes.  After this point nothing
-       can raise an exception.  That's okay, because each Fini() method
-       below has been checked to make sure no exceptions are ever
-       raised.
-    */
-
-    _PyExc_Fini();
-
-    /* Sundry finalizers */
-    PyMethod_Fini();
-    PyFrame_Fini();
-    PyCFunction_Fini();
-    PyTuple_Fini();
-    PyList_Fini();
-    PySet_Fini();
-    PyBytes_Fini();
-    PyByteArray_Fini();
-    PyLong_Fini();
-    PyFloat_Fini();
-    PyDict_Fini();
-    PySlice_Fini();
-    _PyGC_Fini();
-    _PyRandom_Fini();
-
-    /* Cleanup Unicode implementation */
-    _PyUnicode_Fini();
-
-    /* reset file system default encoding */
-    if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
-        PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
-        Py_FileSystemDefaultEncoding = NULL;
-    }
-
-    /* XXX Still allocated:
-       - various static ad-hoc pointers to interned strings
-       - int and float free list blocks
-       - whatever various modules and libraries allocate
-    */
-
-    PyGrammar_RemoveAccelerators(&_PyParser_Grammar);
-
-    /* Cleanup auto-thread-state */
-#ifdef WITH_THREAD
-    _PyGILState_Fini();
-#endif /* WITH_THREAD */
-
-    /* Delete current thread. After this, many C API calls become crashy. */
-    PyThreadState_Swap(NULL);
-    PyInterpreterState_Delete(interp);
-
-#ifdef Py_TRACE_REFS
-    /* Display addresses (& refcnts) of all objects still alive.
-     * An address can be used to find the repr of the object, printed
-     * above by _Py_PrintReferences.
-     */
-    if (Py_GETENV("PYTHONDUMPREFS"))
-        _Py_PrintReferenceAddresses(stderr);
-#endif /* Py_TRACE_REFS */
-#ifdef PYMALLOC_DEBUG
-    if (Py_GETENV("PYTHONMALLOCSTATS"))
-        _PyObject_DebugMallocStats(stderr);
-#endif
-
-    call_ll_exitfuncs();
-}
-
-/* Create and initialize a new interpreter and thread, and return the
-   new thread.  This requires that Py_Initialize() has been called
-   first.
-
-   Unsuccessful initialization yields a NULL pointer.  Note that *no*
-   exception information is available even in this case -- the
-   exception information is held in the thread, and there is no
-   thread.
-
-   Locking: as above.
-
-*/
-
-PyThreadState *
-Py_NewInterpreter(void)
-{
-    PyInterpreterState *interp;
-    PyThreadState *tstate, *save_tstate;
-    PyObject *bimod, *sysmod;
-
-    if (!initialized)
-        Py_FatalError("Py_NewInterpreter: call Py_Initialize first");
-
-    interp = PyInterpreterState_New();
-    if (interp == NULL)
-        return NULL;
-
-    tstate = PyThreadState_New(interp);
-    if (tstate == NULL) {
-        PyInterpreterState_Delete(interp);
-        return NULL;
-    }
-
-    save_tstate = PyThreadState_Swap(tstate);
-
-    /* XXX The following is lax in error checking */
-
-    interp->modules = PyDict_New();
-
-    bimod = _PyImport_FindBuiltin("builtins");
-    if (bimod != NULL) {
-        interp->builtins = PyModule_GetDict(bimod);
-        if (interp->builtins == NULL)
-            goto handle_error;
-        Py_INCREF(interp->builtins);
-    }
-
-    /* initialize builtin exceptions */
-    _PyExc_Init(bimod);
-
-    sysmod = _PyImport_FindBuiltin("sys");
-    if (bimod != NULL && sysmod != NULL) {
-        PyObject *pstderr;
-
-        interp->sysdict = PyModule_GetDict(sysmod);
-        if (interp->sysdict == NULL)
-            goto handle_error;
-        Py_INCREF(interp->sysdict);
-        PySys_SetPath(Py_GetPath());
-        PyDict_SetItemString(interp->sysdict, "modules",
-                             interp->modules);
-        /* Set up a preliminary stderr printer until we have enough
-           infrastructure for the io module in place. */
-        pstderr = PyFile_NewStdPrinter(fileno(stderr));
-        if (pstderr == NULL)
-            Py_FatalError("Py_Initialize: can't set preliminary stderr");
-        _PySys_SetObjectId(&PyId_stderr, pstderr);
-        PySys_SetObject("__stderr__", pstderr);
-        Py_DECREF(pstderr);
-
-        _PyImportHooks_Init();
-
-        import_init(interp, sysmod);
-
-        if (initfsencoding(interp) < 0)
-            goto handle_error;
-
-        if (initstdio() < 0)
-            Py_FatalError(
-            "Py_Initialize: can't initialize sys standard streams");
-        initmain(interp);
-        if (!Py_NoSiteFlag)
-            initsite();
-    }
-
-    if (!PyErr_Occurred())
-        return tstate;
-
-handle_error:
-    /* Oops, it didn't work.  Undo it all. */
-
-    PyErr_PrintEx(0);
-    PyThreadState_Clear(tstate);
-    PyThreadState_Swap(save_tstate);
-    PyThreadState_Delete(tstate);
-    PyInterpreterState_Delete(interp);
-
-    return NULL;
-}
-
-/* Delete an interpreter and its last thread.  This requires that the
-   given thread state is current, that the thread has no remaining
-   frames, and that it is its interpreter's only remaining thread.
-   It is a fatal error to violate these constraints.
-
-   (Py_Finalize() doesn't have these constraints -- it zaps
-   everything, regardless.)
-
-   Locking: as above.
-
-*/
-
-void
-Py_EndInterpreter(PyThreadState *tstate)
-{
-    PyInterpreterState *interp = tstate->interp;
-
-    if (tstate != PyThreadState_GET())
-        Py_FatalError("Py_EndInterpreter: thread is not current");
-    if (tstate->frame != NULL)
-        Py_FatalError("Py_EndInterpreter: thread still has a frame");
-
-    wait_for_thread_shutdown();
-
-    if (tstate != interp->tstate_head || tstate->next != NULL)
-        Py_FatalError("Py_EndInterpreter: not the last thread");
-
-    PyImport_Cleanup();
-    PyInterpreterState_Clear(interp);
-    PyThreadState_Swap(NULL);
-    PyInterpreterState_Delete(interp);
-}
-
-#ifdef MS_WINDOWS
-static wchar_t *progname = L"python";
-#else
-static wchar_t *progname = L"python3";
-#endif
-
-void
-Py_SetProgramName(wchar_t *pn)
-{
-    if (pn && *pn)
-        progname = pn;
-}
-
-wchar_t *
-Py_GetProgramName(void)
-{
-    return progname;
-}
-
-static wchar_t *default_home = NULL;
-static wchar_t env_home[MAXPATHLEN+1];
-
-void
-Py_SetPythonHome(wchar_t *home)
-{
-    default_home = home;
-}
-
-wchar_t *
-Py_GetPythonHome(void)
-{
-    wchar_t *home = default_home;
-    if (home == NULL && !Py_IgnoreEnvironmentFlag) {
-        char* chome = Py_GETENV("PYTHONHOME");
-        if (chome) {
-            size_t size = Py_ARRAY_LENGTH(env_home);
-            size_t r = mbstowcs(env_home, chome, size);
-            if (r != (size_t)-1 && r < size)
-                home = env_home;
-        }
-
-    }
-    return home;
-}
-
-/* Create __main__ module */
-
-static void
-initmain(PyInterpreterState *interp)
-{
-    PyObject *m, *d, *loader;
-    m = PyImport_AddModule("__main__");
-    if (m == NULL)
-        Py_FatalError("can't create __main__ module");
-    d = PyModule_GetDict(m);
-    if (PyDict_GetItemString(d, "__builtins__") == NULL) {
-        PyObject *bimod = PyImport_ImportModule("builtins");
-        if (bimod == NULL) {
-            Py_FatalError("Failed to retrieve builtins module");
-        }
-        if (PyDict_SetItemString(d, "__builtins__", bimod) < 0) {
-            Py_FatalError("Failed to initialize __main__.__builtins__");
-        }
-        Py_DECREF(bimod);
-    }
-    /* Main is a little special - imp.is_builtin("__main__") will return
-     * False, but BuiltinImporter is still the most appropriate initial
-     * setting for its __loader__ attribute. A more suitable value will
-     * be set if __main__ gets further initialized later in the startup
-     * process.
-     */
-    loader = PyDict_GetItemString(d, "__loader__");
-    if (loader == NULL || loader == Py_None) {
-        PyObject *loader = PyObject_GetAttrString(interp->importlib,
-                                                  "BuiltinImporter");
-        if (loader == NULL) {
-            Py_FatalError("Failed to retrieve BuiltinImporter");
-        }
-        if (PyDict_SetItemString(d, "__loader__", loader) < 0) {
-            Py_FatalError("Failed to initialize __main__.__loader__");
-        }
-        Py_DECREF(loader);
-    }
-}
-
-static int
-initfsencoding(PyInterpreterState *interp)
-{
-    PyObject *codec;
-
-    if (Py_FileSystemDefaultEncoding == NULL)
-    {
-        Py_FileSystemDefaultEncoding = get_locale_encoding();
-        if (Py_FileSystemDefaultEncoding == NULL)
-            Py_FatalError("Py_Initialize: Unable to get the locale encoding");
-
-        Py_HasFileSystemDefaultEncoding = 0;
-        interp->fscodec_initialized = 1;
-        return 0;
-    }
-
-    /* the encoding is mbcs, utf-8 or ascii */
-    codec = _PyCodec_Lookup(Py_FileSystemDefaultEncoding);
-    if (!codec) {
-        /* Such error can only occurs in critical situations: no more
-         * memory, import a module of the standard library failed,
-         * etc. */
-        return -1;
-    }
-    Py_DECREF(codec);
-    interp->fscodec_initialized = 1;
-    return 0;
-}
-
-/* Import the site module (not into __main__ though) */
-
-static void
-initsite(void)
-{
-    PyObject *m;
-    m = PyImport_ImportModule("site");
-    if (m == NULL) {
-        fprintf(stderr, "Failed to import the site module\n");
-        PyErr_Print();
-        Py_Finalize();
-        exit(1);
-    }
-    else {
-        Py_DECREF(m);
-    }
-}
-
-static PyObject*
-create_stdio(PyObject* io,
-    int fd, int write_mode, char* name,
-    char* encoding, char* errors)
-{
-    PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res;
-    const char* mode;
-    const char* newline;
-    PyObject *line_buffering;
-    int buffering, isatty;
-    _Py_IDENTIFIER(open);
-    _Py_IDENTIFIER(isatty);
-    _Py_IDENTIFIER(TextIOWrapper);
-    _Py_IDENTIFIER(mode);
-
-    /* stdin is always opened in buffered mode, first because it shouldn't
-       make a difference in common use cases, second because TextIOWrapper
-       depends on the presence of a read1() method which only exists on
-       buffered streams.
-    */
-    if (Py_UnbufferedStdioFlag && write_mode)
-        buffering = 0;
-    else
-        buffering = -1;
-    if (write_mode)
-        mode = "wb";
-    else
-        mode = "rb";
-    buf = _PyObject_CallMethodId(io, &PyId_open, "isiOOOi",
-                                 fd, mode, buffering,
-                                 Py_None, Py_None, Py_None, 0);
-    if (buf == NULL)
-        goto error;
-
-    if (buffering) {
-        _Py_IDENTIFIER(raw);
-        raw = _PyObject_GetAttrId(buf, &PyId_raw);
-        if (raw == NULL)
-            goto error;
-    }
-    else {
-        raw = buf;
-        Py_INCREF(raw);
-    }
-
-    text = PyUnicode_FromString(name);
-    if (text == NULL || _PyObject_SetAttrId(raw, &PyId_name, text) < 0)
-        goto error;
-    res = _PyObject_CallMethodId(raw, &PyId_isatty, "");
-    if (res == NULL)
-        goto error;
-    isatty = PyObject_IsTrue(res);
-    Py_DECREF(res);
-    if (isatty == -1)
-        goto error;
-    if (isatty || Py_UnbufferedStdioFlag)
-        line_buffering = Py_True;
-    else
-        line_buffering = Py_False;
-
-    Py_CLEAR(raw);
-    Py_CLEAR(text);
-
-#ifdef MS_WINDOWS
-    /* sys.stdin: enable universal newline mode, translate "\r\n" and "\r"
-       newlines to "\n".
-       sys.stdout and sys.stderr: translate "\n" to "\r\n". */
-    newline = NULL;
-#else
-    /* sys.stdin: split lines at "\n".
-       sys.stdout and sys.stderr: don't translate newlines (use "\n"). */
-    newline = "\n";
-#endif
-
-    stream = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "OsssO",
-                                    buf, encoding, errors,
-                                    newline, line_buffering);
-    Py_CLEAR(buf);
-    if (stream == NULL)
-        goto error;
-
-    if (write_mode)
-        mode = "w";
-    else
-        mode = "r";
-    text = PyUnicode_FromString(mode);
-    if (!text || _PyObject_SetAttrId(stream, &PyId_mode, text) < 0)
-        goto error;
-    Py_CLEAR(text);
-    return stream;
-
-error:
-    Py_XDECREF(buf);
-    Py_XDECREF(stream);
-    Py_XDECREF(text);
-    Py_XDECREF(raw);
-    return NULL;
-}
-
-static int
-is_valid_fd(int fd)
-{
-    int dummy_fd;
-    if (fd < 0 || !_PyVerify_fd(fd))
-        return 0;
-    dummy_fd = dup(fd);
-    if (dummy_fd < 0)
-        return 0;
-    close(dummy_fd);
-    return 1;
-}
-
-/* Initialize sys.stdin, stdout, stderr and builtins.open */
-static int
-initstdio(void)
-{
-    PyObject *iomod = NULL, *wrapper;
-    PyObject *bimod = NULL;
-    PyObject *m;
-    PyObject *std = NULL;
-    int status = 0, fd;
-    PyObject * encoding_attr;
-    char *pythonioencoding = NULL, *encoding, *errors;
-
-    /* Hack to avoid a nasty recursion issue when Python is invoked
-       in verbose mode: pre-import the Latin-1 and UTF-8 codecs */
-    if ((m = PyImport_ImportModule("encodings.utf_8")) == NULL) {
-        goto error;
-    }
-    Py_DECREF(m);
-
-    if (!(m = PyImport_ImportModule("encodings.latin_1"))) {
-        goto error;
-    }
-    Py_DECREF(m);
-
-    if (!(bimod = PyImport_ImportModule("builtins"))) {
-        goto error;
-    }
-
-    if (!(iomod = PyImport_ImportModule("io"))) {
-        goto error;
-    }
-    if (!(wrapper = PyObject_GetAttrString(iomod, "OpenWrapper"))) {
-        goto error;
-    }
-
-    /* Set builtins.open */
-    if (PyObject_SetAttrString(bimod, "open", wrapper) == -1) {
-        Py_DECREF(wrapper);
-        goto error;
-    }
-    Py_DECREF(wrapper);
-
-    encoding = _Py_StandardStreamEncoding;
-    errors = _Py_StandardStreamErrors;
-    if (!encoding || !errors) {
-        if (!errors) {
-            /* When the LC_CTYPE locale is the POSIX locale ("C locale"),
-               stdin and stdout use the surrogateescape error handler by
-               default, instead of the strict error handler. */
-            char *loc = setlocale(LC_CTYPE, NULL);
-            if (loc != NULL && strcmp(loc, "C") == 0)
-                errors = "surrogateescape";
-        }
-
-        pythonioencoding = Py_GETENV("PYTHONIOENCODING");
-        if (pythonioencoding) {
-            char *err;
-            pythonioencoding = _PyMem_Strdup(pythonioencoding);
-            if (pythonioencoding == NULL) {
-                PyErr_NoMemory();
-                goto error;
-            }
-            err = strchr(pythonioencoding, ':');
-            if (err) {
-                *err = '\0';
-                err++;
-                if (*err && !_Py_StandardStreamErrors) {
-                    errors = err;
-                }
-            }
-            if (*pythonioencoding && !encoding) {
-                encoding = pythonioencoding;
-            }
-        }
-    }
-
-    /* Set sys.stdin */
-    fd = fileno(stdin);
-    /* Under some conditions stdin, stdout and stderr may not be connected
-     * and fileno() may point to an invalid file descriptor. For example
-     * GUI apps don't have valid standard streams by default.
-     */
-    if (!is_valid_fd(fd)) {
-        std = Py_None;
-        Py_INCREF(std);
-    }
-    else {
-        std = create_stdio(iomod, fd, 0, "<stdin>", encoding, errors);
-        if (std == NULL)
-            goto error;
-    } /* if (fd < 0) */
-    PySys_SetObject("__stdin__", std);
-    _PySys_SetObjectId(&PyId_stdin, std);
-    Py_DECREF(std);
-
-    /* Set sys.stdout */
-    fd = fileno(stdout);
-    if (!is_valid_fd(fd)) {
-        std = Py_None;
-        Py_INCREF(std);
-    }
-    else {
-        std = create_stdio(iomod, fd, 1, "<stdout>", encoding, errors);
-        if (std == NULL)
-            goto error;
-    } /* if (fd < 0) */
-    PySys_SetObject("__stdout__", std);
-    _PySys_SetObjectId(&PyId_stdout, std);
-    Py_DECREF(std);
-
-#if 1 /* Disable this if you have trouble debugging bootstrap stuff */
-    /* Set sys.stderr, replaces the preliminary stderr */
-    fd = fileno(stderr);
-    if (!is_valid_fd(fd)) {
-        std = Py_None;
-        Py_INCREF(std);
-    }
-    else {
-        std = create_stdio(iomod, fd, 1, "<stderr>", encoding, "backslashreplace");
-        if (std == NULL)
-            goto error;
-    } /* if (fd < 0) */
-
-    /* Same as hack above, pre-import stderr's codec to avoid recursion
-       when import.c tries to write to stderr in verbose mode. */
-    encoding_attr = PyObject_GetAttrString(std, "encoding");
-    if (encoding_attr != NULL) {
-        const char * std_encoding;
-        std_encoding = _PyUnicode_AsString(encoding_attr);
-        if (std_encoding != NULL) {
-            PyObject *codec_info = _PyCodec_Lookup(std_encoding);
-            Py_XDECREF(codec_info);
-        }
-        Py_DECREF(encoding_attr);
-    }
-    PyErr_Clear();  /* Not a fatal error if codec isn't available */
-
-    if (PySys_SetObject("__stderr__", std) < 0) {
-        Py_DECREF(std);
-        goto error;
-    }
-    if (_PySys_SetObjectId(&PyId_stderr, std) < 0) {
-        Py_DECREF(std);
-        goto error;
-    }
-    Py_DECREF(std);
-#endif
-
-    if (0) {
-  error:
-        status = -1;
-    }
-
-    /* We won't need them anymore. */
-    if (_Py_StandardStreamEncoding) {
-        PyMem_RawFree(_Py_StandardStreamEncoding);
-        _Py_StandardStreamEncoding = NULL;
-    }
-    if (_Py_StandardStreamErrors) {
-        PyMem_RawFree(_Py_StandardStreamErrors);
-        _Py_StandardStreamErrors = NULL;
-    }
-    PyMem_Free(pythonioencoding);
-    Py_XDECREF(bimod);
-    Py_XDECREF(iomod);
-    return status;
-}
 
 /* Parse input from a file and execute it */
 
@@ -1327,7 +110,7 @@
     err = -1;
     for (;;) {
         ret = PyRun_InteractiveOneObject(fp, filename, flags);
-        PRINT_TOTAL_REFS();
+        _PY_DEBUG_PRINT_TOTAL_REFS();
         if (ret == E_EOF) {
             err = 0;
             break;
@@ -2592,192 +1375,6 @@
     }
 }
 
-/* Print fatal error message and abort */
-
-void
-Py_FatalError(const char *msg)
-{
-    const int fd = fileno(stderr);
-    PyThreadState *tstate;
-
-    fprintf(stderr, "Fatal Python error: %s\n", msg);
-    fflush(stderr); /* it helps in Windows debug build */
-    if (PyErr_Occurred()) {
-        PyErr_PrintEx(0);
-    }
-    else {
-        tstate = _Py_atomic_load_relaxed(&_PyThreadState_Current);
-        if (tstate != NULL) {
-            fputc('\n', stderr);
-            fflush(stderr);
-            _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
-        }
-        _PyFaulthandler_Fini();
-    }
-
-#ifdef MS_WINDOWS
-    {
-        size_t len = strlen(msg);
-        WCHAR* buffer;
-        size_t i;
-
-        /* Convert the message to wchar_t. This uses a simple one-to-one
-        conversion, assuming that the this error message actually uses ASCII
-        only. If this ceases to be true, we will have to convert. */
-        buffer = alloca( (len+1) * (sizeof *buffer));
-        for( i=0; i<=len; ++i)
-            buffer[i] = msg[i];
-        OutputDebugStringW(L"Fatal Python error: ");
-        OutputDebugStringW(buffer);
-        OutputDebugStringW(L"\n");
-    }
-#ifdef _DEBUG
-    DebugBreak();
-#endif
-#endif /* MS_WINDOWS */
-    abort();
-}
-
-/* Clean up and exit */
-
-#ifdef WITH_THREAD
-#include "pythread.h"
-#endif
-
-static void (*pyexitfunc)(void) = NULL;
-/* For the atexit module. */
-void _Py_PyAtExit(void (*func)(void))
-{
-    pyexitfunc = func;
-}
-
-static void
-call_py_exitfuncs(void)
-{
-    if (pyexitfunc == NULL)
-        return;
-
-    (*pyexitfunc)();
-    PyErr_Clear();
-}
-
-/* Wait until threading._shutdown completes, provided
-   the threading module was imported in the first place.
-   The shutdown routine will wait until all non-daemon
-   "threading" threads have completed. */
-static void
-wait_for_thread_shutdown(void)
-{
-#ifdef WITH_THREAD
-    _Py_IDENTIFIER(_shutdown);
-    PyObject *result;
-    PyThreadState *tstate = PyThreadState_GET();
-    PyObject *threading = PyMapping_GetItemString(tstate->interp->modules,
-                                                  "threading");
-    if (threading == NULL) {
-        /* threading not imported */
-        PyErr_Clear();
-        return;
-    }
-    result = _PyObject_CallMethodId(threading, &PyId__shutdown, "");
-    if (result == NULL) {
-        PyErr_WriteUnraisable(threading);
-    }
-    else {
-        Py_DECREF(result);
-    }
-    Py_DECREF(threading);
-#endif
-}
-
-#define NEXITFUNCS 32
-static void (*exitfuncs[NEXITFUNCS])(void);
-static int nexitfuncs = 0;
-
-int Py_AtExit(void (*func)(void))
-{
-    if (nexitfuncs >= NEXITFUNCS)
-        return -1;
-    exitfuncs[nexitfuncs++] = func;
-    return 0;
-}
-
-static void
-call_ll_exitfuncs(void)
-{
-    while (nexitfuncs > 0)
-        (*exitfuncs[--nexitfuncs])();
-
-    fflush(stdout);
-    fflush(stderr);
-}
-
-void
-Py_Exit(int sts)
-{
-    Py_Finalize();
-
-    exit(sts);
-}
-
-static void
-initsigs(void)
-{
-#ifdef SIGPIPE
-    PyOS_setsig(SIGPIPE, SIG_IGN);
-#endif
-#ifdef SIGXFZ
-    PyOS_setsig(SIGXFZ, SIG_IGN);
-#endif
-#ifdef SIGXFSZ
-    PyOS_setsig(SIGXFSZ, SIG_IGN);
-#endif
-    PyOS_InitInterrupts(); /* May imply initsignal() */
-    if (PyErr_Occurred()) {
-        Py_FatalError("Py_Initialize: can't import signal");
-    }
-}
-
-
-/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL.
- *
- * All of the code in this function must only use async-signal-safe functions,
- * listed at `man 7 signal` or
- * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
- */
-void
-_Py_RestoreSignals(void)
-{
-#ifdef SIGPIPE
-    PyOS_setsig(SIGPIPE, SIG_DFL);
-#endif
-#ifdef SIGXFZ
-    PyOS_setsig(SIGXFZ, SIG_DFL);
-#endif
-#ifdef SIGXFSZ
-    PyOS_setsig(SIGXFSZ, SIG_DFL);
-#endif
-}
-
-
-/*
- * The file descriptor fd is considered ``interactive'' if either
- *   a) isatty(fd) is TRUE, or
- *   b) the -i flag was given, and the filename associated with
- *      the descriptor is NULL or "<stdin>" or "???".
- */
-int
-Py_FdIsInteractive(FILE *fp, const char *filename)
-{
-    if (isatty((int)fileno(fp)))
-        return 1;
-    if (!Py_InteractiveFlag)
-        return 0;
-    return (filename == NULL) ||
-           (strcmp(filename, "<stdin>") == 0) ||
-           (strcmp(filename, "???") == 0);
-}
-
 
 #if defined(USE_STACKCHECK)
 #if defined(WIN32) && defined(_MSC_VER)
@@ -2816,73 +1413,6 @@
 
 #endif /* USE_STACKCHECK */
 
-
-/* Wrappers around sigaction() or signal(). */
-
-PyOS_sighandler_t
-PyOS_getsig(int sig)
-{
-#ifdef HAVE_SIGACTION
-    struct sigaction context;
-    if (sigaction(sig, NULL, &context) == -1)
-        return SIG_ERR;
-    return context.sa_handler;
-#else
-    PyOS_sighandler_t handler;
-/* Special signal handling for the secure CRT in Visual Studio 2005 */
-#if defined(_MSC_VER) && _MSC_VER >= 1400
-    switch (sig) {
-    /* Only these signals are valid */
-    case SIGINT:
-    case SIGILL:
-    case SIGFPE:
-    case SIGSEGV:
-    case SIGTERM:
-    case SIGBREAK:
-    case SIGABRT:
-        break;
-    /* Don't call signal() with other values or it will assert */
-    default:
-        return SIG_ERR;
-    }
-#endif /* _MSC_VER && _MSC_VER >= 1400 */
-    handler = signal(sig, SIG_IGN);
-    if (handler != SIG_ERR)
-        signal(sig, handler);
-    return handler;
-#endif
-}
-
-/*
- * All of the code in this function must only use async-signal-safe functions,
- * listed at `man 7 signal` or
- * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
- */
-PyOS_sighandler_t
-PyOS_setsig(int sig, PyOS_sighandler_t handler)
-{
-#ifdef HAVE_SIGACTION
-    /* Some code in Modules/signalmodule.c depends on sigaction() being
-     * used here if HAVE_SIGACTION is defined.  Fix that if this code
-     * changes to invalidate that assumption.
-     */
-    struct sigaction context, ocontext;
-    context.sa_handler = handler;
-    sigemptyset(&context.sa_mask);
-    context.sa_flags = 0;
-    if (sigaction(sig, &context, &ocontext) == -1)
-        return SIG_ERR;
-    return ocontext.sa_handler;
-#else
-    PyOS_sighandler_t oldhandler;
-    oldhandler = signal(sig, handler);
-#ifdef HAVE_SIGINTERRUPT
-    siginterrupt(sig, 1);
-#endif
-    return oldhandler;
-#endif
-}
-
 /* Deprecated C API functions still provided for binary compatiblity */
 
 #undef PyParser_SimpleParseFile
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -1681,7 +1681,7 @@
     }
 #endif
 
-    /* stdin/stdout/stderr are now set by pythonrun.c */
+    /* stdin/stdout/stderr are set in pylifecycle.c */
 
     SET_SYS_FROM_STRING_BORROW("__displayhook__",
                                PyDict_GetItemString(sysdict, "displayhook"));

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list