bpo-36763: Fix Python preinitialization (GH-13432)

* Add _PyPreConfig.parse_argv
* Add _PyCoreConfig._config_init field and _PyCoreConfigInitEnum enum
  type
* Initialization functions: reject preconfig=NULL and config=NULL
* Add config parameter to _PyCoreConfig_DecodeLocaleErr(): pass
  config->argv to _Py_PreInitializeFromPyArgv(), to parse config
  command line arguments in preinitialization.
* Add config parameter to _PyCoreConfig_SetString(). It now
  preinitializes Python.
* _PyCoreConfig_SetPyArgv() now also preinitializes Python for wide
  argv
* Fix _Py_PreInitializeFromCoreConfig(): don't pass args to
  _Py_PreInitializeFromPyArgv() if config.parse_argv=0.
* Use "char * const *" and "wchar_t * const *" types for 'argv'
  parameters and _PyArgv.argv.
* Add unit test on preinitialization from argv.
* _PyPreConfig.allocator type becomes int
* Add _PyPreConfig_InitFromPreConfig() and
  _PyPreConfig_InitFromCoreConfig() helper functions
diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h
index a71f161..decfb70 100644
--- a/Include/cpython/coreconfig.h
+++ b/Include/cpython/coreconfig.h
@@ -44,6 +44,10 @@
     int _config_version;  /* Internal configuration version,
                              used for ABI compatibility */
 
+    /* Parse _Py_PreInitializeFromArgs() arguments?
+       See _PyCoreConfig.parse_argv */
+    int parse_argv;
+
     /* If greater than 0, enable isolated mode: sys.path contains
        neither the script's directory nor the user's site-packages directory.
 
@@ -111,8 +115,9 @@
 
     int dev_mode;           /* Development mode. PYTHONDEVMODE, -X dev */
 
-    /* Memory allocator: PYTHONMALLOC env var */
-    PyMemAllocatorName allocator;
+    /* Memory allocator: PYTHONMALLOC env var.
+       See PyMemAllocatorName for valid values. */
+    int allocator;
 } _PyPreConfig;
 
 PyAPI_FUNC(void) _PyPreConfig_InitPythonConfig(_PyPreConfig *config);
@@ -121,9 +126,16 @@
 
 /* --- _PyCoreConfig ---------------------------------------------- */
 
+typedef enum {
+    _PyCoreConfig_INIT = 0,
+    _PyCoreConfig_INIT_PYTHON = 1,
+    _PyCoreConfig_INIT_ISOLATED = 2
+} _PyCoreConfigInitEnum;
+
 typedef struct {
     int _config_version;  /* Internal configuration version,
                              used for ABI compatibility */
+    int _config_init;     /* _PyCoreConfigInitEnum value */
 
     int isolated;         /* Isolated mode? see _PyPreConfig.isolated */
     int use_environment;  /* Use environment variables? see _PyPreConfig.use_environment */
@@ -401,19 +413,21 @@
 PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitIsolatedConfig(_PyCoreConfig *config);
 PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *);
 PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetString(
+    _PyCoreConfig *config,
     wchar_t **config_str,
     const wchar_t *str);
 PyAPI_FUNC(_PyInitError) _PyCoreConfig_DecodeLocale(
+    _PyCoreConfig *config,
     wchar_t **config_str,
     const char *str);
 PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config);
 PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetArgv(
     _PyCoreConfig *config,
     Py_ssize_t argc,
-    char **argv);
+    char * const *argv);
 PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetWideArgv(_PyCoreConfig *config,
     Py_ssize_t argc,
-    wchar_t **argv);
+    wchar_t * const *argv);
 
 #ifdef __cplusplus
 }
diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h
index 8fc809d..1e1dabe 100644
--- a/Include/cpython/pylifecycle.h
+++ b/Include/cpython/pylifecycle.h
@@ -35,11 +35,11 @@
 PyAPI_FUNC(_PyInitError) _Py_InitializeFromArgs(
     const _PyCoreConfig *config,
     Py_ssize_t argc,
-    char **argv);
+    char * const *argv);
 PyAPI_FUNC(_PyInitError) _Py_InitializeFromWideArgs(
     const _PyCoreConfig *config,
     Py_ssize_t argc,
-    wchar_t **argv);
+    wchar_t * const *argv);
 PyAPI_FUNC(_PyInitError) _Py_InitializeMain(void);
 
 PyAPI_FUNC(int) _Py_RunMain(void);
diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h
index edde7b1..324e0b8 100644
--- a/Include/internal/pycore_coreconfig.h
+++ b/Include/internal/pycore_coreconfig.h
@@ -63,8 +63,8 @@
 typedef struct {
     Py_ssize_t argc;
     int use_bytes_argv;
-    char **bytes_argv;
-    wchar_t **wchar_argv;
+    char * const *bytes_argv;
+    wchar_t * const *wchar_argv;
 } _PyArgv;
 
 PyAPI_FUNC(_PyInitError) _PyArgv_AsWstrList(const _PyArgv *args,
@@ -121,6 +121,12 @@
 /* --- _PyPreConfig ----------------------------------------------- */
 
 PyAPI_FUNC(void) _PyPreConfig_Init(_PyPreConfig *config);
+PyAPI_FUNC(void) _PyPreConfig_InitFromCoreConfig(
+    _PyPreConfig *config,
+    const _PyCoreConfig *coreconfig);
+PyAPI_FUNC(void) _PyPreConfig_InitFromPreConfig(
+    _PyPreConfig *config,
+    const _PyPreConfig *config2);
 PyAPI_FUNC(void) _PyPreConfig_Copy(_PyPreConfig *config,
     const _PyPreConfig *config2);
 PyAPI_FUNC(PyObject*) _PyPreConfig_AsDict(const _PyPreConfig *config);