bpo-36763: Implement the PEP 587 (GH-13592)

* Add a whole new documentation page:
  "Python Initialization Configuration"
* PyWideStringList_Append() return type is now PyStatus,
  instead of int
* PyInterpreterState_New() now calls PyConfig_Clear() if
  PyConfig_InitPythonConfig() fails.
* Rename files:

  * Python/coreconfig.c => Python/initconfig.c
  * Include/cpython/coreconfig.h => Include/cpython/initconfig.h
  * Include/internal/: pycore_coreconfig.h => pycore_initconfig.h

* Rename structures

  * _PyCoreConfig => PyConfig
  * _PyPreConfig => PyPreConfig
  * _PyInitError => PyStatus
  * _PyWstrList => PyWideStringList

* Rename PyConfig fields:

  * use_module_search_paths => module_search_paths_set
  * module_search_path_env => pythonpath_env

* Rename PyStatus field: _func => func
* PyInterpreterState: rename core_config field to config
* Rename macros and functions:

  * _PyCoreConfig_SetArgv() => PyConfig_SetBytesArgv()
  * _PyCoreConfig_SetWideArgv() => PyConfig_SetArgv()
  * _PyCoreConfig_DecodeLocale() => PyConfig_SetBytesString()
  * _PyInitError_Failed() => PyStatus_Exception()
  * _Py_INIT_ERROR_TYPE_xxx enums => _PyStatus_TYPE_xxx
  * _Py_UnixMain() => Py_BytesMain()
  * _Py_ExitInitError() => Py_ExitStatusException()
  * _Py_PreInitializeFromArgs() => Py_PreInitializeFromBytesArgs()
  * _Py_PreInitializeFromWideArgs() => Py_PreInitializeFromArgs()
  * _Py_PreInitialize() => Py_PreInitialize()
  * _Py_RunMain() => Py_RunMain()
  * _Py_InitializeFromConfig() => Py_InitializeFromConfig()
  * _Py_INIT_XXX() => _PyStatus_XXX()
  * _Py_INIT_FAILED() => _PyStatus_EXCEPTION()

* Rename 'err' PyStatus variables to 'status'
* Convert RUN_CODE() macro to config_run_code() static inline function
* Remove functions:

  * _Py_InitializeFromArgs()
  * _Py_InitializeFromWideArgs()
  * _PyInterpreterState_GetCoreConfig()
diff --git a/Doc/c-api/index.rst b/Doc/c-api/index.rst
index 3bfbaf4..9a8f150 100644
--- a/Doc/c-api/index.rst
+++ b/Doc/c-api/index.rst
@@ -21,6 +21,7 @@
    abstract.rst
    concrete.rst
    init.rst
+   init_config.rst
    memory.rst
    objimpl.rst
    apiabiversion.rst
diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst
new file mode 100644
index 0000000..0d94e6b
--- /dev/null
+++ b/Doc/c-api/init_config.rst
@@ -0,0 +1,1018 @@
+.. highlight:: c
+
+.. _init-config:
+
+***********************************
+Python Initialization Configuration
+***********************************
+
+.. versionadded:: 3.8
+
+Structures:
+
+* :c:type:`PyConfig`
+* :c:type:`PyPreConfig`
+* :c:type:`PyStatus`
+* :c:type:`PyWideStringList`
+
+Functions:
+
+* :c:func:`PyConfig_Clear`
+* :c:func:`PyConfig_InitIsolatedConfig`
+* :c:func:`PyConfig_InitPythonConfig`
+* :c:func:`PyConfig_Read`
+* :c:func:`PyConfig_SetArgv`
+* :c:func:`PyConfig_SetBytesArgv`
+* :c:func:`PyConfig_SetBytesString`
+* :c:func:`PyConfig_SetString`
+* :c:func:`PyPreConfig_InitIsolatedConfig`
+* :c:func:`PyPreConfig_InitPythonConfig`
+* :c:func:`PyStatus_Error`
+* :c:func:`PyStatus_Exception`
+* :c:func:`PyStatus_Exit`
+* :c:func:`PyStatus_IsError`
+* :c:func:`PyStatus_IsExit`
+* :c:func:`PyStatus_NoMemory`
+* :c:func:`PyStatus_Ok`
+* :c:func:`PyWideStringList_Append`
+* :c:func:`PyWideStringList_Insert`
+* :c:func:`Py_ExitStatusException`
+* :c:func:`Py_InitializeFromConfig`
+* :c:func:`Py_PreInitialize`
+* :c:func:`Py_PreInitializeFromArgs`
+* :c:func:`Py_PreInitializeFromBytesArgs`
+* :c:func:`Py_RunMain`
+
+The preconfiguration (``PyPreConfig`` type) is stored in
+``_PyRuntime.preconfig`` and the configuration (``PyConfig`` type) is stored in
+``PyInterpreterState.config``.
+
+.. seealso::
+   :pep:`587` "Python Initialization Configuration".
+
+
+PyWideStringList
+----------------
+
+.. c:type:: PyWideStringList
+
+   List of ``wchar_t*`` strings.
+
+   If *length* is non-zero, *items* must be non-NULL and all strings must be
+   non-NULL.
+
+   Methods:
+
+   .. c:function:: PyStatus PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
+
+      Append *item* to *list*.
+
+      Python must be preinitialized to call this function.
+
+   .. c:function:: PyStatus PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item)
+
+      Insert *item* into *list* at *index*. If *index* is greater than *list*
+      length, just append *item* to *list*.
+
+      Python must be preinitialized to call this function.
+
+   Structure fields:
+
+   .. c:member:: Py_ssize_t length
+
+      List length.
+
+   .. c:member:: wchar_t** items
+
+      List items.
+
+PyStatus
+--------
+
+.. c:type:: PyStatus
+
+   Structure to store an initialization function status: success, error
+   or exit.
+
+   For an error, it can store the C function name which created the error.
+
+   Structure fields:
+
+   .. c:member:: int exitcode
+
+      Exit code. Argument passed to ``exit()``.
+
+   .. c:member:: const char *err_msg
+
+      Error message.
+
+   .. c:member:: const char *func
+
+      Name of the function which created an error, can be ``NULL``.
+
+   Functions to create a status:
+
+   .. c:function:: PyStatus PyStatus_Ok(void)
+
+      Success.
+
+   .. c:function:: PyStatus PyStatus_Error(const char *err_msg)
+
+      Initialization error with a message.
+
+   .. c:function:: PyStatus PyStatus_NoMemory(void)
+
+      Memory allocation failure (out of memory).
+
+   .. c:function:: PyStatus PyStatus_Exit(int exitcode)
+
+      Exit Python with the specified exit code.
+
+   Functions to handle a status:
+
+   .. c:function:: int PyStatus_Exception(PyStatus status)
+
+      Is the status an error or an exit? If true, the exception must be
+      handled; by calling :c:func:`Py_ExitStatusException` for example.
+
+   .. c:function:: int PyStatus_IsError(PyStatus status)
+
+      Is the result an error?
+
+   .. c:function:: int PyStatus_IsExit(PyStatus status)
+
+      Is the result an exit?
+
+   .. c:function:: void Py_ExitStatusException(PyStatus status)
+
+      Call ``exit(exitcode)`` if *status* is an exit. Print the error
+      message and exit with a non-zero exit code if *status* is an error.  Must
+      only be called if ``PyStatus_Exception(status)`` is non-zero.
+
+.. note::
+   Internally, Python uses macros which set ``PyStatus.func``,
+   whereas functions to create a status set ``func`` to ``NULL``.
+
+Example::
+
+    PyStatus alloc(void **ptr, size_t size)
+    {
+        *ptr = PyMem_RawMalloc(size);
+        if (*ptr == NULL) {
+            return PyStatus_NoMemory();
+        }
+        return PyStatus_Ok();
+    }
+
+    int main(int argc, char **argv)
+    {
+        void *ptr;
+        PyStatus status = alloc(&ptr, 16);
+        if (PyStatus_Exception(status)) {
+            Py_ExitStatusException(status);
+        }
+        PyMem_Free(ptr);
+        return 0;
+    }
+
+
+PyPreConfig
+-----------
+
+.. c:type:: PyPreConfig
+
+   Structure used to preinitialize Python:
+
+   * Set the Python memory allocator
+   * Configure the LC_CTYPE locale
+   * Set the UTF-8 mode
+
+   Function to initialize a preconfiguration:
+
+   .. c:function:: void PyPreConfig_InitIsolatedConfig(PyPreConfig *preconfig)
+
+      Initialize the preconfiguration with :ref:`Python Configuration
+      <init-python-config>`.
+
+   .. c:function:: void PyPreConfig_InitPythonConfig(PyPreConfig *preconfig)
+
+      Initialize the preconfiguration with :ref:`Isolated Configuration
+      <init-isolated-conf>`.
+
+   Structure fields:
+
+   .. c:member:: int allocator
+
+      Name of the memory allocator:
+
+      * ``PYMEM_ALLOCATOR_NOT_SET`` (``0``): don't change memory allocators
+        (use defaults)
+      * ``PYMEM_ALLOCATOR_DEFAULT`` (``1``): default memory allocators
+      * ``PYMEM_ALLOCATOR_DEBUG`` (``2``): default memory allocators with
+        debug hooks
+      * ``PYMEM_ALLOCATOR_MALLOC`` (``3``): force usage of ``malloc()``
+      * ``PYMEM_ALLOCATOR_MALLOC_DEBUG`` (``4``): force usage of
+        ``malloc()`` with debug hooks
+      * ``PYMEM_ALLOCATOR_PYMALLOC`` (``5``): :ref:`Python pymalloc memory
+        allocator <pymalloc>`
+      * ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG`` (``6``): :ref:`Python pymalloc
+        memory allocator <pymalloc>` with debug hooks
+
+      ``PYMEM_ALLOCATOR_PYMALLOC`` and ``PYMEM_ALLOCATOR_PYMALLOC_DEBUG``
+      are not supported if Python is configured using ``--without-pymalloc``
+
+      See :ref:`Memory Management <memory>`.
+
+   .. c:member:: int configure_locale
+
+      Set the LC_CTYPE locale to the user preferred locale? If equals to 0, set
+      :c:member:`coerce_c_locale` and :c:member:`coerce_c_locale_warn` to 0.
+
+   .. c:member:: int coerce_c_locale
+
+      If equals to 2, coerce the C locale; if equals to 1, read the LC_CTYPE
+      locale to decide if it should be coerced.
+
+   .. c:member:: int coerce_c_locale_warn
+      If non-zero, emit a warning if the C locale is coerced.
+
+   .. c:member:: int dev_mode
+
+      See :c:member:`PyConfig.dev_mode`.
+
+   .. c:member:: int isolated
+
+      See :c:member:`PyConfig.isolated`.
+
+   .. c:member:: int legacy_windows_fs_encoding (Windows only)
+
+      If non-zero, disable UTF-8 Mode, set the Python filesystem encoding to
+      ``mbcs``, set the filesystem error handler to ``replace``.
+
+      Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
+      Windows specific code.
+
+   .. c:member:: int parse_argv
+
+      If non-zero, :c:func:`Py_PreInitializeFromArgs` and
+      :c:func:`Py_PreInitializeFromBytesArgs` parse their ``argv`` argument the
+      same way the regular Python parses command line arguments: see
+      :ref:`Command Line Arguments <using-on-cmdline>`.
+
+   .. c:member:: int use_environment
+
+      See :c:member:`PyConfig.use_environment`.
+
+   .. c:member:: int utf8_mode
+
+      If non-zero, enable the UTF-8 mode.
+
+Preinitialization with PyPreConfig
+----------------------------------
+
+Functions to preinitialize Python:
+
+.. c:function:: PyStatus Py_PreInitialize(const PyPreConfig *preconfig)
+
+   Preinitialize Python from *preconfig* preconfiguration.
+
+.. c:function:: PyStatus Py_PreInitializeFromBytesArgs(const PyPreConfig *preconfig, int argc, char * const *argv)
+
+   Preinitialize Python from *preconfig* preconfiguration and command line
+   arguments (bytes strings).
+
+.. c:function:: PyStatus Py_PreInitializeFromArgs(const PyPreConfig *preconfig, int argc, wchar_t * const * argv)
+
+   Preinitialize Python from *preconfig* preconfiguration and command line
+   arguments (wide strings).
+
+The caller is responsible to handle exceptions (error or exit) using
+:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`.
+
+For :ref:`Python Configuration <init-python-config>`
+(:c:func:`PyPreConfig_InitPythonConfig`), if Python is initialized with
+command line arguments, the command line arguments must also be passed to
+preinitialize Python, since they have an effect on the pre-configuration
+like encodings. For example, the :option:`-X` ``utf8`` command line option
+enables the UTF-8 Mode.
+
+``PyMem_SetAllocator()`` can be called after :c:func:`Py_PreInitialize` and
+before :c:func:`Py_InitializeFromConfig` to install a custom memory allocator.
+It can be called before :c:func:`Py_PreInitialize` if
+:c:member:`PyPreConfig.allocator` is set to ``PYMEM_ALLOCATOR_NOT_SET``.
+
+Python memory allocation functions like :c:func:`PyMem_RawMalloc` must not be
+used before Python preinitialization, whereas calling directly ``malloc()`` and
+``free()`` is always safe. :c:func:`Py_DecodeLocale` must not be called before
+the preinitialization.
+
+Example using the preinitialization to enable the UTF-8 Mode::
+
+    PyPreConfig preconfig;
+    PyPreConfig_InitPythonConfig(&preconfig);
+
+    preconfig.utf8_mode = 1;
+
+    PyStatus status = Py_PreInitialize(&preconfig);
+    if (PyStatus_Exception(status)) {
+        Py_ExitStatusException(status);
+    }
+
+    /* at this point, Python will speak UTF-8 */
+
+    Py_Initialize();
+    /* ... use Python API here ... */
+    Py_Finalize();
+
+
+PyConfig
+--------
+
+.. c:type:: PyConfig
+
+   Structure containing most parameters to configure Python.
+
+   Structure methods:
+
+   .. c:function:: PyStatus PyConfig_InitPythonConfig(PyConfig *config)
+
+      Initialize configuration with :ref:`Python Configuration
+      <init-python-config>`.
+
+   .. c:function:: PyStatus PyConfig_InitIsolatedConfig(PyConfig *config)
+
+      Initialize configuration with :ref:`Isolated Configuration
+      <init-isolated-conf>`.
+
+   .. c:function:: PyStatus PyConfig_SetString(PyConfig *config, wchar_t * const *config_str, const wchar_t *str)
+
+      Copy the wide character string *str* into ``*config_str``.
+
+      Preinitialize Python if needed.
+
+   .. c:function:: PyStatus PyConfig_SetBytesString(PyConfig *config, wchar_t * const *config_str, const char *str)
+
+      Decode *str* using ``Py_DecodeLocale()`` and set the result into ``*config_str``.
+
+      Preinitialize Python if needed.
+
+   .. c:function:: PyStatus PyConfig_SetArgv(PyConfig *config, int argc, wchar_t * const *argv)
+
+      Set command line arguments from wide character strings.
+
+      Preinitialize Python if needed.
+
+   .. c:function:: PyStatus PyConfig_SetBytesArgv(PyConfig *config, int argc, char * const *argv)
+
+      Set command line arguments: decode bytes using :c:func:`Py_DecodeLocale`.
+
+      Preinitialize Python if needed.
+
+   .. c:function:: PyStatus PyConfig_Read(PyConfig *config)
+
+      Read all Python configuration.
+
+      Fields which are already initialized are left unchanged.
+
+      Preinitialize Python if needed.
+
+   .. c:function:: void PyConfig_Clear(PyConfig *config)
+
+      Release configuration memory.
+
+   Most ``PyConfig`` methods preinitialize Python if needed. In that case, the
+   Python preinitialization configuration in based on the :c:type:`PyConfig`.
+   If configuration fields which are in common with :c:type:`PyPreConfig` are
+   tuned, they must be set before calling a :c:type:`PyConfig` method:
+
+   * :c:member:`~PyConfig.dev_mode`
+   * :c:member:`~PyConfig.isolated`
+   * :c:member:`~PyConfig.parse_argv`
+   * :c:member:`~PyConfig.use_environment`
+
+   Moreover, if :c:func:`PyConfig_SetArgv` or :c:func:`PyConfig_SetBytesArgv`
+   is used, this method must be called first, before other methods, since the
+   preinitialization configuration depends on command line arguments (if
+   :c:member:`parse_argv` is non-zero).
+
+   The caller of these methods is responsible to handle exceptions (error or
+   exit) using ``PyStatus_Exception()`` and ``Py_ExitStatusException()``.
+
+   Structure fields:
+
+   .. c:member:: PyWideStringList argv
+
+      Command line arguments, :data:`sys.argv`. See
+      :c:member:`~PyConfig.parse_argv` to parse :c:member:`~PyConfig.argv` the
+      same way the regular Python parses Python command line arguments. If
+      :c:member:`~PyConfig.argv` is empty, an empty string is added to ensure
+      that :data:`sys.argv` always exists and is never empty.
+
+   .. c:member:: wchar_t* base_exec_prefix
+
+      :data:`sys.base_exec_prefix`.
+
+   .. c:member:: wchar_t* base_prefix
+
+      :data:`sys.base_prefix`.
+
+   .. c:member:: int buffered_stdio
+
+      If equals to 0, enable unbuffered mode, making the stdout and stderr
+      streams unbuffered.
+
+      stdin is always opened in buffered mode.
+
+   .. c:member:: int bytes_warning
+
+      If equals to 1, issue a warning when comparing :class:`bytes` or
+      :class:`bytearray` with :class:`str`, or comparing :class:`bytes` with
+      :class:`int`. If equal or greater to 2, raise a :exc:`BytesWarning`
+      exception.
+
+   .. c:member:: wchar_t* check_hash_pycs_mode
+
+      Control the validation behavior of hash-based ``.pyc`` files (see
+      :pep:`552`): :option:`--check-hash-based-pycs` command line option value.
+
+      Valid values: ``always``, ``never`` and ``default``.
+
+      The default value is: ``default``.
+
+   .. c:member:: int configure_c_stdio
+
+      If non-zero, configure C standard streams (``stdio``, ``stdout``,
+      ``stdout``). For example, set their mode to ``O_BINARY`` on Windows.
+
+   .. c:member:: int dev_mode
+
+      Development mode: see :option:`-X` ``dev``.
+
+   .. c:member:: int dump_refs
+
+      If non-zero, dump all objects which are still alive at exit.
+
+      Require a debug build of Python (``Py_REF_DEBUG`` macro must be defined).
+
+   .. c:member:: wchar_t* exec_prefix
+
+      :data:`sys.exec_prefix`.
+
+   .. c:member:: wchar_t* executable
+
+      :data:`sys.executable`.
+
+   .. c:member:: int faulthandler
+
+      If non-zero, call :func:`faulthandler.enable`.
+
+   .. c:member:: wchar_t* filesystem_encoding
+
+      Filesystem encoding, :func:`sys.getfilesystemencoding`.
+
+   .. c:member:: wchar_t* filesystem_errors
+
+      Filesystem encoding errors, :func:`sys.getfilesystemencodeerrors`.
+
+   .. c:member:: unsigned long hash_seed
+   .. c:member:: int use_hash_seed
+
+      Randomized hash function seed.
+
+      If :c:member:`~PyConfig.use_hash_seed` is zero, a seed is chosen randomly
+      at Pythonstartup, and :c:member:`~PyConfig.hash_seed` is ignored.
+
+   .. c:member:: wchar_t* home
+
+      Python home directory.
+
+   .. c:member:: int import_time
+
+      If non-zero, profile import time.
+
+   .. c:member:: int inspect
+
+      Enter interactive mode after executing a script or a command.
+
+   .. c:member:: int install_signal_handlers
+
+      Install signal handlers?
+
+   .. c:member:: int interactive
+
+      Interactive mode.
+
+   .. c:member:: int isolated
+
+      If greater than 0, enable isolated mode:
+
+      * :data:`sys.path` contains neither the script's directory (computed from
+        ``argv[0]`` or the current directory) nor the user's site-packages
+        directory.
+      * Python REPL doesn't import :mod:`readline` nor enable default readline
+        configuration on interactive prompts.
+      * Set :c:member:`~PyConfig.use_environment` and
+        :c:member:`~PyConfig.user_site_directory` to 0.
+
+   .. c:member:: int legacy_windows_stdio
+
+      If non-zero, use :class:`io.FileIO` instead of
+      :class:`io.WindowsConsoleIO` for :data:`sys.stdin`, :data:`sys.stdout`
+      and :data:`sys.stderr`.
+
+      Only available on Windows. ``#ifdef MS_WINDOWS`` macro can be used for
+      Windows specific code.
+
+   .. c:member:: int malloc_stats
+
+      If non-zero, dump statistics on :ref:`Python pymalloc memory allocator
+      <pymalloc>` at exit.
+
+      The option is ignored if Python is built using ``--without-pymalloc``.
+
+   .. c:member:: wchar_t* pythonpath_env
+
+      Module search paths as a string separated by ``DELIM``
+      (:data:`os.path.pathsep`).
+
+      Initialized from :envvar:`PYTHONPATH` environment variable value by
+      default.
+
+   .. c:member:: PyWideStringList module_search_paths
+   .. c:member:: int module_search_paths_set
+
+      :data:`sys.path`. If :c:member:`~PyConfig.module_search_paths_set` is
+      equal to 0, the :c:member:`~PyConfig.module_search_paths` is overridden
+      by the function computing the :ref:`Path Configuration
+      <init-path-config>`.
+
+   .. c:member:: int optimization_level
+
+      Compilation optimization level:
+
+      * 0: Peephole optimizer (and ``__debug__`` is set to ``True``)
+      * 1: Remove assertions, set ``__debug__`` to ``False``
+      * 2: Strip docstrings
+
+   .. c:member:: int parse_argv
+
+      If non-zero, parse :c:member:`~PyConfig.argv` the same way the regular
+      Python command line arguments, and strip Python arguments from
+      :c:member:`~PyConfig.argv`: see :ref:`Command Line Arguments
+      <using-on-cmdline>`.
+
+   .. c:member:: int parser_debug
+
+      If non-zero, turn on parser debugging output (for expert only, depending
+      on compilation options).
+
+   .. c:member:: int pathconfig_warnings
+
+      If equal to 0, suppress warnings when computing the path configuration
+      (Unix only, Windows does not log any warning). Otherwise, warnings are
+      written into ``stderr``.
+
+   .. c:member:: wchar_t* prefix
+
+      :data:`sys.prefix`.
+
+   .. c:member:: wchar_t* program_name
+
+      Program name.
+
+   .. c:member:: wchar_t* pycache_prefix
+
+      ``.pyc`` cache prefix.
+
+   .. c:member:: int quiet
+
+      Quiet mode. For example, don't display the copyright and version messages
+      even in interactive mode.
+
+   .. c:member:: wchar_t* run_command
+
+      ``python3 -c COMMAND`` argument.
+
+   .. c:member:: wchar_t* run_filename
+
+      ``python3 FILENAME`` argument.
+
+   .. c:member:: wchar_t* run_module
+
+      ``python3 -m MODULE`` argument.
+
+   .. c:member:: int show_alloc_count
+
+      Show allocation counts at exit?
+
+      Need a special Python build with ``COUNT_ALLOCS`` macro defined.
+
+   .. c:member:: int show_ref_count
+
+      Show total reference count at exit?
+
+      Need a debug build of Python (``Py_REF_DEBUG`` macro must be defined).
+
+   .. c:member:: int site_import
+
+      Import the :mod:`site` module at startup?
+
+   .. c:member:: int skip_source_first_line
+
+      Skip the first line of the source?
+
+   .. c:member:: wchar_t* stdio_encoding
+   .. c:member:: wchar_t* stdio_errors
+
+      Encoding and encoding errors of :data:`sys.stdin`, :data:`sys.stdout` and
+      :data:`sys.stderr`.
+
+   .. c:member:: int tracemalloc
+
+      If non-zero, call :func:`tracemalloc.start`.
+
+   .. c:member:: int use_environment
+
+      If greater than 0, use :ref:`environment variables <using-on-envvars>`.
+
+   .. c:member:: int user_site_directory
+
+      If non-zero, add user site directory to :data:`sys.path`.
+
+   .. c:member:: int verbose
+
+      If non-zero, enable verbose mode.
+
+   .. c:member:: PyWideStringList warnoptions
+
+      Options of the :mod:`warnings` module to build warnings filters.
+
+   .. c:member:: int write_bytecode
+
+      If non-zero, write ``.pyc`` files.
+
+   .. c:member:: PyWideStringList xoptions
+
+      :data:`sys._xoptions`.
+
+If ``parse_argv`` is non-zero, ``argv`` arguments are parsed the same
+way the regular Python parses command line arguments, and Python
+arguments are stripped from ``argv``: see :ref:`Command Line Arguments
+<using-on-cmdline>`.
+
+The ``xoptions`` options are parsed to set other options: see :option:`-X`
+option.
+
+
+Initialization with PyConfig
+----------------------------
+
+Function to initialize Python:
+
+.. c:function:: PyStatus Py_InitializeFromConfig(const PyConfig *config)
+
+   Initialize Python from *config* configuration.
+
+The caller is responsible to handle exceptions (error or exit) using
+:c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`.
+
+``PyImport_FrozenModules``, ``PyImport_AppendInittab()`` or
+``PyImport_ExtendInittab()`` is used: they must be set or called after Python
+preinitialization and before the Python initialization.
+
+Example setting the program name::
+
+    void init_python(void)
+    {
+        PyStatus status;
+        PyConfig config;
+
+        status = PyConfig_InitPythonConfig(&config);
+        if (PyStatus_Exception(status)) {
+            goto fail;
+        }
+
+        /* Set the program name. Implicitly preinitialize Python. */
+        status = PyConfig_SetString(&config, &config.program_name,
+                                    L"/path/to/my_program");
+        if (PyStatus_Exception(status)) {
+            goto fail;
+        }
+
+        status = Py_InitializeFromConfig(&config);
+        if (PyStatus_Exception(status)) {
+            goto fail;
+        }
+        PyConfig_Clear(&config);
+        return;
+
+    fail:
+        PyConfig_Clear(&config);
+        Py_ExitStatusException(status);
+    }
+
+More complete example modifying the default configuration, read the
+configuration, and then override some parameters::
+
+    PyStatus init_python(const char *program_name)
+    {
+        PyStatus status;
+        PyConfig config;
+
+        status = PyConfig_InitPythonConfig(&config);
+        if (PyStatus_Exception(status)) {
+            goto done;
+        }
+
+        /* Set the program name before reading the configuraton
+           (decode byte string from the locale encoding).
+
+           Implicitly preinitialize Python. */
+        status = PyConfig_SetBytesString(&config, &config.program_name,
+                                      program_name);
+        if (PyStatus_Exception(status)) {
+            goto done;
+        }
+
+        /* Read all configuration at once */
+        status = PyConfig_Read(&config);
+        if (PyStatus_Exception(status)) {
+            goto done;
+        }
+
+        /* Append our custom search path to sys.path */
+        status = PyWideStringList_Append(&config.module_search_paths,
+                                      L"/path/to/more/modules");
+        if (PyStatus_Exception(status)) {
+            goto done;
+        }
+
+        /* Override executable computed by PyConfig_Read() */
+        status = PyConfig_SetString(&config, &config.executable,
+                                    L"/path/to/my_executable");
+        if (PyStatus_Exception(status)) {
+            goto done;
+        }
+
+        status = Py_InitializeFromConfig(&config);
+
+    done:
+        PyConfig_Clear(&config);
+        return status;
+    }
+
+
+.. _init-isolated-conf:
+
+Isolated Configuration
+----------------------
+
+:c:func:`PyPreConfig_InitIsolatedConfig` and
+:c:func:`PyConfig_InitIsolatedConfig` functions create a configuration to
+isolate Python from the system. For example, to embed Python into an
+application.
+
+This configuration ignores global configuration variables, environments
+variables and command line arguments (:c:member:`PyConfig.argv` is not parsed).
+The C standard streams (ex: ``stdout``) and the LC_CTYPE locale are left
+unchanged by default.
+
+Configuration files are still used with this configuration. Set the
+:ref:`Path Configuration <init-path-config>` ("output fields") to ignore these
+configuration files and avoid the function computing the default path
+configuration.
+
+
+.. _init-python-config:
+
+Python Configuration
+--------------------
+
+:c:func:`PyPreConfig_InitPythonConfig` and :c:func:`PyConfig_InitPythonConfig`
+functions create a configuration to build a customized Python which behaves as
+the regular Python.
+
+Environments variables and command line arguments are used to configure
+Python, whereas global configuration variables are ignored.
+
+This function enables C locale coercion (:pep:`538`) and UTF-8 Mode
+(:pep:`540`) depending on the LC_CTYPE locale, :envvar:`PYTHONUTF8` and
+:envvar:`PYTHONCOERCECLOCALE` environment variables.
+
+Example of customized Python always running in isolated mode::
+
+    int main(int argc, char **argv)
+    {
+        PyConfig config;
+        PyStatus status;
+
+        status = PyConfig_InitPythonConfig(&config);
+        if (PyStatus_Exception(status)) {
+            goto fail;
+        }
+
+        config.isolated = 1;
+
+        /* Decode command line arguments.
+           Implicitly preinitialize Python (in isolated mode). */
+        status = PyConfig_SetBytesArgv(&config, argc, argv);
+        if (PyStatus_Exception(status)) {
+            goto fail;
+        }
+
+        status = Py_InitializeFromConfig(&config);
+        if (PyStatus_Exception(status)) {
+            goto fail;
+        }
+        PyConfig_Clear(&config);
+
+        return Py_RunMain();
+
+    fail:
+        PyConfig_Clear(&config);
+        if (PyStatus_IsExit(status)) {
+            return status.exitcode;
+        }
+        /* Display the error message and exit the process with
+           non-zero exit code */
+        Py_ExitStatusException(status);
+    }
+
+
+.. _init-path-config:
+
+Path Configuration
+------------------
+
+:c:type:`PyConfig` contains multiple fields for the path configuration:
+
+* Path configuration input fields:
+
+  * :c:member:`PyConfig.home`
+  * :c:member:`PyConfig.pythonpath_env`
+  * :c:member:`PyConfig.pathconfig_warnings`
+
+* Path configuration output fields:
+
+  * :c:member:`PyConfig.exec_prefix`
+  * :c:member:`PyConfig.executable`
+  * :c:member:`PyConfig.prefix`
+  * :c:member:`PyConfig.module_search_paths_set`,
+    :c:member:`PyConfig.module_search_paths`
+
+If at least one "output field" is not set, Python computes the path
+configuration to fill unset fields. If
+:c:member:`~PyConfig.module_search_paths_set` is equal to 0,
+:c:member:`~PyConfig.module_search_paths` is overriden and
+:c:member:`~PyConfig.module_search_paths_set` is set to 1.
+
+It is possible to completely ignore the function computing the default
+path configuration by setting explicitly all path configuration output
+fields listed above. A string is considered as set even if it is non-empty.
+``module_search_paths`` is considered as set if
+``module_search_paths_set`` is set to 1. In this case, path
+configuration input fields are ignored as well.
+
+Set :c:member:`~PyConfig.pathconfig_warnings` to 0 to suppress warnings when
+computing the path configuration (Unix only, Windows does not log any warning).
+
+If :c:member:`~PyConfig.base_prefix` or :c:member:`~PyConfig.base_exec_prefix`
+fields are not set, they inherit their value from :c:member:`~PyConfig.prefix`
+and :c:member:`~PyConfig.exec_prefix` respectively.
+
+:c:func:`Py_RunMain` and :c:func:`Py_Main` modify :data:`sys.path`:
+
+* If :c:member:`~PyConfig.run_filename` is set and is a directory which contains a
+  ``__main__.py`` script, prepend :c:member:`~PyConfig.run_filename` to
+  :data:`sys.path`.
+* If :c:member:`~PyConfig.isolated` is zero:
+
+  * If :c:member:`~PyConfig.run_module` is set, prepend the current directory
+    to :data:`sys.path`. Do nothing if the current directory cannot be read.
+  * If :c:member:`~PyConfig.run_filename` is set, prepend the directory of the
+    filename to :data:`sys.path`.
+  * Otherwise, prepend an empty string to :data:`sys.path`.
+
+If :c:member:`~PyConfig.site_import` is non-zero, :data:`sys.path` can be
+modified by the :mod:`site` module. If
+:c:member:`~PyConfig.user_site_directory` is non-zero and the user's
+site-package directory exists, the :mod:`site` module appends the user's
+site-package directory to :data:`sys.path`.
+
+The following configuration files are used by the path configuration:
+
+* ``pyvenv.cfg``
+* ``python._pth`` (Windows only)
+* ``pybuilddir.txt`` (Unix only)
+
+
+Py_RunMain()
+------------
+
+.. c:function:: int Py_RunMain(void)
+
+   Execute the command (:c:member:`PyConfig.run_command`), the script
+   (:c:member:`PyConfig.run_filename`) or the module
+   (:c:member:`PyConfig.run_module`) specified on the command line or in the
+   configuration.
+
+   By default and when if :option:`-i` option is used, run the REPL.
+
+   Finally, finalizes Python and returns an exit status that can be passed to
+   the ``exit()`` function.
+
+See :ref:`Python Configuration <init-python-config>` for an example of
+customized Python always running in isolated mode using
+:c:func:`Py_RunMain`.
+
+
+Multi-Phase Initialization Private Provisional API
+--------------------------------------------------
+
+This section is a private provisional API introducing multi-phase
+initialization, the core feature of the :pep:`432`:
+
+* "Core" initialization phase, "bare minimum Python":
+
+  * Builtin types;
+  * Builtin exceptions;
+  * Builtin and frozen modules;
+  * The :mod:`sys` module is only partially initialized
+    (ex: :data:`sys.path` doesn't exist yet);
+
+* "Main" initialization phase, Python is fully initialized:
+
+  * Install and configure :mod:`importlib`;
+  * Apply the :ref:`Path Configuration <init-path-config>`;
+  * Install signal handlers;
+  * Finish :mod:`sys` module initialization (ex: create :data:`sys.stdout`
+    and :data:`sys.path`);
+  * Enable optional features like :mod:`faulthandler` and :mod:`tracemalloc`;
+  * Import the :mod:`site` module;
+  * etc.
+
+Private provisional API:
+
+* :c:member:`PyConfig._init_main`: if set to 0,
+  :c:func:`Py_InitializeFromConfig` stops at the "Core" initialization phase.
+
+.. c:function:: PyStatus _Py_InitializeMain(void)
+
+   Move to the "Main" initialization phase, finish the Python initialization.
+
+No module is imported during the "Core" phase and the ``importlib`` module is
+not configured: the :ref:`Path Configuration <init-path-config>` is only
+applied during the "Main" phase. It may allow to customize Python in Python to
+override or tune the :ref:`Path Configuration <init-path-config>`, maybe
+install a custom sys.meta_path importer or an import hook, etc.
+
+It may become possible to compute the :ref:`Path Configuration
+<init-path-config>` in Python, after the Core phase and before the Main phase,
+which is one of the :pep:`432` motivation.
+
+The "Core" phase is not properly defined: what should be and what should
+not be available at this phase is not specified yet. The API is marked
+as private and provisional: the API can be modified or even be removed
+anytime until a proper public API is designed.
+
+Example running Python code between "Core" and "Main" initialization
+phases::
+
+    void init_python(void)
+    {
+        PyStatus status;
+        PyConfig config;
+
+        status = PyConfig_InitPythonConfig(&config);
+        if (PyStatus_Exception(status)) {
+            PyConfig_Clear(&config);
+            Py_ExitStatusException(status);
+        }
+
+        config._init_main = 0;
+
+        /* ... customize 'config' configuration ... */
+
+        status = Py_InitializeFromConfig(&config);
+        PyConfig_Clear(&config);
+        if (PyStatus_Exception(status)) {
+            Py_ExitStatusException(status);
+        }
+
+        /* Use sys.stderr because sys.stdout is only created
+           by _Py_InitializeMain() */
+        int res = PyRun_SimpleString(
+            "import sys; "
+            "print('Run Python code before _Py_InitializeMain', "
+                   "file=sys.stderr)");
+        if (res < 0) {
+            exit(1);
+        }
+
+        /* ... put more configuration code here ... */
+
+        status = _Py_InitializeMain();
+        if (PyStatus_Exception(status)) {
+            Py_ExitStatusException(status);
+        }
+    }
diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst
index a7ff08c..3fe0ae4 100644
--- a/Doc/c-api/veryhigh.rst
+++ b/Doc/c-api/veryhigh.rst
@@ -42,6 +42,13 @@
    ``Py_InspectFlag`` is not set.
 
 
+.. c:function:: int Py_BytesMain(int argc, char **argv)
+
+   Similar to :c:func:`Py_Main` but *argv* is an array of bytes strings.
+
+   .. versionadded:: 3.8
+
+
 .. c:function:: int PyRun_AnyFile(FILE *fp, const char *filename)
 
    This is a simplified interface to :c:func:`PyRun_AnyFileExFlags` below, leaving