LCOV - code coverage report
Current view: | top level - Python - preconfig.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 266 | 397 | 67.0 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 28 | 30 | 93.3 %
|  |  | Branches: | 100 | 271 | 36.9 %

               Branch data     Line data    Source code
           1                 :            : #include "Python.h"
           2                 :            : #include "pycore_fileutils.h"     // DECODE_LOCALE_ERR
           3                 :            : #include "pycore_getopt.h"        // _PyOS_GetOpt()
           4                 :            : #include "pycore_initconfig.h"    // _PyArgv
           5                 :            : #include "pycore_pymem.h"         // _PyMem_GetAllocatorName()
           6                 :            : #include "pycore_runtime.h"       // _PyRuntime_Initialize()
           7                 :            :
           8                 :            : #include <locale.h>               // setlocale()
           9                 :            : #include <stdlib.h>               // getenv()
          10                 :            :
          11                 :            :
          12                 :            : /* Forward declarations */
          13                 :            : static void
          14                 :            : preconfig_copy(PyPreConfig *config, const PyPreConfig *config2);
          15                 :            :
          16                 :            :
          17                 :            : /* --- File system encoding/errors -------------------------------- */
          18                 :            :
          19                 :            : const char *Py_FileSystemDefaultEncoding = NULL;
          20                 :            : int Py_HasFileSystemDefaultEncoding = 0;
          21                 :            : const char *Py_FileSystemDefaultEncodeErrors = NULL;
          22                 :            : int _Py_HasFileSystemDefaultEncodeErrors = 0;
          23                 :            :
          24                 :            : void
          25                 :         50 : _Py_ClearFileSystemEncoding(void)
          26                 :            : {
          27                 :            : _Py_COMP_DIAG_PUSH
          28                 :            : _Py_COMP_DIAG_IGNORE_DEPR_DECLS
          29   [ +  -  +  + ]:         50 :     if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
          30                 :         25 :         PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
          31                 :         25 :         Py_FileSystemDefaultEncoding = NULL;
          32                 :            :     }
          33   [ +  -  +  + ]:         50 :     if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) {
          34                 :         25 :         PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors);
          35                 :         25 :         Py_FileSystemDefaultEncodeErrors = NULL;
          36                 :            :     }
          37                 :            : _Py_COMP_DIAG_POP
          38                 :         50 : }
          39                 :            :
          40                 :            :
          41                 :            : /* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
          42                 :            :    global configuration variables to PyConfig.filesystem_encoding and
          43                 :            :    PyConfig.filesystem_errors (encoded to UTF-8).
          44                 :            :
          45                 :            :    Function called by _PyUnicode_InitEncodings(). */
          46                 :            : int
          47                 :         25 : _Py_SetFileSystemEncoding(const char *encoding, const char *errors)
          48                 :            : {
          49                 :         25 :     char *encoding2 = _PyMem_RawStrdup(encoding);
          50         [ -  + ]:         25 :     if (encoding2 == NULL) {
          51                 :          0 :         return -1;
          52                 :            :     }
          53                 :            :
          54                 :         25 :     char *errors2 = _PyMem_RawStrdup(errors);
          55         [ -  + ]:         25 :     if (errors2 == NULL) {
          56                 :          0 :         PyMem_RawFree(encoding2);
          57                 :          0 :         return -1;
          58                 :            :     }
          59                 :            :
          60                 :         25 :     _Py_ClearFileSystemEncoding();
          61                 :            :
          62                 :            : _Py_COMP_DIAG_PUSH
          63                 :            : _Py_COMP_DIAG_IGNORE_DEPR_DECLS
          64                 :         25 :     Py_FileSystemDefaultEncoding = encoding2;
          65                 :         25 :     Py_HasFileSystemDefaultEncoding = 0;
          66                 :            :
          67                 :         25 :     Py_FileSystemDefaultEncodeErrors = errors2;
          68                 :         25 :     _Py_HasFileSystemDefaultEncodeErrors = 0;
          69                 :            : _Py_COMP_DIAG_POP
          70                 :         25 :     return 0;
          71                 :            : }
          72                 :            :
          73                 :            :
          74                 :            : /* --- _PyArgv ---------------------------------------------------- */
          75                 :            :
          76                 :            : /* Decode bytes_argv using Py_DecodeLocale() */
          77                 :            : PyStatus
          78                 :         50 : _PyArgv_AsWstrList(const _PyArgv *args, PyWideStringList *list)
          79                 :            : {
          80                 :         50 :     PyWideStringList wargv = _PyWideStringList_INIT;
          81         [ +  - ]:         50 :     if (args->use_bytes_argv) {
          82                 :         50 :         size_t size = sizeof(wchar_t*) * args->argc;
          83                 :         50 :         wargv.items = (wchar_t **)PyMem_RawMalloc(size);
          84         [ -  + ]:         50 :         if (wargv.items == NULL) {
          85                 :          0 :             return _PyStatus_NO_MEMORY();
          86                 :            :         }
          87                 :            :
          88         [ +  + ]:        338 :         for (Py_ssize_t i = 0; i < args->argc; i++) {
          89                 :            :             size_t len;
          90                 :        288 :             wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
          91         [ -  + ]:        288 :             if (arg == NULL) {
          92                 :          0 :                 _PyWideStringList_Clear(&wargv);
          93         [ #  # ]:          0 :                 return DECODE_LOCALE_ERR("command line arguments", len);
          94                 :            :             }
          95                 :        288 :             wargv.items[i] = arg;
          96                 :        288 :             wargv.length++;
          97                 :            :         }
          98                 :            :
          99                 :         50 :         _PyWideStringList_Clear(list);
         100                 :         50 :         *list = wargv;
         101                 :            :     }
         102                 :            :     else {
         103                 :          0 :         wargv.length = args->argc;
         104                 :          0 :         wargv.items = (wchar_t **)args->wchar_argv;
         105         [ #  # ]:          0 :         if (_PyWideStringList_Copy(list, &wargv) < 0) {
         106                 :          0 :             return _PyStatus_NO_MEMORY();
         107                 :            :         }
         108                 :            :     }
         109                 :         50 :     return _PyStatus_OK();
         110                 :            : }
         111                 :            :
         112                 :            :
         113                 :            : /* --- _PyPreCmdline ------------------------------------------------- */
         114                 :            :
         115                 :            : void
         116                 :         79 : _PyPreCmdline_Clear(_PyPreCmdline *cmdline)
         117                 :            : {
         118                 :         79 :     _PyWideStringList_Clear(&cmdline->argv);
         119                 :         79 :     _PyWideStringList_Clear(&cmdline->xoptions);
         120                 :         79 : }
         121                 :            :
         122                 :            :
         123                 :            : PyStatus
         124                 :         25 : _PyPreCmdline_SetArgv(_PyPreCmdline *cmdline, const _PyArgv *args)
         125                 :            : {
         126                 :         25 :     return _PyArgv_AsWstrList(args, &cmdline->argv);
         127                 :            : }
         128                 :            :
         129                 :            :
         130                 :            : static void
         131                 :         79 : precmdline_get_preconfig(_PyPreCmdline *cmdline, const PyPreConfig *config)
         132                 :            : {
         133                 :            : #define COPY_ATTR(ATTR) \
         134                 :            :     if (config->ATTR != -1) { \
         135                 :            :         cmdline->ATTR = config->ATTR; \
         136                 :            :     }
         137                 :            :
         138         [ +  - ]:         79 :     COPY_ATTR(isolated);
         139         [ +  - ]:         79 :     COPY_ATTR(use_environment);
         140         [ +  + ]:         79 :     COPY_ATTR(dev_mode);
         141                 :            :
         142                 :            : #undef COPY_ATTR
         143                 :         79 : }
         144                 :            :
         145                 :            :
         146                 :            : static void
         147                 :         29 : precmdline_set_preconfig(const _PyPreCmdline *cmdline, PyPreConfig *config)
         148                 :            : {
         149                 :            : #define COPY_ATTR(ATTR) \
         150                 :            :     config->ATTR = cmdline->ATTR
         151                 :            :
         152                 :         29 :     COPY_ATTR(isolated);
         153                 :         29 :     COPY_ATTR(use_environment);
         154                 :         29 :     COPY_ATTR(dev_mode);
         155                 :            :
         156                 :            : #undef COPY_ATTR
         157                 :         29 : }
         158                 :            :
         159                 :            :
         160                 :            : PyStatus
         161                 :         50 : _PyPreCmdline_SetConfig(const _PyPreCmdline *cmdline, PyConfig *config)
         162                 :            : {
         163                 :            : #define COPY_ATTR(ATTR) \
         164                 :            :     config->ATTR = cmdline->ATTR
         165                 :            :
         166                 :         50 :     PyStatus status = _PyWideStringList_Extend(&config->xoptions, &cmdline->xoptions);
         167         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
         168                 :          0 :         return status;
         169                 :            :     }
         170                 :            :
         171                 :         50 :     COPY_ATTR(isolated);
         172                 :         50 :     COPY_ATTR(use_environment);
         173                 :         50 :     COPY_ATTR(dev_mode);
         174                 :         50 :     COPY_ATTR(warn_default_encoding);
         175                 :         50 :     return _PyStatus_OK();
         176                 :            :
         177                 :            : #undef COPY_ATTR
         178                 :            : }
         179                 :            :
         180                 :            :
         181                 :            : /* Parse the command line arguments */
         182                 :            : static PyStatus
         183                 :         71 : precmdline_parse_cmdline(_PyPreCmdline *cmdline)
         184                 :            : {
         185                 :         71 :     const PyWideStringList *argv = &cmdline->argv;
         186                 :            :
         187                 :         71 :     _PyOS_ResetGetOpt();
         188                 :            :     /* Don't log parsing errors into stderr here: PyConfig_Read()
         189                 :            :        is responsible for that */
         190                 :         71 :     _PyOS_opterr = 0;
         191                 :          8 :     do {
         192                 :         79 :         int longindex = -1;
         193                 :         79 :         int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
         194                 :            :
         195   [ +  +  +  +  :         79 :         if (c == EOF || c == 'c' || c == 'm') {
                       +  + ]
         196                 :            :             break;
         197                 :            :         }
         198                 :            :
         199   [ +  -  -  + ]:          8 :         switch (c) {
         200                 :          6 :         case 'E':
         201                 :          6 :             cmdline->use_environment = 0;
         202                 :          6 :             break;
         203                 :            :
         204                 :          0 :         case 'I':
         205                 :          0 :             cmdline->isolated = 1;
         206                 :          0 :             break;
         207                 :            :
         208                 :          0 :         case 'X':
         209                 :            :         {
         210                 :          0 :             PyStatus status = PyWideStringList_Append(&cmdline->xoptions,
         211                 :            :                                                       _PyOS_optarg);
         212         [ #  # ]:          0 :             if (_PyStatus_EXCEPTION(status)) {
         213                 :          0 :                 return status;
         214                 :            :             }
         215                 :          0 :             break;
         216                 :            :         }
         217                 :            :
         218                 :          2 :         default:
         219                 :            :             /* ignore other argument:
         220                 :            :                handled by PyConfig_Read() */
         221                 :          2 :             break;
         222                 :            :         }
         223                 :            :     } while (1);
         224                 :            :
         225                 :         71 :     return _PyStatus_OK();
         226                 :            : }
         227                 :            :
         228                 :            :
         229                 :            : PyStatus
         230                 :         79 : _PyPreCmdline_Read(_PyPreCmdline *cmdline, const PyPreConfig *preconfig)
         231                 :            : {
         232                 :         79 :     precmdline_get_preconfig(cmdline, preconfig);
         233                 :            :
         234         [ +  + ]:         79 :     if (preconfig->parse_argv) {
         235                 :         71 :         PyStatus status = precmdline_parse_cmdline(cmdline);
         236         [ -  + ]:         71 :         if (_PyStatus_EXCEPTION(status)) {
         237                 :          0 :             return status;
         238                 :            :         }
         239                 :            :     }
         240                 :            :
         241                 :            :     /* isolated, use_environment */
         242         [ -  + ]:         79 :     if (cmdline->isolated < 0) {
         243                 :          0 :         cmdline->isolated = 0;
         244                 :            :     }
         245         [ +  + ]:         79 :     if (cmdline->isolated > 0) {
         246                 :          8 :         cmdline->use_environment = 0;
         247                 :            :     }
         248         [ -  + ]:         79 :     if (cmdline->use_environment < 0) {
         249                 :          0 :         cmdline->use_environment = 0;
         250                 :            :     }
         251                 :            :
         252                 :            :     /* dev_mode */
         253         [ +  + ]:         79 :     if ((cmdline->dev_mode < 0)
         254         [ +  - ]:          4 :         && (_Py_get_xoption(&cmdline->xoptions, L"dev")
         255         [ -  + ]:          4 :             || _Py_GetEnv(cmdline->use_environment, "PYTHONDEVMODE")))
         256                 :            :     {
         257                 :          0 :         cmdline->dev_mode = 1;
         258                 :            :     }
         259         [ +  + ]:         79 :     if (cmdline->dev_mode < 0) {
         260                 :          4 :         cmdline->dev_mode = 0;
         261                 :            :     }
         262                 :            :
         263                 :            :     // warn_default_encoding
         264         [ +  - ]:         79 :     if (_Py_get_xoption(&cmdline->xoptions, L"warn_default_encoding")
         265         [ -  + ]:         79 :             || _Py_GetEnv(cmdline->use_environment, "PYTHONWARNDEFAULTENCODING"))
         266                 :            :     {
         267                 :          0 :         cmdline->warn_default_encoding = 1;
         268                 :            :     }
         269                 :            :
         270                 :            :     assert(cmdline->use_environment >= 0);
         271                 :            :     assert(cmdline->isolated >= 0);
         272                 :            :     assert(cmdline->dev_mode >= 0);
         273                 :            :     assert(cmdline->warn_default_encoding >= 0);
         274                 :            :
         275                 :         79 :     return _PyStatus_OK();
         276                 :            : }
         277                 :            :
         278                 :            :
         279                 :            : /* --- PyPreConfig ----------------------------------------------- */
         280                 :            :
         281                 :            :
         282                 :            : void
         283                 :        195 : _PyPreConfig_InitCompatConfig(PyPreConfig *config)
         284                 :            : {
         285                 :        195 :     memset(config, 0, sizeof(*config));
         286                 :            :
         287                 :        195 :     config->_config_init = (int)_PyConfig_INIT_COMPAT;
         288                 :        195 :     config->parse_argv = 0;
         289                 :        195 :     config->isolated = -1;
         290                 :        195 :     config->use_environment = -1;
         291                 :        195 :     config->configure_locale = 1;
         292                 :            :
         293                 :            :     /* bpo-36443: C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
         294                 :            :        are disabled by default using the Compat configuration.
         295                 :            :
         296                 :            :        Py_UTF8Mode=1 enables the UTF-8 mode. PYTHONUTF8 environment variable
         297                 :            :        is ignored (even if use_environment=1). */
         298                 :        195 :     config->utf8_mode = 0;
         299                 :        195 :     config->coerce_c_locale = 0;
         300                 :        195 :     config->coerce_c_locale_warn = 0;
         301                 :            :
         302                 :        195 :     config->dev_mode = -1;
         303                 :        195 :     config->allocator = PYMEM_ALLOCATOR_NOT_SET;
         304                 :            : #ifdef MS_WINDOWS
         305                 :            :     config->legacy_windows_fs_encoding = -1;
         306                 :            : #endif
         307                 :        195 : }
         308                 :            :
         309                 :            :
         310                 :            : void
         311                 :        170 : PyPreConfig_InitPythonConfig(PyPreConfig *config)
         312                 :            : {
         313                 :        170 :     _PyPreConfig_InitCompatConfig(config);
         314                 :            :
         315                 :        170 :     config->_config_init = (int)_PyConfig_INIT_PYTHON;
         316                 :        170 :     config->isolated = 0;
         317                 :        170 :     config->parse_argv = 1;
         318                 :        170 :     config->use_environment = 1;
         319                 :            :     /* Set to -1 to enable C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
         320                 :            :        depending on the LC_CTYPE locale, PYTHONUTF8 and PYTHONCOERCECLOCALE
         321                 :            :        environment variables. */
         322                 :        170 :     config->coerce_c_locale = -1;
         323                 :        170 :     config->coerce_c_locale_warn = -1;
         324                 :        170 :     config->utf8_mode = -1;
         325                 :            : #ifdef MS_WINDOWS
         326                 :            :     config->legacy_windows_fs_encoding = 0;
         327                 :            : #endif
         328                 :        170 : }
         329                 :            :
         330                 :            :
         331                 :            : void
         332                 :         25 : PyPreConfig_InitIsolatedConfig(PyPreConfig *config)
         333                 :            : {
         334                 :         25 :     _PyPreConfig_InitCompatConfig(config);
         335                 :            :
         336                 :         25 :     config->_config_init = (int)_PyConfig_INIT_ISOLATED;
         337                 :         25 :     config->configure_locale = 0;
         338                 :         25 :     config->isolated = 1;
         339                 :         25 :     config->use_environment = 0;
         340                 :         25 :     config->utf8_mode = 0;
         341                 :         25 :     config->dev_mode = 0;
         342                 :            : #ifdef MS_WINDOWS
         343                 :            :     config->legacy_windows_fs_encoding = 0;
         344                 :            : #endif
         345                 :         25 : }
         346                 :            :
         347                 :            :
         348                 :            : PyStatus
         349                 :        137 : _PyPreConfig_InitFromPreConfig(PyPreConfig *config,
         350                 :            :                                const PyPreConfig *config2)
         351                 :            : {
         352                 :        137 :     PyPreConfig_InitPythonConfig(config);
         353                 :        137 :     preconfig_copy(config, config2);
         354                 :        137 :     return _PyStatus_OK();
         355                 :            : }
         356                 :            :
         357                 :            :
         358                 :            : void
         359                 :         25 : _PyPreConfig_InitFromConfig(PyPreConfig *preconfig, const PyConfig *config)
         360                 :            : {
         361                 :         25 :     _PyConfigInitEnum config_init = (_PyConfigInitEnum)config->_config_init;
         362      [ -  +  - ]:         25 :     switch (config_init) {
         363                 :          0 :     case _PyConfig_INIT_PYTHON:
         364                 :          0 :         PyPreConfig_InitPythonConfig(preconfig);
         365                 :          0 :         break;
         366                 :         25 :     case _PyConfig_INIT_ISOLATED:
         367                 :         25 :         PyPreConfig_InitIsolatedConfig(preconfig);
         368                 :         25 :         break;
         369                 :          0 :     case _PyConfig_INIT_COMPAT:
         370                 :            :     default:
         371                 :          0 :         _PyPreConfig_InitCompatConfig(preconfig);
         372                 :            :     }
         373                 :            :
         374                 :         25 :     _PyPreConfig_GetConfig(preconfig, config);
         375                 :         25 : }
         376                 :            :
         377                 :            :
         378                 :            : static void
         379                 :        253 : preconfig_copy(PyPreConfig *config, const PyPreConfig *config2)
         380                 :            : {
         381                 :            : #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
         382                 :            :
         383                 :        253 :     COPY_ATTR(_config_init);
         384                 :        253 :     COPY_ATTR(parse_argv);
         385                 :        253 :     COPY_ATTR(isolated);
         386                 :        253 :     COPY_ATTR(use_environment);
         387                 :        253 :     COPY_ATTR(configure_locale);
         388                 :        253 :     COPY_ATTR(dev_mode);
         389                 :        253 :     COPY_ATTR(coerce_c_locale);
         390                 :        253 :     COPY_ATTR(coerce_c_locale_warn);
         391                 :        253 :     COPY_ATTR(utf8_mode);
         392                 :        253 :     COPY_ATTR(allocator);
         393                 :            : #ifdef MS_WINDOWS
         394                 :            :     COPY_ATTR(legacy_windows_fs_encoding);
         395                 :            : #endif
         396                 :            :
         397                 :            : #undef COPY_ATTR
         398                 :        253 : }
         399                 :            :
         400                 :            :
         401                 :            : PyObject*
         402                 :          0 : _PyPreConfig_AsDict(const PyPreConfig *config)
         403                 :            : {
         404                 :            :     PyObject *dict;
         405                 :            :
         406                 :          0 :     dict = PyDict_New();
         407         [ #  # ]:          0 :     if (dict == NULL) {
         408                 :          0 :         return NULL;
         409                 :            :     }
         410                 :            :
         411                 :            : #define SET_ITEM_INT(ATTR) \
         412                 :            :         do { \
         413                 :            :             PyObject *obj = PyLong_FromLong(config->ATTR); \
         414                 :            :             if (obj == NULL) { \
         415                 :            :                 goto fail; \
         416                 :            :             } \
         417                 :            :             int res = PyDict_SetItemString(dict, #ATTR, obj); \
         418                 :            :             Py_DECREF(obj); \
         419                 :            :             if (res < 0) { \
         420                 :            :                 goto fail; \
         421                 :            :             } \
         422                 :            :         } while (0)
         423                 :            :
         424   [ #  #  #  # ]:          0 :     SET_ITEM_INT(_config_init);
         425   [ #  #  #  # ]:          0 :     SET_ITEM_INT(parse_argv);
         426   [ #  #  #  # ]:          0 :     SET_ITEM_INT(isolated);
         427   [ #  #  #  # ]:          0 :     SET_ITEM_INT(use_environment);
         428   [ #  #  #  # ]:          0 :     SET_ITEM_INT(configure_locale);
         429   [ #  #  #  # ]:          0 :     SET_ITEM_INT(coerce_c_locale);
         430   [ #  #  #  # ]:          0 :     SET_ITEM_INT(coerce_c_locale_warn);
         431   [ #  #  #  # ]:          0 :     SET_ITEM_INT(utf8_mode);
         432                 :            : #ifdef MS_WINDOWS
         433                 :            :     SET_ITEM_INT(legacy_windows_fs_encoding);
         434                 :            : #endif
         435   [ #  #  #  # ]:          0 :     SET_ITEM_INT(dev_mode);
         436   [ #  #  #  # ]:          0 :     SET_ITEM_INT(allocator);
         437                 :          0 :     return dict;
         438                 :            :
         439                 :          0 : fail:
         440                 :          0 :     Py_DECREF(dict);
         441                 :          0 :     return NULL;
         442                 :            :
         443                 :            : #undef SET_ITEM_INT
         444                 :            : }
         445                 :            :
         446                 :            :
         447                 :            : void
         448                 :         75 : _PyPreConfig_GetConfig(PyPreConfig *preconfig, const PyConfig *config)
         449                 :            : {
         450                 :            : #define COPY_ATTR(ATTR) \
         451                 :            :     if (config->ATTR != -1) { \
         452                 :            :         preconfig->ATTR = config->ATTR; \
         453                 :            :     }
         454                 :            :
         455         [ +  - ]:         75 :     COPY_ATTR(parse_argv);
         456         [ +  - ]:         75 :     COPY_ATTR(isolated);
         457         [ +  - ]:         75 :     COPY_ATTR(use_environment);
         458         [ +  + ]:         75 :     COPY_ATTR(dev_mode);
         459                 :            :
         460                 :            : #undef COPY_ATTR
         461                 :         75 : }
         462                 :            :
         463                 :            :
         464                 :            : static void
         465                 :         29 : preconfig_get_global_vars(PyPreConfig *config)
         466                 :            : {
         467         [ +  - ]:         29 :     if (config->_config_init != _PyConfig_INIT_COMPAT) {
         468                 :            :         /* Python and Isolated configuration ignore global variables */
         469                 :         29 :         return;
         470                 :            :     }
         471                 :            :
         472                 :            : #define COPY_FLAG(ATTR, VALUE) \
         473                 :            :     if (config->ATTR < 0) { \
         474                 :            :         config->ATTR = VALUE; \
         475                 :            :     }
         476                 :            : #define COPY_NOT_FLAG(ATTR, VALUE) \
         477                 :            :     if (config->ATTR < 0) { \
         478                 :            :         config->ATTR = !(VALUE); \
         479                 :            :     }
         480                 :            :
         481                 :            : _Py_COMP_DIAG_PUSH
         482                 :            : _Py_COMP_DIAG_IGNORE_DEPR_DECLS
         483         [ #  # ]:          0 :     COPY_FLAG(isolated, Py_IsolatedFlag);
         484         [ #  # ]:          0 :     COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
         485         [ #  # ]:          0 :     if (Py_UTF8Mode > 0) {
         486                 :          0 :         config->utf8_mode = Py_UTF8Mode;
         487                 :            :     }
         488                 :            : #ifdef MS_WINDOWS
         489                 :            :     COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
         490                 :            : #endif
         491                 :            : _Py_COMP_DIAG_POP
         492                 :            :
         493                 :            : #undef COPY_FLAG
         494                 :            : #undef COPY_NOT_FLAG
         495                 :            : }
         496                 :            :
         497                 :            :
         498                 :            : static void
         499                 :         29 : preconfig_set_global_vars(const PyPreConfig *config)
         500                 :            : {
         501                 :            : #define COPY_FLAG(ATTR, VAR) \
         502                 :            :     if (config->ATTR >= 0) { \
         503                 :            :         VAR = config->ATTR; \
         504                 :            :     }
         505                 :            : #define COPY_NOT_FLAG(ATTR, VAR) \
         506                 :            :     if (config->ATTR >= 0) { \
         507                 :            :         VAR = !config->ATTR; \
         508                 :            :     }
         509                 :            :
         510                 :            : _Py_COMP_DIAG_PUSH
         511                 :            : _Py_COMP_DIAG_IGNORE_DEPR_DECLS
         512         [ +  - ]:         29 :     COPY_FLAG(isolated, Py_IsolatedFlag);
         513         [ +  - ]:         29 :     COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
         514                 :            : #ifdef MS_WINDOWS
         515                 :            :     COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
         516                 :            : #endif
         517         [ +  - ]:         29 :     COPY_FLAG(utf8_mode, Py_UTF8Mode);
         518                 :            : _Py_COMP_DIAG_POP
         519                 :            :
         520                 :            : #undef COPY_FLAG
         521                 :            : #undef COPY_NOT_FLAG
         522                 :         29 : }
         523                 :            :
         524                 :            :
         525                 :            : const char*
         526                 :        301 : _Py_GetEnv(int use_environment, const char *name)
         527                 :            : {
         528                 :            :     assert(use_environment >= 0);
         529                 :            :
         530         [ +  + ]:        301 :     if (!use_environment) {
         531                 :        276 :         return NULL;
         532                 :            :     }
         533                 :            :
         534                 :         25 :     const char *var = getenv(name);
         535   [ -  +  -  - ]:         25 :     if (var && var[0] != '\0') {
         536                 :          0 :         return var;
         537                 :            :     }
         538                 :            :     else {
         539                 :         25 :         return NULL;
         540                 :            :     }
         541                 :            : }
         542                 :            :
         543                 :            :
         544                 :            : int
         545                 :          0 : _Py_str_to_int(const char *str, int *result)
         546                 :            : {
         547                 :          0 :     const char *endptr = str;
         548                 :          0 :     errno = 0;
         549                 :          0 :     long value = strtol(str, (char **)&endptr, 10);
         550   [ #  #  #  # ]:          0 :     if (*endptr != '\0' || errno == ERANGE) {
         551                 :          0 :         return -1;
         552                 :            :     }
         553   [ #  #  #  # ]:          0 :     if (value < INT_MIN || value > INT_MAX) {
         554                 :          0 :         return -1;
         555                 :            :     }
         556                 :            :
         557                 :          0 :     *result = (int)value;
         558                 :          0 :     return 0;
         559                 :            : }
         560                 :            :
         561                 :            :
         562                 :            : void
         563                 :          7 : _Py_get_env_flag(int use_environment, int *flag, const char *name)
         564                 :            : {
         565                 :          7 :     const char *var = _Py_GetEnv(use_environment, name);
         566         [ +  - ]:          7 :     if (!var) {
         567                 :          7 :         return;
         568                 :            :     }
         569                 :            :     int value;
         570   [ #  #  #  # ]:          0 :     if (_Py_str_to_int(var, &value) < 0 || value < 0) {
         571                 :            :         /* PYTHONDEBUG=text and PYTHONDEBUG=-2 behave as PYTHONDEBUG=1 */
         572                 :          0 :         value = 1;
         573                 :            :     }
         574         [ #  # ]:          0 :     if (*flag < value) {
         575                 :          0 :         *flag = value;
         576                 :            :     }
         577                 :            : }
         578                 :            :
         579                 :            :
         580                 :            : const wchar_t*
         581                 :        374 : _Py_get_xoption(const PyWideStringList *xoptions, const wchar_t *name)
         582                 :            : {
         583         [ -  + ]:        374 :     for (Py_ssize_t i=0; i < xoptions->length; i++) {
         584                 :          0 :         const wchar_t *option = xoptions->items[i];
         585                 :            :         size_t len;
         586                 :          0 :         wchar_t *sep = wcschr(option, L'=');
         587         [ #  # ]:          0 :         if (sep != NULL) {
         588                 :          0 :             len = (sep - option);
         589                 :            :         }
         590                 :            :         else {
         591                 :          0 :             len = wcslen(option);
         592                 :            :         }
         593   [ #  #  #  # ]:          0 :         if (wcsncmp(option, name, len) == 0 && name[len] == L'\0') {
         594                 :          0 :             return option;
         595                 :            :         }
         596                 :            :     }
         597                 :        374 :     return NULL;
         598                 :            : }
         599                 :            :
         600                 :            :
         601                 :            : static PyStatus
         602                 :         29 : preconfig_init_utf8_mode(PyPreConfig *config, const _PyPreCmdline *cmdline)
         603                 :            : {
         604                 :            : #ifdef MS_WINDOWS
         605                 :            :     if (config->legacy_windows_fs_encoding) {
         606                 :            :         config->utf8_mode = 0;
         607                 :            :     }
         608                 :            : #endif
         609                 :            :
         610         [ +  + ]:         29 :     if (config->utf8_mode >= 0) {
         611                 :         25 :         return _PyStatus_OK();
         612                 :            :     }
         613                 :            :
         614                 :            :     const wchar_t *xopt;
         615                 :          4 :     xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
         616         [ -  + ]:          4 :     if (xopt) {
         617                 :          0 :         wchar_t *sep = wcschr(xopt, L'=');
         618         [ #  # ]:          0 :         if (sep) {
         619                 :          0 :             xopt = sep + 1;
         620         [ #  # ]:          0 :             if (wcscmp(xopt, L"1") == 0) {
         621                 :          0 :                 config->utf8_mode = 1;
         622                 :            :             }
         623         [ #  # ]:          0 :             else if (wcscmp(xopt, L"0") == 0) {
         624                 :          0 :                 config->utf8_mode = 0;
         625                 :            :             }
         626                 :            :             else {
         627                 :          0 :                 return _PyStatus_ERR("invalid -X utf8 option value");
         628                 :            :             }
         629                 :            :         }
         630                 :            :         else {
         631                 :          0 :             config->utf8_mode = 1;
         632                 :            :         }
         633                 :          0 :         return _PyStatus_OK();
         634                 :            :     }
         635                 :            :
         636                 :          4 :     const char *opt = _Py_GetEnv(config->use_environment, "PYTHONUTF8");
         637         [ -  + ]:          4 :     if (opt) {
         638         [ #  # ]:          0 :         if (strcmp(opt, "1") == 0) {
         639                 :          0 :             config->utf8_mode = 1;
         640                 :            :         }
         641         [ #  # ]:          0 :         else if (strcmp(opt, "0") == 0) {
         642                 :          0 :             config->utf8_mode = 0;
         643                 :            :         }
         644                 :            :         else {
         645                 :          0 :             return _PyStatus_ERR("invalid PYTHONUTF8 environment "
         646                 :            :                                 "variable value");
         647                 :            :         }
         648                 :          0 :         return _PyStatus_OK();
         649                 :            :     }
         650                 :            :
         651                 :            :
         652                 :            : #ifndef MS_WINDOWS
         653         [ +  - ]:          4 :     if (config->utf8_mode < 0) {
         654                 :            :         /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
         655                 :          4 :         const char *ctype_loc = setlocale(LC_CTYPE, NULL);
         656         [ +  - ]:          4 :         if (ctype_loc != NULL
         657         [ +  - ]:          4 :            && (strcmp(ctype_loc, "C") == 0
         658         [ -  + ]:          4 :                || strcmp(ctype_loc, "POSIX") == 0))
         659                 :            :         {
         660                 :          0 :             config->utf8_mode = 1;
         661                 :            :         }
         662                 :            :     }
         663                 :            : #endif
         664                 :            :
         665         [ +  - ]:          4 :     if (config->utf8_mode < 0) {
         666                 :          4 :         config->utf8_mode = 0;
         667                 :            :     }
         668                 :          4 :     return _PyStatus_OK();
         669                 :            : }
         670                 :            :
         671                 :            :
         672                 :            : static void
         673                 :         29 : preconfig_init_coerce_c_locale(PyPreConfig *config)
         674                 :            : {
         675         [ +  + ]:         29 :     if (!config->configure_locale) {
         676                 :         25 :         config->coerce_c_locale = 0;
         677                 :         25 :         config->coerce_c_locale_warn = 0;
         678                 :         25 :         return;
         679                 :            :     }
         680                 :            :
         681                 :          4 :     const char *env = _Py_GetEnv(config->use_environment, "PYTHONCOERCECLOCALE");
         682         [ -  + ]:          4 :     if (env) {
         683         [ #  # ]:          0 :         if (strcmp(env, "0") == 0) {
         684         [ #  # ]:          0 :             if (config->coerce_c_locale < 0) {
         685                 :          0 :                 config->coerce_c_locale = 0;
         686                 :            :             }
         687                 :            :         }
         688         [ #  # ]:          0 :         else if (strcmp(env, "warn") == 0) {
         689         [ #  # ]:          0 :             if (config->coerce_c_locale_warn < 0) {
         690                 :          0 :                 config->coerce_c_locale_warn = 1;
         691                 :            :             }
         692                 :            :         }
         693                 :            :         else {
         694         [ #  # ]:          0 :             if (config->coerce_c_locale < 0) {
         695                 :          0 :                 config->coerce_c_locale = 1;
         696                 :            :             }
         697                 :            :         }
         698                 :            :     }
         699                 :            :
         700                 :            :     /* Test if coerce_c_locale equals to -1 or equals to 1:
         701                 :            :        PYTHONCOERCECLOCALE=1 doesn't imply that the C locale is always coerced.
         702                 :            :        It is only coerced if if the LC_CTYPE locale is "C". */
         703   [ -  +  -  - ]:          4 :     if (config->coerce_c_locale < 0 || config->coerce_c_locale == 1) {
         704                 :            :         /* The C locale enables the C locale coercion (PEP 538) */
         705         [ -  + ]:          4 :         if (_Py_LegacyLocaleDetected(0)) {
         706                 :          0 :             config->coerce_c_locale = 2;
         707                 :            :         }
         708                 :            :         else {
         709                 :          4 :             config->coerce_c_locale = 0;
         710                 :            :         }
         711                 :            :     }
         712                 :            :
         713         [ +  - ]:          4 :     if (config->coerce_c_locale_warn < 0) {
         714                 :          4 :         config->coerce_c_locale_warn = 0;
         715                 :            :     }
         716                 :            : }
         717                 :            :
         718                 :            :
         719                 :            : static PyStatus
         720                 :         29 : preconfig_init_allocator(PyPreConfig *config)
         721                 :            : {
         722         [ +  - ]:         29 :     if (config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
         723                 :            :         /* bpo-34247. The PYTHONMALLOC environment variable has the priority
         724                 :            :            over PYTHONDEV env var and "-X dev" command line option.
         725                 :            :            For example, PYTHONMALLOC=malloc PYTHONDEVMODE=1 sets the memory
         726                 :            :            allocators to "malloc" (and not to "debug"). */
         727                 :         29 :         const char *envvar = _Py_GetEnv(config->use_environment, "PYTHONMALLOC");
         728         [ -  + ]:         29 :         if (envvar) {
         729                 :            :             PyMemAllocatorName name;
         730         [ #  # ]:          0 :             if (_PyMem_GetAllocatorName(envvar, &name) < 0) {
         731                 :          0 :                 return _PyStatus_ERR("PYTHONMALLOC: unknown allocator");
         732                 :            :             }
         733                 :          0 :             config->allocator = (int)name;
         734                 :            :         }
         735                 :            :     }
         736                 :            :
         737   [ -  +  -  - ]:         29 :     if (config->dev_mode && config->allocator == PYMEM_ALLOCATOR_NOT_SET) {
         738                 :          0 :         config->allocator = PYMEM_ALLOCATOR_DEBUG;
         739                 :            :     }
         740                 :         29 :     return _PyStatus_OK();
         741                 :            : }
         742                 :            :
         743                 :            :
         744                 :            : static PyStatus
         745                 :         29 : preconfig_read(PyPreConfig *config, _PyPreCmdline *cmdline)
         746                 :            : {
         747                 :            :     PyStatus status;
         748                 :            :
         749                 :         29 :     status = _PyPreCmdline_Read(cmdline, config);
         750         [ -  + ]:         29 :     if (_PyStatus_EXCEPTION(status)) {
         751                 :          0 :         return status;
         752                 :            :     }
         753                 :            :
         754                 :         29 :     precmdline_set_preconfig(cmdline, config);
         755                 :            :
         756                 :            :     /* legacy_windows_fs_encoding, coerce_c_locale, utf8_mode */
         757                 :            : #ifdef MS_WINDOWS
         758                 :            :     _Py_get_env_flag(config->use_environment,
         759                 :            :                      &config->legacy_windows_fs_encoding,
         760                 :            :                      "PYTHONLEGACYWINDOWSFSENCODING");
         761                 :            : #endif
         762                 :            :
         763                 :         29 :     preconfig_init_coerce_c_locale(config);
         764                 :            :
         765                 :         29 :     status = preconfig_init_utf8_mode(config, cmdline);
         766         [ -  + ]:         29 :     if (_PyStatus_EXCEPTION(status)) {
         767                 :          0 :         return status;
         768                 :            :     }
         769                 :            :
         770                 :            :     /* allocator */
         771                 :         29 :     status = preconfig_init_allocator(config);
         772         [ -  + ]:         29 :     if (_PyStatus_EXCEPTION(status)) {
         773                 :          0 :         return status;
         774                 :            :     }
         775                 :            :
         776                 :            :     assert(config->coerce_c_locale >= 0);
         777                 :            :     assert(config->coerce_c_locale_warn >= 0);
         778                 :            : #ifdef MS_WINDOWS
         779                 :            :     assert(config->legacy_windows_fs_encoding >= 0);
         780                 :            : #endif
         781                 :            :     assert(config->utf8_mode >= 0);
         782                 :            :     assert(config->isolated >= 0);
         783                 :            :     assert(config->use_environment >= 0);
         784                 :            :     assert(config->dev_mode >= 0);
         785                 :            :
         786                 :         29 :     return _PyStatus_OK();
         787                 :            : }
         788                 :            :
         789                 :            :
         790                 :            : /* Read the configuration from:
         791                 :            :
         792                 :            :    - command line arguments
         793                 :            :    - environment variables
         794                 :            :    - Py_xxx global configuration variables
         795                 :            :    - the LC_CTYPE locale */
         796                 :            : PyStatus
         797                 :         29 : _PyPreConfig_Read(PyPreConfig *config, const _PyArgv *args)
         798                 :            : {
         799                 :            :     PyStatus status;
         800                 :            :
         801                 :         29 :     status = _PyRuntime_Initialize();
         802         [ -  + ]:         29 :     if (_PyStatus_EXCEPTION(status)) {
         803                 :          0 :         return status;
         804                 :            :     }
         805                 :            :
         806                 :         29 :     preconfig_get_global_vars(config);
         807                 :            :
         808                 :            :     /* Copy LC_CTYPE locale, since it's modified later */
         809                 :         29 :     const char *loc = setlocale(LC_CTYPE, NULL);
         810         [ -  + ]:         29 :     if (loc == NULL) {
         811                 :          0 :         return _PyStatus_ERR("failed to LC_CTYPE locale");
         812                 :            :     }
         813                 :         29 :     char *init_ctype_locale = _PyMem_RawStrdup(loc);
         814         [ -  + ]:         29 :     if (init_ctype_locale == NULL) {
         815                 :          0 :         return _PyStatus_NO_MEMORY();
         816                 :            :     }
         817                 :            :
         818                 :            :     /* Save the config to be able to restore it if encodings change */
         819                 :            :     PyPreConfig save_config;
         820                 :            :
         821                 :         29 :     status = _PyPreConfig_InitFromPreConfig(&save_config, config);
         822         [ -  + ]:         29 :     if (_PyStatus_EXCEPTION(status)) {
         823                 :          0 :         return status;
         824                 :            :     }
         825                 :            :
         826                 :            :     /* Set LC_CTYPE to the user preferred locale */
         827         [ +  + ]:         29 :     if (config->configure_locale) {
         828                 :          4 :         _Py_SetLocaleFromEnv(LC_CTYPE);
         829                 :            :     }
         830                 :            :
         831                 :            :     PyPreConfig save_runtime_config;
         832                 :         29 :     preconfig_copy(&save_runtime_config, &_PyRuntime.preconfig);
         833                 :            :
         834                 :         29 :     _PyPreCmdline cmdline = _PyPreCmdline_INIT;
         835                 :         29 :     int locale_coerced = 0;
         836                 :         29 :     int loops = 0;
         837                 :            :
         838                 :          0 :     while (1) {
         839                 :         29 :         int utf8_mode = config->utf8_mode;
         840                 :            :
         841                 :            :         /* Watchdog to prevent an infinite loop */
         842                 :         29 :         loops++;
         843         [ -  + ]:         29 :         if (loops == 3) {
         844                 :          0 :             status = _PyStatus_ERR("Encoding changed twice while "
         845                 :            :                                    "reading the configuration");
         846                 :          0 :             goto done;
         847                 :            :         }
         848                 :            :
         849                 :            :         /* bpo-34207: Py_DecodeLocale() and Py_EncodeLocale() depend
         850                 :            :            on the utf8_mode and legacy_windows_fs_encoding members
         851                 :            :            of _PyRuntime.preconfig. */
         852                 :         29 :         preconfig_copy(&_PyRuntime.preconfig, config);
         853                 :            :
         854         [ +  + ]:         29 :         if (args) {
         855                 :            :             // Set command line arguments at each iteration. If they are bytes
         856                 :            :             // strings, they are decoded from the new encoding.
         857                 :         25 :             status = _PyPreCmdline_SetArgv(&cmdline, args);
         858         [ -  + ]:         25 :             if (_PyStatus_EXCEPTION(status)) {
         859                 :          0 :                 goto done;
         860                 :            :             }
         861                 :            :         }
         862                 :            :
         863                 :         29 :         status = preconfig_read(config, &cmdline);
         864         [ -  + ]:         29 :         if (_PyStatus_EXCEPTION(status)) {
         865                 :          0 :             goto done;
         866                 :            :         }
         867                 :            :
         868                 :            :         /* The legacy C locale assumes ASCII as the default text encoding, which
         869                 :            :          * causes problems not only for the CPython runtime, but also other
         870                 :            :          * components like GNU readline.
         871                 :            :          *
         872                 :            :          * Accordingly, when the CLI detects it, it attempts to coerce it to a
         873                 :            :          * more capable UTF-8 based alternative.
         874                 :            :          *
         875                 :            :          * See the documentation of the PYTHONCOERCECLOCALE setting for more
         876                 :            :          * details.
         877                 :            :          */
         878                 :         29 :         int encoding_changed = 0;
         879   [ -  +  -  - ]:         29 :         if (config->coerce_c_locale && !locale_coerced) {
         880                 :          0 :             locale_coerced = 1;
         881                 :          0 :             _Py_CoerceLegacyLocale(0);
         882                 :          0 :             encoding_changed = 1;
         883                 :            :         }
         884                 :            :
         885         [ +  + ]:         29 :         if (utf8_mode == -1) {
         886         [ -  + ]:          4 :             if (config->utf8_mode == 1) {
         887                 :            :                 /* UTF-8 Mode enabled */
         888                 :          0 :                 encoding_changed = 1;
         889                 :            :             }
         890                 :            :         }
         891                 :            :         else {
         892         [ -  + ]:         25 :             if (config->utf8_mode != utf8_mode) {
         893                 :          0 :                 encoding_changed = 1;
         894                 :            :             }
         895                 :            :         }
         896                 :            :
         897         [ +  - ]:         29 :         if (!encoding_changed) {
         898                 :         29 :             break;
         899                 :            :         }
         900                 :            :
         901                 :            :         /* Reset the configuration before reading again the configuration,
         902                 :            :            just keep UTF-8 Mode and coerce C locale value. */
         903                 :          0 :         int new_utf8_mode = config->utf8_mode;
         904                 :          0 :         int new_coerce_c_locale = config->coerce_c_locale;
         905                 :          0 :         preconfig_copy(config, &save_config);
         906                 :          0 :         config->utf8_mode = new_utf8_mode;
         907                 :          0 :         config->coerce_c_locale = new_coerce_c_locale;
         908                 :            :
         909                 :            :         /* The encoding changed: read again the configuration
         910                 :            :            with the new encoding */
         911                 :            :     }
         912                 :         29 :     status = _PyStatus_OK();
         913                 :            :
         914                 :         29 : done:
         915                 :            :     // Revert side effects
         916                 :         29 :     setlocale(LC_CTYPE, init_ctype_locale);
         917                 :         29 :     PyMem_RawFree(init_ctype_locale);
         918                 :         29 :     preconfig_copy(&_PyRuntime.preconfig, &save_runtime_config);
         919                 :         29 :     _PyPreCmdline_Clear(&cmdline);
         920                 :         29 :     return status;
         921                 :            : }
         922                 :            :
         923                 :            :
         924                 :            : /* Write the pre-configuration:
         925                 :            :
         926                 :            :    - set the memory allocators
         927                 :            :    - set Py_xxx global configuration variables
         928                 :            :    - set the LC_CTYPE locale (coerce C locale, PEP 538) and set the UTF-8 mode
         929                 :            :      (PEP 540)
         930                 :            :
         931                 :            :    The applied configuration is written into _PyRuntime.preconfig.
         932                 :            :    If the C locale cannot be coerced, set coerce_c_locale to 0.
         933                 :            :
         934                 :            :    Do nothing if called after Py_Initialize(): ignore the new
         935                 :            :    pre-configuration. */
         936                 :            : PyStatus
         937                 :         29 : _PyPreConfig_Write(const PyPreConfig *src_config)
         938                 :            : {
         939                 :            :     PyPreConfig config;
         940                 :            :
         941                 :         29 :     PyStatus status = _PyPreConfig_InitFromPreConfig(&config, src_config);
         942         [ -  + ]:         29 :     if (_PyStatus_EXCEPTION(status)) {
         943                 :          0 :         return status;
         944                 :            :     }
         945                 :            :
         946         [ -  + ]:         29 :     if (_PyRuntime.core_initialized) {
         947                 :            :         /* bpo-34008: Calling this functions after Py_Initialize() ignores
         948                 :            :            the new configuration. */
         949                 :          0 :         return _PyStatus_OK();
         950                 :            :     }
         951                 :            :
         952                 :         29 :     PyMemAllocatorName name = (PyMemAllocatorName)config.allocator;
         953         [ -  + ]:         29 :     if (name != PYMEM_ALLOCATOR_NOT_SET) {
         954         [ #  # ]:          0 :         if (_PyMem_SetupAllocators(name) < 0) {
         955                 :          0 :             return _PyStatus_ERR("Unknown PYTHONMALLOC allocator");
         956                 :            :         }
         957                 :            :     }
         958                 :            :
         959                 :         29 :     preconfig_set_global_vars(&config);
         960                 :            :
         961         [ +  + ]:         29 :     if (config.configure_locale) {
         962         [ -  + ]:          4 :         if (config.coerce_c_locale) {
         963         [ #  # ]:          0 :             if (!_Py_CoerceLegacyLocale(config.coerce_c_locale_warn)) {
         964                 :            :                 /* C locale not coerced */
         965                 :          0 :                 config.coerce_c_locale = 0;
         966                 :            :             }
         967                 :            :         }
         968                 :            :
         969                 :            :         /* Set LC_CTYPE to the user preferred locale */
         970                 :          4 :         _Py_SetLocaleFromEnv(LC_CTYPE);
         971                 :            :     }
         972                 :            :
         973                 :            :     /* Write the new pre-configuration into _PyRuntime */
         974                 :         29 :     preconfig_copy(&_PyRuntime.preconfig, &config);
         975                 :            :
         976                 :         29 :     return _PyStatus_OK();
         977                 :            : }

Generated by: LCOV version 1.14