summaryrefslogtreecommitdiffstats
path: root/Python/preconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/preconfig.c')
-rw-r--r--Python/preconfig.c967
1 files changed, 0 insertions, 967 deletions
diff --git a/Python/preconfig.c b/Python/preconfig.c
deleted file mode 100644
index 89a6227..0000000
--- a/Python/preconfig.c
+++ /dev/null
@@ -1,967 +0,0 @@
-#include "Python.h"
-#include "pycore_initconfig.h"
-#include "pycore_getopt.h"
-#include "pycore_pystate.h" /* _PyRuntime_Initialize() */
-#include <locale.h> /* setlocale() */
-
-
-#define DECODE_LOCALE_ERR(NAME, LEN) \
- (((LEN) == -2) \
- ? _PyStatus_ERR("cannot decode " NAME) \
- : _PyStatus_NO_MEMORY())
-
-
-/* Forward declarations */
-static void
-preconfig_copy(PyPreConfig *config, const PyPreConfig *config2);
-
-
-/* --- File system encoding/errors -------------------------------- */
-
-/* The filesystem encoding is chosen by config_init_fs_encoding(),
- see also initfsencoding().
-
- Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
- are encoded to UTF-8. */
-const char *Py_FileSystemDefaultEncoding = NULL;
-int Py_HasFileSystemDefaultEncoding = 0;
-const char *Py_FileSystemDefaultEncodeErrors = NULL;
-int _Py_HasFileSystemDefaultEncodeErrors = 0;
-
-void
-_Py_ClearFileSystemEncoding(void)
-{
- if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
- PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
- Py_FileSystemDefaultEncoding = NULL;
- }
- if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) {
- PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors);
- Py_FileSystemDefaultEncodeErrors = NULL;
- }
-}
-
-
-/* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
- global configuration variables. */
-int
-_Py_SetFileSystemEncoding(const char *encoding, const char *errors)
-{
- char *encoding2 = _PyMem_RawStrdup(encoding);
- if (encoding2 == NULL) {
- return -1;
- }
-
- char *errors2 = _PyMem_RawStrdup(errors);
- if (errors2 == NULL) {
- PyMem_RawFree(encoding2);
- return -1;
- }
-
- _Py_ClearFileSystemEncoding();
-
- Py_FileSystemDefaultEncoding = encoding2;
- Py_HasFileSystemDefaultEncoding = 0;
-
- Py_FileSystemDefaultEncodeErrors = errors2;
- _Py_HasFileSystemDefaultEncodeErrors = 0;
- return 0;
-}
-
-
-/* --- _PyArgv ---------------------------------------------------- */
-
-/* Decode bytes_argv using Py_DecodeLocale() */
-PyStatus
-_PyArgv_AsWstrList(const _PyArgv *args, PyWideStringList *list)
-{
- PyWideStringList wargv = _PyWideStringList_INIT;
- if (args->use_bytes_argv) {
- size_t size = sizeof(wchar_t*) * args->argc;
- wargv.items = (wchar_t **)PyMem_RawMalloc(size);
- if (wargv.items == NULL) {
- return _PyStatus_NO_MEMORY();
- }
-
- for (Py_ssize_t i = 0; i < args->argc; i++) {
- size_t len;
- wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
- if (arg == NULL) {
- _PyWideStringList_Clear(&wargv);
- return DECODE_LOCALE_ERR("command line arguments",
- (Py_ssize_t)len);
- }
- wargv.items[i] = arg;
- wargv.length++;
- }
-
- _PyWideStringList_Clear(list);
- *list = wargv;
- }
- else {
- wargv.length = args->argc;
- wargv.items = (wchar_t **)args->wchar_argv;
- if (_PyWideStringList_Copy(list, &wargv) < 0) {
- return _PyStatus_NO_MEMORY();
- }
- }
- return _PyStatus_OK();
-}
-
-
-/* --- _PyPreCmdline ------------------------------------------------- */
-
-void
-_PyPreCmdline_Clear(_PyPreCmdline *cmdline)
-{
- _PyWideStringList_Clear(&cmdline->argv);
- _PyWideStringList_Clear(&cmdline->xoptions);
-}
-
-
-PyStatus
-_PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)
-{
- return _PyArgv_AsWstrList(args, &cmdline->argv);
-}
-
-
-static void
-precmdline_get_preconfig(_PyPreCmdline *cmdline, const PyPreConfig *config)
-{
-#define COPY_ATTR(ATTR) \
- if (config->ATTR != -1) { \
- cmdline->ATTR = config->ATTR; \
- }
-
- COPY_ATTR(isolated);
- COPY_ATTR(use_environment);
- COPY_ATTR(dev_mode);
-
-#undef COPY_ATTR
-}
-
-
-static void
-precmdline_set_preconfig(const _PyPreCmdline *cmdline, PyPreConfig *config)
-{
-#define COPY_ATTR(ATTR) \
- config->ATTR = cmdline->ATTR
-
- COPY_ATTR(isolated);
- COPY_ATTR(use_environment);
- COPY_ATTR(dev_mode);
-
-#undef COPY_ATTR
-}
-
-
-PyStatus
-_PyPreCmdline_SetConfig(const _PyPreCmdline *cmdline, PyConfig *config)
-{
-#define COPY_ATTR(ATTR) \
- config->ATTR = cmdline->ATTR
-
- PyStatus status = _PyWideStringList_Extend(&config->xoptions, &cmdline->xoptions);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- COPY_ATTR(isolated);
- COPY_ATTR(use_environment);
- COPY_ATTR(dev_mode);
- return _PyStatus_OK();
-
-#undef COPY_ATTR
-}
-
-
-/* Parse the command line arguments */
-static PyStatus
-precmdline_parse_cmdline(_PyPreCmdline *cmdline)
-{
- const PyWideStringList *argv = &cmdline->argv;
-
- _PyOS_ResetGetOpt();
- /* Don't log parsing errors into stderr here: PyConfig_Read()
- is responsible for that */
- _PyOS_opterr = 0;
- do {
- int longindex = -1;
- int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
-
- if (c == EOF || c == 'c' || c == 'm') {
- break;
- }
-
- switch (c) {
- case 'E':
- cmdline->use_environment = 0;
- break;
-
- case 'I':
- cmdline->isolated = 1;
- break;
-
- case 'X':
- {
- PyStatus status = PyWideStringList_Append(&cmdline->xoptions,
- _PyOS_optarg);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
- break;
- }
-
- default:
- /* ignore other argument:
- handled by PyConfig_Read() */
- break;
- }
- } while (1);
-
- return _PyStatus_OK();
-}
-
-
-PyStatus
-_PyPreCmdline_Read(_PyPreCmdline *cmdline, const PyPreConfig *preconfig)
-{
- precmdline_get_preconfig(cmdline, preconfig);
-
- if (preconfig->parse_argv) {
- PyStatus status = precmdline_parse_cmdline(cmdline);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
- }
-
- /* isolated, use_environment */
- if (cmdline->isolated < 0) {
- cmdline->isolated = 0;
- }
- if (cmdline->isolated > 0) {
- cmdline->use_environment = 0;
- }
- if (cmdline->use_environment < 0) {
- cmdline->use_environment = 0;
- }
-
- /* dev_mode */
- if ((cmdline->dev_mode < 0)
- && (_Py_get_xoption(&cmdline->xoptions, L"dev")
- || _Py_GetEnv(cmdline->use_environment, "PYTHONDEVMODE")))
- {
- cmdline->dev_mode = 1;
- }
- if (cmdline->dev_mode < 0) {
- cmdline->dev_mode = 0;
- }
-
- assert(cmdline->use_environment >= 0);
- assert(cmdline->isolated >= 0);
- assert(cmdline->dev_mode >= 0);
-
- return _PyStatus_OK();
-}
-
-
-/* --- PyPreConfig ----------------------------------------------- */
-
-
-void
-_PyPreConfig_InitCompatConfig(PyPreConfig *config)
-{
- memset(config, 0, sizeof(*config));
-
- config->_config_init = (int)_PyConfig_INIT_COMPAT;
- config->parse_argv = 0;
- config->isolated = -1;
- config->use_environment = -1;
- config->configure_locale = 1;
-
- /* bpo-36443: C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
- are disabled by default using the Compat configuration.
-
- Py_UTF8Mode=1 enables the UTF-8 mode. PYTHONUTF8 environment variable
- is ignored (even if use_environment=1). */
- config->utf8_mode = 0;
- config->coerce_c_locale = 0;
- config->coerce_c_locale_warn = 0;
-
- config->dev_mode = -1;
- config->allocator = PYMEM_ALLOCATOR_NOT_SET;
-#ifdef MS_WINDOWS
- config->legacy_windows_fs_encoding = -1;
-#endif
-}
-
-
-void
-PyPreConfig_InitPythonConfig(PyPreConfig *config)
-{
- _PyPreConfig_InitCompatConfig(config);
-
- config->_config_init = (int)_PyConfig_INIT_PYTHON;
- config->isolated = 0;
- config->parse_argv = 1;
- config->use_environment = 1;
- /* Set to -1 to enable C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
- depending on the LC_CTYPE locale, PYTHONUTF8 and PYTHONCOERCECLOCALE
- environment variables. */
- config->coerce_c_locale = -1;
- config->coerce_c_locale_warn = -1;
- config->utf8_mode = -1;
-#ifdef MS_WINDOWS
- config->legacy_windows_fs_encoding = 0;
-#endif
-}
-
-
-void
-PyPreConfig_InitIsolatedConfig(PyPreConfig *config)
-{
- _PyPreConfig_InitCompatConfig(config);
-
- config->_config_init = (int)_PyConfig_INIT_ISOLATED;
- config->configure_locale = 0;
- config->isolated = 1;
- config->use_environment = 0;
- config->utf8_mode = 0;
- config->dev_mode = 0;
-#ifdef MS_WINDOWS
- config->legacy_windows_fs_encoding = 0;
-#endif
-}
-
-
-PyStatus
-_PyPreConfig_InitFromPreConfig(PyPreConfig *config,
- const PyPreConfig *config2)
-{
- PyPreConfig_InitPythonConfig(config);
- preconfig_copy(config, config2);
- return _PyStatus_OK();
-}
-
-
-void
-_PyPreConfig_InitFromConfig(PyPreConfig *preconfig, const PyConfig *config)
-{
- _PyConfigInitEnum config_init = (_PyConfigInitEnum)config->_config_init;
- switch (config_init) {
- case _PyConfig_INIT_PYTHON:
- PyPreConfig_InitPythonConfig(preconfig);
- break;
- case _PyConfig_INIT_ISOLATED:
- PyPreConfig_InitIsolatedConfig(preconfig);
- break;
- case _PyConfig_INIT_COMPAT:
- default:
- _PyPreConfig_InitCompatConfig(preconfig);
- }
-
- _PyPreConfig_GetConfig(preconfig, config);
-}
-
-
-static void
-preconfig_copy(PyPreConfig *config, const PyPreConfig *config2)
-{
-#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
-
- COPY_ATTR(_config_init);
- COPY_ATTR(parse_argv);
- COPY_ATTR(isolated);
- COPY_ATTR(use_environment);
- COPY_ATTR(configure_locale);
- COPY_ATTR(dev_mode);
- COPY_ATTR(coerce_c_locale);
- COPY_ATTR(coerce_c_locale_warn);
- COPY_ATTR(utf8_mode);
- COPY_ATTR(allocator);
-#ifdef MS_WINDOWS
- COPY_ATTR(legacy_windows_fs_encoding);
-#endif
-
-#undef COPY_ATTR
-}
-
-
-PyObject*
-_PyPreConfig_AsDict(const PyPreConfig *config)
-{
- PyObject *dict;
-
- dict = PyDict_New();
- if (dict == NULL) {
- return NULL;
- }
-
-#define SET_ITEM_INT(ATTR) \
- do { \
- PyObject *obj = PyLong_FromLong(config->ATTR); \
- if (obj == NULL) { \
- goto fail; \
- } \
- int res = PyDict_SetItemString(dict, #ATTR, obj); \
- Py_DECREF(obj); \
- if (res < 0) { \
- goto fail; \
- } \
- } while (0)
-
- SET_ITEM_INT(_config_init);
- SET_ITEM_INT(parse_argv);
- SET_ITEM_INT(isolated);
- SET_ITEM_INT(use_environment);
- SET_ITEM_INT(configure_locale);
- SET_ITEM_INT(coerce_c_locale);
- SET_ITEM_INT(coerce_c_locale_warn);
- SET_ITEM_INT(utf8_mode);
-#ifdef MS_WINDOWS
- SET_ITEM_INT(legacy_windows_fs_encoding);
-#endif
- SET_ITEM_INT(dev_mode);
- SET_ITEM_INT(allocator);
- return dict;
-
-fail:
- Py_DECREF(dict);
- return NULL;
-
-#undef SET_ITEM_INT
-}
-
-
-void
-_PyPreConfig_GetConfig(PyPreConfig *preconfig, const PyConfig *config)
-{
-#define COPY_ATTR(ATTR) \
- if (config->ATTR != -1) { \
- preconfig->ATTR = config->ATTR; \
- }
-
- COPY_ATTR(parse_argv);
- COPY_ATTR(isolated);
- COPY_ATTR(use_environment);
- COPY_ATTR(dev_mode);
-
-#undef COPY_ATTR
-}
-
-
-static void
-preconfig_get_global_vars(PyPreConfig *config)
-{
- if (config->_config_init != _PyConfig_INIT_COMPAT) {
- /* Python and Isolated configuration ignore global variables */
- return;
- }
-
-#define COPY_FLAG(ATTR, VALUE) \
- if (config->ATTR < 0) { \
- config->ATTR = VALUE; \
- }
-#define COPY_NOT_FLAG(ATTR, VALUE) \
- if (config->ATTR < 0) { \
- config->ATTR = !(VALUE); \
- }
-
- COPY_FLAG(isolated, Py_IsolatedFlag);
- COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
- if (Py_UTF8Mode > 0) {
- config->utf8_mode = Py_UTF8Mode;
- }
-#ifdef MS_WINDOWS
- COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
-#endif
-
-#undef COPY_FLAG
-#undef COPY_NOT_FLAG
-}
-
-
-static void
-preconfig_set_global_vars(const PyPreConfig *config)
-{
-#define COPY_FLAG(ATTR, VAR) \
- if (config->ATTR >= 0) { \
- VAR = config->ATTR; \
- }
-#define COPY_NOT_FLAG(ATTR, VAR) \
- if (config->ATTR >= 0) { \
- VAR = !config->ATTR; \
- }
-
- COPY_FLAG(isolated, Py_IsolatedFlag);
- COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
-#ifdef MS_WINDOWS
- COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
-#endif
- COPY_FLAG(utf8_mode, Py_UTF8Mode);
-
-#undef COPY_FLAG
-#undef COPY_NOT_FLAG
-}
-
-
-const char*
-_Py_GetEnv(int use_environment, const char *name)
-{
- assert(use_environment >= 0);
-
- if (!use_environment) {
- return NULL;
- }
-
- const char *var = getenv(name);
- if (var && var[0] != '\0') {
- return var;
- }
- else {
- return NULL;
- }
-}
-
-
-int
-_Py_str_to_int(const char *str, int *result)
-{
- const char *endptr = str;
- errno = 0;
- long value = strtol(str, (char **)&endptr, 10);
- if (*endptr != '\0' || errno == ERANGE) {
- return -1;
- }
- if (value < INT_MIN || value > INT_MAX) {
- return -1;
- }
-
- *result = (int)value;
- return 0;
-}
-
-
-void
-_Py_get_env_flag(int use_environment, int *flag, const char *name)
-{
- const char *var = _Py_GetEnv(use_environment, name);
- if (!var) {
- return;
- }
- int value;
- if (_Py_str_to_int(var, &value) < 0 || value < 0) {
- /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
- value = 1;
- }
- if (*flag < value) {
- *flag = value;
- }
-}
-
-
-const wchar_t*
-_Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name)
-{
- for (Py_ssize_t i=0; i < xoptions->length; i++) {
- const wchar_t *option = xoptions->items[i];
- size_t len;
- wchar_t *sep = wcschr(option, L'=');
- if (sep != NULL) {
- len = (sep - option);
- }
- else {
- len = wcslen(option);
- }
- if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
- return option;
- }
- }
- return NULL;
-}
-
-
-static PyStatus
-preconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline)
-{
-#ifdef MS_WINDOWS
- if (config->legacy_windows_fs_encoding) {
- config->utf8_mode = 0;
- }
-#endif
-
- if (config->utf8_mode >= 0) {
- return _PyStatus_OK();
- }
-
- const wchar_t *xopt;
- xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
- if (xopt) {
- wchar_t *sep = wcschr(xopt, L'=');
- if (sep) {
- xopt = sep + 1;
- if (wcscmp(xopt, L"1") == 0) {
- config->utf8_mode = 1;
- }
- else if (wcscmp(xopt, L"0") == 0) {
- config->utf8_mode = 0;
- }
- else {
- return _PyStatus_ERR("invalid -X utf8 option value");
- }
- }
- else {
- config->utf8_mode = 1;
- }
- return _PyStatus_OK();
- }
-
- const char *opt = _Py_GetEnv(config->use_environment, "PYTHONUTF8");
- if (opt) {
- if (strcmp(opt, "1") == 0) {
- config->utf8_mode = 1;
- }
- else if (strcmp(opt, "0") == 0) {
- config->utf8_mode = 0;
- }
- else {
- return _PyStatus_ERR("invalid PYTHONUTF8 environment "
- "variable value");
- }
- return _PyStatus_OK();
- }
-
-
-#ifndef MS_WINDOWS
- if (config->utf8_mode < 0) {
- /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
- const char *ctype_loc = setlocale(LC_CTYPE, NULL);
- if (ctype_loc != NULL
- && (strcmp(ctype_loc, "C") == 0
- || strcmp(ctype_loc, "POSIX") == 0))
- {
- config->utf8_mode = 1;
- }
- }
-#endif
-
- if (config->utf8_mode < 0) {
- config->utf8_mode = 0;
- }
- return _PyStatus_OK();
-}
-
-
-static void
-preconfig_init_coerce_c_locale(PyPreConfig *config)
-{
- if (!config->configure_locale) {
- config->coerce_c_locale = 0;
- config->coerce_c_locale_warn = 0;
- return;
- }
-
- const char *env = _Py_GetEnv(config->use_environment, "PYTHONCOERCECLOCALE");
- if (env) {
- if (strcmp(env, "0") == 0) {
- if (config->coerce_c_locale < 0) {
- config->coerce_c_locale = 0;
- }
- }
- else if (strcmp(env, "warn") == 0) {
- if (config->coerce_c_locale_warn < 0) {
- config->coerce_c_locale_warn = 1;
- }
- }
- else {
- if (config->coerce_c_locale < 0) {
- config->coerce_c_locale = 1;
- }
- }
- }
-
- /* Test if coerce_c_locale equals to -1 or equals to 1:
- PYTHONCOERCECLOCALE=1 doesn't imply that the C locale is always coerced.
- It is only coerced if if the LC_CTYPE locale is "C". */
- if (config->coerce_c_locale < 0 || config->coerce_c_locale == 1) {
- /* The C locale enables the C locale coercion (PEP 538) */
- if (_Py_LegacyLocaleDetected(0)) {
- config->coerce_c_locale = 2;
- }
- else {
- config->coerce_c_locale = 0;
- }
- }
-
- if (config->coerce_c_locale_warn < 0) {
- config->coerce_c_locale_warn = 0;
- }
-}
-
-
-static PyStatus
-preconfig_init_allocator(PyPreConfig *config)
-{
- if (config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
- /* bpo-34247. The PYTHONMALLOC environment variable has the priority
- over PYTHONDEV env var and "-X dev" command line option.
- For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
- allocators to "malloc" (and not to "debug"). */
- const char *envvar = _Py_GetEnv(config->use_environment, "PYTHONMALLOC");
- if (envvar) {
- PyMemAllocatorName name;
- if (_PyMem_GetAllocatorName(envvar, &name) < 0) {
- return _PyStatus_ERR("PYTHONMALLOC: unknown allocator");
- }
- config->allocator = (int)name;
- }
- }
-
- if (config->dev_mode && config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
- config->allocator = PYMEM_ALLOCATOR_DEBUG;
- }
- return _PyStatus_OK();
-}
-
-
-static PyStatus
-preconfig_read(PyPreConfig *config, _PyPreCmdline *cmdline)
-{
- PyStatus status;
-
- status = _PyPreCmdline_Read(cmdline, config);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- precmdline_set_preconfig(cmdline, config);
-
- /* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */
-#ifdef MS_WINDOWS
- _Py_get_env_flag(config->use_environment,
- &config->legacy_windows_fs_encoding,
- "PYTHONLEGACYWINDOWSFSENCODING");
-#endif
-
- preconfig_init_coerce_c_locale(config);
-
- status = preconfig_init_utf8_mode(config, cmdline);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- /* allocator */
- status = preconfig_init_allocator(config);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- assert(config->coerce_c_locale >= 0);
- assert(config->coerce_c_locale_warn >= 0);
-#ifdef MS_WINDOWS
- assert(config->legacy_windows_fs_encoding >= 0);
-#endif
- assert(config->utf8_mode >= 0);
- assert(config->isolated >= 0);
- assert(config->use_environment >= 0);
- assert(config->dev_mode >= 0);
-
- return _PyStatus_OK();
-}
-
-
-/* Read the configuration from:
-
- - command line arguments
- - environment variables
- - Py_xxx global configuration variables
- - the LC_CTYPE locale */
-PyStatus
-_PyPreConfig_Read(PyPreConfig *config, const _PyArgv *args)
-{
- PyStatus status;
-
- status = _PyRuntime_Initialize();
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- preconfig_get_global_vars(config);
-
- /* Copy LC_CTYPE locale, since it's modified later */
- const char *loc = setlocale(LC_CTYPE, NULL);
- if (loc == NULL) {
- return _PyStatus_ERR("failed to LC_CTYPE locale");
- }
- char *init_ctype_locale = _PyMem_RawStrdup(loc);
- if (init_ctype_locale == NULL) {
- return _PyStatus_NO_MEMORY();
- }
-
- /* Save the config to be able to restore it if encodings change */
- PyPreConfig save_config;
-
- status = _PyPreConfig_InitFromPreConfig(&save_config, config);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- /* Set LC_CTYPE to the user preferred locale */
- if (config->configure_locale) {
- _Py_SetLocaleFromEnv(LC_CTYPE);
- }
-
- _PyPreCmdline cmdline = _PyPreCmdline_INIT;
- int init_utf8_mode = Py_UTF8Mode;
-#ifdef MS_WINDOWS
- int init_legacy_encoding = Py_LegacyWindowsFSEncodingFlag;
-#endif
-
- if (args) {
- status = _PyPreCmdline_SetArgv(&cmdline, args);
- if (_PyStatus_EXCEPTION(status)) {
- goto done;
- }
- }
-
- int locale_coerced = 0;
- int loops = 0;
-
- while (1) {
- int utf8_mode = config->utf8_mode;
-
- /* Watchdog to prevent an infinite loop */
- loops++;
- if (loops == 3) {
- status = _PyStatus_ERR("Encoding changed twice while "
- "reading the configuration");
- goto done;
- }
-
- /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
- on Py_UTF8Mode and Py_LegacyWindowsFSEncodingFlag. */
- Py_UTF8Mode = config->utf8_mode;
-#ifdef MS_WINDOWS
- Py_LegacyWindowsFSEncodingFlag = config->legacy_windows_fs_encoding;
-#endif
-
- status = preconfig_read(config, &cmdline);
- if (_PyStatus_EXCEPTION(status)) {
- goto done;
- }
-
- /* The legacy C locale assumes ASCII as the default text encoding, which
- * causes problems not only for the CPython runtime, but also other
- * components like GNU readline.
- *
- * Accordingly, when the CLI detects it, it attempts to coerce it to a
- * more capable UTF-8 based alternative.
- *
- * See the documentation of the PYTHONCOERCECLOCALE setting for more
- * details.
- */
- int encoding_changed = 0;
- if (config->coerce_c_locale && !locale_coerced) {
- locale_coerced = 1;
- _Py_CoerceLegacyLocale(0);
- encoding_changed = 1;
- }
-
- if (utf8_mode == -1) {
- if (config->utf8_mode == 1) {
- /* UTF-8 Mode enabled */
- encoding_changed = 1;
- }
- }
- else {
- if (config->utf8_mode != utf8_mode) {
- encoding_changed = 1;
- }
- }
-
- if (!encoding_changed) {
- break;
- }
-
- /* Reset the configuration before reading again the configuration,
- just keep UTF-8 Mode value. */
- int new_utf8_mode = config->utf8_mode;
- int new_coerce_c_locale = config->coerce_c_locale;
- preconfig_copy(config, &save_config);
- config->utf8_mode = new_utf8_mode;
- config->coerce_c_locale = new_coerce_c_locale;
-
- /* The encoding changed: read again the configuration
- with the new encoding */
- }
- status = _PyStatus_OK();
-
-done:
- if (init_ctype_locale != NULL) {
- setlocale(LC_CTYPE, init_ctype_locale);
- PyMem_RawFree(init_ctype_locale);
- }
- Py_UTF8Mode = init_utf8_mode ;
-#ifdef MS_WINDOWS
- Py_LegacyWindowsFSEncodingFlag = init_legacy_encoding;
-#endif
- _PyPreCmdline_Clear(&cmdline);
- return status;
-}
-
-
-/* Write the pre-configuration:
-
- - set the memory allocators
- - set Py_xxx global configuration variables
- - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
- (PEP 540)
-
- The applied configuration is written into _PyRuntime.preconfig.
- If the C locale cannot be coerced, set coerce_c_locale to 0.
-
- Do nothing if called after Py_Initialize(): ignore the new
- pre-configuration. */
-PyStatus
-_PyPreConfig_Write(const PyPreConfig *src_config)
-{
- PyPreConfig config;
-
- PyStatus status = _PyPreConfig_InitFromPreConfig(&config, src_config);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
- if (_PyRuntime.core_initialized) {
- /* bpo-34008: Calling this functions after Py_Initialize() ignores
- the new configuration. */
- return _PyStatus_OK();
- }
-
- PyMemAllocatorName name = (PyMemAllocatorName)config.allocator;
- if (name != PYMEM_ALLOCATOR_NOT_SET) {
- if (_PyMem_SetupAllocators(name) < 0) {
- return _PyStatus_ERR("Unknown PYTHONMALLOC allocator");
- }
- }
-
- preconfig_set_global_vars(&config);
-
- if (config.configure_locale) {
- if (config.coerce_c_locale) {
- if (!_Py_CoerceLegacyLocale(config.coerce_c_locale_warn)) {
- /* C locale not coerced */
- config.coerce_c_locale = 0;
- }
- }
-
- /* Set LC_CTYPE to the user preferred locale */
- _Py_SetLocaleFromEnv(LC_CTYPE);
- }
-
- /* Write the new pre-configuration into _PyRuntime */
- preconfig_copy(&_PyRuntime.preconfig, &config);
-
- return _PyStatus_OK();
-}