LCOV - code coverage report
Current view: top level - Python - initconfig.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit 5e6661bce9] Lines: 831 1406 59.1 %
Date: 2023-03-20 08:15:36 Functions: 61 86 70.9 %
Branches: 543 1351 40.2 %

           Branch data     Line data    Source code
       1                 :            : #include "Python.h"
       2                 :            : #include "pycore_fileutils.h"     // _Py_HasFileSystemDefaultEncodeErrors
       3                 :            : #include "pycore_getopt.h"        // _PyOS_GetOpt()
       4                 :            : #include "pycore_initconfig.h"    // _PyStatus_OK()
       5                 :            : #include "pycore_interp.h"        // _PyInterpreterState.runtime
       6                 :            : #include "pycore_long.h"          // _PY_LONG_MAX_STR_DIGITS_THRESHOLD
       7                 :            : #include "pycore_pathconfig.h"    // _Py_path_config
       8                 :            : #include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
       9                 :            : #include "pycore_pylifecycle.h"   // _Py_PreInitializeFromConfig()
      10                 :            : #include "pycore_pymem.h"         // _PyMem_SetDefaultAllocator()
      11                 :            : #include "pycore_pystate.h"       // _PyThreadState_GET()
      12                 :            : 
      13                 :            : #include "osdefs.h"               // DELIM
      14                 :            : 
      15                 :            : #include <locale.h>               // setlocale()
      16                 :            : #include <stdlib.h>               // getenv()
      17                 :            : #if defined(MS_WINDOWS) || defined(__CYGWIN__)
      18                 :            : #  ifdef HAVE_IO_H
      19                 :            : #    include <io.h>
      20                 :            : #  endif
      21                 :            : #  ifdef HAVE_FCNTL_H
      22                 :            : #    include <fcntl.h>            // O_BINARY
      23                 :            : #  endif
      24                 :            : #endif
      25                 :            : 
      26                 :            : /* --- Command line options --------------------------------------- */
      27                 :            : 
      28                 :            : /* Short usage message (with %s for argv0) */
      29                 :            : static const char usage_line[] =
      30                 :            : "usage: %ls [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
      31                 :            : 
      32                 :            : /* Long help message */
      33                 :            : /* Lines sorted by option name; keep in sync with usage_envvars* below */
      34                 :            : static const char usage_help[] = "\
      35                 :            : Options (and corresponding environment variables):\n\
      36                 :            : -b     : issue warnings about str(bytes_instance), str(bytearray_instance)\n\
      37                 :            :          and comparing bytes/bytearray with str. (-bb: issue errors)\n\
      38                 :            : -B     : don't write .pyc files on import; also PYTHONDONTWRITEBYTECODE=x\n\
      39                 :            : -c cmd : program passed in as string (terminates option list)\n\
      40                 :            : -d     : turn on parser debugging output (for experts only, only works on\n\
      41                 :            :          debug builds); also PYTHONDEBUG=x\n\
      42                 :            : -E     : ignore PYTHON* environment variables (such as PYTHONPATH)\n\
      43                 :            : -h     : print this help message and exit (also -? or --help)\n\
      44                 :            : -i     : inspect interactively after running script; forces a prompt even\n\
      45                 :            :          if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\
      46                 :            : -I     : isolate Python from the user's environment (implies -E and -s)\n\
      47                 :            : -m mod : run library module as a script (terminates option list)\n\
      48                 :            : -O     : remove assert and __debug__-dependent statements; add .opt-1 before\n\
      49                 :            :          .pyc extension; also PYTHONOPTIMIZE=x\n\
      50                 :            : -OO    : do -O changes and also discard docstrings; add .opt-2 before\n\
      51                 :            :          .pyc extension\n\
      52                 :            : -P     : don't prepend a potentially unsafe path to sys.path\n\
      53                 :            : -q     : don't print version and copyright messages on interactive startup\n\
      54                 :            : -s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\
      55                 :            : -S     : don't imply 'import site' on initialization\n\
      56                 :            : -u     : force the stdout and stderr streams to be unbuffered;\n\
      57                 :            :          this option has no effect on stdin; also PYTHONUNBUFFERED=x\n\
      58                 :            : -v     : verbose (trace import statements); also PYTHONVERBOSE=x\n\
      59                 :            :          can be supplied multiple times to increase verbosity\n\
      60                 :            : -V     : print the Python version number and exit (also --version)\n\
      61                 :            :          when given twice, print more information about the build\n\
      62                 :            : -W arg : warning control; arg is action:message:category:module:lineno\n\
      63                 :            :          also PYTHONWARNINGS=arg\n\
      64                 :            : -x     : skip first line of source, allowing use of non-Unix forms of #!cmd\n\
      65                 :            : -X opt : set implementation-specific option\n\
      66                 :            : --check-hash-based-pycs always|default|never:\n\
      67                 :            :          control how Python invalidates hash-based .pyc files\n\
      68                 :            : --help-env      : print help about Python environment variables and exit\n\
      69                 :            : --help-xoptions : print help about implementation-specific -X options and exit\n\
      70                 :            : --help-all      : print complete help information and exit\n\
      71                 :            : Arguments:\n\
      72                 :            : file   : program read from script file\n\
      73                 :            : -      : program read from stdin (default; interactive mode if a tty)\n\
      74                 :            : arg ...: arguments passed to program in sys.argv[1:]\n\
      75                 :            : ";
      76                 :            : 
      77                 :            : static const char usage_xoptions[] = "\
      78                 :            : The following implementation-specific options are available:\n\
      79                 :            : \n\
      80                 :            : -X faulthandler: enable faulthandler\n\
      81                 :            : \n\
      82                 :            : -X showrefcount: output the total reference count and number of used\n\
      83                 :            :     memory blocks when the program finishes or after each statement in the\n\
      84                 :            :     interactive interpreter. This only works on debug builds\n\
      85                 :            : \n\
      86                 :            : -X tracemalloc: start tracing Python memory allocations using the\n\
      87                 :            :     tracemalloc module. By default, only the most recent frame is stored in a\n\
      88                 :            :     traceback of a trace. Use -X tracemalloc=NFRAME to start tracing with a\n\
      89                 :            :     traceback limit of NFRAME frames\n\
      90                 :            : \n\
      91                 :            : -X importtime: show how long each import takes. It shows module name,\n\
      92                 :            :     cumulative time (including nested imports) and self time (excluding\n\
      93                 :            :     nested imports). Note that its output may be broken in multi-threaded\n\
      94                 :            :     application. Typical usage is python3 -X importtime -c 'import asyncio'\n\
      95                 :            : \n\
      96                 :            : -X dev: enable CPython's \"development mode\", introducing additional runtime\n\
      97                 :            :     checks which are too expensive to be enabled by default. Effect of the\n\
      98                 :            :     developer mode:\n\
      99                 :            :        * Add default warning filter, as -W default\n\
     100                 :            :        * Install debug hooks on memory allocators: see the PyMem_SetupDebugHooks()\n\
     101                 :            :          C function\n\
     102                 :            :        * Enable the faulthandler module to dump the Python traceback on a crash\n\
     103                 :            :        * Enable asyncio debug mode\n\
     104                 :            :        * Set the dev_mode attribute of sys.flags to True\n\
     105                 :            :        * io.IOBase destructor logs close() exceptions\n\
     106                 :            : \n\
     107                 :            : -X utf8: enable UTF-8 mode for operating system interfaces, overriding the default\n\
     108                 :            :     locale-aware mode. -X utf8=0 explicitly disables UTF-8 mode (even when it would\n\
     109                 :            :     otherwise activate automatically)\n\
     110                 :            : \n\
     111                 :            : -X pycache_prefix=PATH: enable writing .pyc files to a parallel tree rooted at the\n\
     112                 :            :     given directory instead of to the code tree\n\
     113                 :            : \n\
     114                 :            : -X warn_default_encoding: enable opt-in EncodingWarning for 'encoding=None'\n\
     115                 :            : \n\
     116                 :            : -X no_debug_ranges: disable the inclusion of the tables mapping extra location \n\
     117                 :            :    information (end line, start column offset and end column offset) to every \n\
     118                 :            :    instruction in code objects. This is useful when smaller code objects and pyc \n\
     119                 :            :    files are desired as well as suppressing the extra visual location indicators \n\
     120                 :            :    when the interpreter displays tracebacks.\n\
     121                 :            : \n\
     122                 :            : -X perf: activate support for the Linux \"perf\" profiler by activating the \"perf\"\n\
     123                 :            :     trampoline. When this option is activated, the Linux \"perf\" profiler will be \n\
     124                 :            :     able to report Python calls. This option is only available on some platforms and will \n\
     125                 :            :     do nothing if is not supported on the current system. The default value is \"off\".\n\
     126                 :            : \n\
     127                 :            : -X frozen_modules=[on|off]: whether or not frozen modules should be used.\n\
     128                 :            :    The default is \"on\" (or \"off\" if you are running a local build).\n\
     129                 :            : \n\
     130                 :            : -X int_max_str_digits=number: limit the size of int<->str conversions.\n\
     131                 :            :     This helps avoid denial of service attacks when parsing untrusted data.\n\
     132                 :            :     The default is sys.int_info.default_max_str_digits.  0 disables."
     133                 :            : 
     134                 :            : #ifdef Py_STATS
     135                 :            : "\n\
     136                 :            : \n\
     137                 :            : -X pystats: Enable pystats collection at startup."
     138                 :            : #endif
     139                 :            : ;
     140                 :            : 
     141                 :            : /* Envvars that don't have equivalent command-line options are listed first */
     142                 :            : static const char usage_envvars[] =
     143                 :            : "Environment variables that change behavior:\n"
     144                 :            : "PYTHONSTARTUP: file executed on interactive startup (no default)\n"
     145                 :            : "PYTHONPATH   : '%lc'-separated list of directories prefixed to the\n"
     146                 :            : "               default module search path.  The result is sys.path.\n"
     147                 :            : "PYTHONSAFEPATH: don't prepend a potentially unsafe path to sys.path.\n"
     148                 :            : "PYTHONHOME   : alternate <prefix> directory (or <prefix>%lc<exec_prefix>).\n"
     149                 :            : "               The default module search path uses %s.\n"
     150                 :            : "PYTHONPLATLIBDIR : override sys.platlibdir.\n"
     151                 :            : "PYTHONCASEOK : ignore case in 'import' statements (Windows).\n"
     152                 :            : "PYTHONUTF8: if set to 1, enable the UTF-8 mode.\n"
     153                 :            : "PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\n"
     154                 :            : "PYTHONFAULTHANDLER: dump the Python traceback on fatal errors.\n"
     155                 :            : "PYTHONHASHSEED: if this variable is set to 'random', a random value is used\n"
     156                 :            : "   to seed the hashes of str and bytes objects.  It can also be set to an\n"
     157                 :            : "   integer in the range [0,4294967295] to get hash values with a\n"
     158                 :            : "   predictable seed.\n"
     159                 :            : "PYTHONINTMAXSTRDIGITS: limits the maximum digit characters in an int value\n"
     160                 :            : "   when converting from a string and when converting an int back to a str.\n"
     161                 :            : "   A value of 0 disables the limit.  Conversions to or from bases 2, 4, 8,\n"
     162                 :            : "   16, and 32 are never limited.\n"
     163                 :            : "PYTHONMALLOC: set the Python memory allocators and/or install debug hooks\n"
     164                 :            : "   on Python memory allocators. Use PYTHONMALLOC=debug to install debug\n"
     165                 :            : "   hooks.\n"
     166                 :            : "PYTHONCOERCECLOCALE: if this variable is set to 0, it disables the locale\n"
     167                 :            : "   coercion behavior. Use PYTHONCOERCECLOCALE=warn to request display of\n"
     168                 :            : "   locale coercion and locale compatibility warnings on stderr.\n"
     169                 :            : "PYTHONBREAKPOINT: if this variable is set to 0, it disables the default\n"
     170                 :            : "   debugger. It can be set to the callable of your debugger of choice.\n"
     171                 :            : "PYTHONDEVMODE: enable the development mode.\n"
     172                 :            : "PYTHONPYCACHEPREFIX: root directory for bytecode cache (pyc) files.\n"
     173                 :            : "PYTHONWARNDEFAULTENCODING: enable opt-in EncodingWarning for 'encoding=None'.\n"
     174                 :            : "PYTHONNODEBUGRANGES: If this variable is set, it disables the inclusion of the \n"
     175                 :            : "   tables mapping extra location information (end line, start column offset \n"
     176                 :            : "   and end column offset) to every instruction in code objects. This is useful \n"
     177                 :            : "   when smaller code objects and pyc files are desired as well as suppressing the \n"
     178                 :            : "   extra visual location indicators when the interpreter displays tracebacks.\n"
     179                 :            : "These variables have equivalent command-line parameters (see --help for details):\n"
     180                 :            : "PYTHONDEBUG             : enable parser debug mode (-d)\n"
     181                 :            : "PYTHONDONTWRITEBYTECODE : don't write .pyc files (-B)\n"
     182                 :            : "PYTHONINSPECT           : inspect interactively after running script (-i)\n"
     183                 :            : "PYTHONINTMAXSTRDIGITS   : limit max digit characters in an int value\n"
     184                 :            : "                          (-X int_max_str_digits=number)\n"
     185                 :            : "PYTHONNOUSERSITE        : disable user site directory (-s)\n"
     186                 :            : "PYTHONOPTIMIZE          : enable level 1 optimizations (-O)\n"
     187                 :            : "PYTHONUNBUFFERED        : disable stdout/stderr buffering (-u)\n"
     188                 :            : "PYTHONVERBOSE           : trace import statements (-v)\n"
     189                 :            : "PYTHONWARNINGS=arg      : warning control (-W arg)\n";
     190                 :            : 
     191                 :            : #if defined(MS_WINDOWS)
     192                 :            : #  define PYTHONHOMEHELP "<prefix>\\python{major}{minor}"
     193                 :            : #else
     194                 :            : #  define PYTHONHOMEHELP "<prefix>/lib/pythonX.X"
     195                 :            : #endif
     196                 :            : 
     197                 :            : 
     198                 :            : /* --- Global configuration variables ----------------------------- */
     199                 :            : 
     200                 :            : /* UTF-8 mode (PEP 540): if equals to 1, use the UTF-8 encoding, and change
     201                 :            :    stdin and stdout error handler to "surrogateescape". */
     202                 :            : int Py_UTF8Mode = 0;
     203                 :            : int Py_DebugFlag = 0; /* Needed by parser.c */
     204                 :            : int Py_VerboseFlag = 0; /* Needed by import.c */
     205                 :            : int Py_QuietFlag = 0; /* Needed by sysmodule.c */
     206                 :            : int Py_InteractiveFlag = 0; /* Previously, was used by Py_FdIsInteractive() */
     207                 :            : int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */
     208                 :            : int Py_OptimizeFlag = 0; /* Needed by compile.c */
     209                 :            : int Py_NoSiteFlag = 0; /* Suppress 'import site' */
     210                 :            : int Py_BytesWarningFlag = 0; /* Warn on str(bytes) and str(buffer) */
     211                 :            : int Py_FrozenFlag = 0; /* Needed by getpath.c */
     212                 :            : int Py_IgnoreEnvironmentFlag = 0; /* e.g. PYTHONPATH, PYTHONHOME */
     213                 :            : int Py_DontWriteBytecodeFlag = 0; /* Suppress writing bytecode files (*.pyc) */
     214                 :            : int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
     215                 :            : int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
     216                 :            : int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
     217                 :            : int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */
     218                 :            : #ifdef MS_WINDOWS
     219                 :            : int Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */
     220                 :            : int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */
     221                 :            : #endif
     222                 :            : 
     223                 :            : 
     224                 :            : static PyObject *
     225                 :          0 : _Py_GetGlobalVariablesAsDict(void)
     226                 :            : {
     227                 :            : _Py_COMP_DIAG_PUSH
     228                 :            : _Py_COMP_DIAG_IGNORE_DEPR_DECLS
     229                 :            :     PyObject *dict, *obj;
     230                 :            : 
     231                 :          0 :     dict = PyDict_New();
     232         [ #  # ]:          0 :     if (dict == NULL) {
     233                 :          0 :         return NULL;
     234                 :            :     }
     235                 :            : 
     236                 :            : #define SET_ITEM(KEY, EXPR) \
     237                 :            :         do { \
     238                 :            :             obj = (EXPR); \
     239                 :            :             if (obj == NULL) { \
     240                 :            :                 return NULL; \
     241                 :            :             } \
     242                 :            :             int res = PyDict_SetItemString(dict, (KEY), obj); \
     243                 :            :             Py_DECREF(obj); \
     244                 :            :             if (res < 0) { \
     245                 :            :                 goto fail; \
     246                 :            :             } \
     247                 :            :         } while (0)
     248                 :            : #define SET_ITEM_INT(VAR) \
     249                 :            :     SET_ITEM(#VAR, PyLong_FromLong(VAR))
     250                 :            : #define FROM_STRING(STR) \
     251                 :            :     ((STR != NULL) ? \
     252                 :            :         PyUnicode_FromString(STR) \
     253                 :            :         : Py_NewRef(Py_None))
     254                 :            : #define SET_ITEM_STR(VAR) \
     255                 :            :     SET_ITEM(#VAR, FROM_STRING(VAR))
     256                 :            : 
     257   [ #  #  #  #  :          0 :     SET_ITEM_STR(Py_FileSystemDefaultEncoding);
                   #  # ]
     258   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_HasFileSystemDefaultEncoding);
     259   [ #  #  #  #  :          0 :     SET_ITEM_STR(Py_FileSystemDefaultEncodeErrors);
                   #  # ]
     260   [ #  #  #  # ]:          0 :     SET_ITEM_INT(_Py_HasFileSystemDefaultEncodeErrors);
     261                 :            : 
     262   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_UTF8Mode);
     263   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_DebugFlag);
     264   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_VerboseFlag);
     265   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_QuietFlag);
     266   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_InteractiveFlag);
     267   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_InspectFlag);
     268                 :            : 
     269   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_OptimizeFlag);
     270   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_NoSiteFlag);
     271   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_BytesWarningFlag);
     272   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_FrozenFlag);
     273   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_IgnoreEnvironmentFlag);
     274   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_DontWriteBytecodeFlag);
     275   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_NoUserSiteDirectory);
     276   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_UnbufferedStdioFlag);
     277   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_HashRandomizationFlag);
     278   [ #  #  #  # ]:          0 :     SET_ITEM_INT(Py_IsolatedFlag);
     279                 :            : 
     280                 :            : #ifdef MS_WINDOWS
     281                 :            :     SET_ITEM_INT(Py_LegacyWindowsFSEncodingFlag);
     282                 :            :     SET_ITEM_INT(Py_LegacyWindowsStdioFlag);
     283                 :            : #endif
     284                 :            : 
     285                 :          0 :     return dict;
     286                 :            : 
     287                 :          0 : fail:
     288                 :          0 :     Py_DECREF(dict);
     289                 :          0 :     return NULL;
     290                 :            : 
     291                 :            : #undef FROM_STRING
     292                 :            : #undef SET_ITEM
     293                 :            : #undef SET_ITEM_INT
     294                 :            : #undef SET_ITEM_STR
     295                 :            : _Py_COMP_DIAG_POP
     296                 :            : }
     297                 :            : 
     298                 :            : char*
     299                 :         29 : Py_GETENV(const char *name)
     300                 :            : {
     301                 :            : _Py_COMP_DIAG_PUSH
     302                 :            : _Py_COMP_DIAG_IGNORE_DEPR_DECLS
     303         [ +  + ]:         29 :     if (Py_IgnoreEnvironmentFlag) {
     304                 :         28 :         return NULL;
     305                 :            :     }
     306                 :          1 :     return getenv(name);
     307                 :            : _Py_COMP_DIAG_POP
     308                 :            : }
     309                 :            : 
     310                 :            : /* --- PyStatus ----------------------------------------------- */
     311                 :            : 
     312                 :         29 : PyStatus PyStatus_Ok(void)
     313                 :         29 : { return _PyStatus_OK(); }
     314                 :            : 
     315                 :          0 : PyStatus PyStatus_Error(const char *err_msg)
     316                 :            : {
     317                 :            :     assert(err_msg != NULL);
     318                 :          0 :     return (PyStatus){._type = _PyStatus_TYPE_ERROR,
     319                 :            :                       .err_msg = err_msg};
     320                 :            : }
     321                 :            : 
     322                 :          0 : PyStatus PyStatus_NoMemory(void)
     323                 :          0 : { return PyStatus_Error("memory allocation failed"); }
     324                 :            : 
     325                 :          0 : PyStatus PyStatus_Exit(int exitcode)
     326                 :          0 : { return _PyStatus_EXIT(exitcode); }
     327                 :            : 
     328                 :            : 
     329                 :          0 : int PyStatus_IsError(PyStatus status)
     330                 :          0 : { return _PyStatus_IS_ERROR(status); }
     331                 :            : 
     332                 :          0 : int PyStatus_IsExit(PyStatus status)
     333                 :          0 : { return _PyStatus_IS_EXIT(status); }
     334                 :            : 
     335                 :         50 : int PyStatus_Exception(PyStatus status)
     336                 :         50 : { return _PyStatus_EXCEPTION(status); }
     337                 :            : 
     338                 :            : PyObject*
     339                 :          0 : _PyErr_SetFromPyStatus(PyStatus status)
     340                 :            : {
     341         [ #  # ]:          0 :     if (!_PyStatus_IS_ERROR(status)) {
     342                 :          0 :         PyErr_Format(PyExc_SystemError,
     343                 :            :                      "%s() expects an error PyStatus",
     344                 :            :                      _PyStatus_GET_FUNC());
     345                 :            :     }
     346         [ #  # ]:          0 :     else if (status.func) {
     347                 :          0 :         PyErr_Format(PyExc_ValueError, "%s: %s", status.func, status.err_msg);
     348                 :            :     }
     349                 :            :     else {
     350                 :          0 :         PyErr_Format(PyExc_ValueError, "%s", status.err_msg);
     351                 :            :     }
     352                 :          0 :     return NULL;
     353                 :            : }
     354                 :            : 
     355                 :            : 
     356                 :            : /* --- PyWideStringList ------------------------------------------------ */
     357                 :            : 
     358                 :            : #ifndef NDEBUG
     359                 :            : int
     360                 :            : _PyWideStringList_CheckConsistency(const PyWideStringList *list)
     361                 :            : {
     362                 :            :     assert(list->length >= 0);
     363                 :            :     if (list->length != 0) {
     364                 :            :         assert(list->items != NULL);
     365                 :            :     }
     366                 :            :     for (Py_ssize_t i = 0; i < list->length; i++) {
     367                 :            :         assert(list->items[i] != NULL);
     368                 :            :     }
     369                 :            :     return 1;
     370                 :            : }
     371                 :            : #endif   /* Py_DEBUG */
     372                 :            : 
     373                 :            : 
     374                 :            : void
     375                 :       1811 : _PyWideStringList_Clear(PyWideStringList *list)
     376                 :            : {
     377                 :            :     assert(_PyWideStringList_CheckConsistency(list));
     378         [ +  + ]:       3815 :     for (Py_ssize_t i=0; i < list->length; i++) {
     379                 :       2004 :         PyMem_RawFree(list->items[i]);
     380                 :            :     }
     381                 :       1811 :     PyMem_RawFree(list->items);
     382                 :       1811 :     list->length = 0;
     383                 :       1811 :     list->items = NULL;
     384                 :       1811 : }
     385                 :            : 
     386                 :            : 
     387                 :            : int
     388                 :        523 : _PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2)
     389                 :            : {
     390                 :            :     assert(_PyWideStringList_CheckConsistency(list));
     391                 :            :     assert(_PyWideStringList_CheckConsistency(list2));
     392                 :            : 
     393         [ +  + ]:        523 :     if (list2->length == 0) {
     394                 :        248 :         _PyWideStringList_Clear(list);
     395                 :        248 :         return 0;
     396                 :            :     }
     397                 :            : 
     398                 :        275 :     PyWideStringList copy = _PyWideStringList_INIT;
     399                 :            : 
     400                 :        275 :     size_t size = list2->length * sizeof(list2->items[0]);
     401                 :        275 :     copy.items = PyMem_RawMalloc(size);
     402         [ -  + ]:        275 :     if (copy.items == NULL) {
     403                 :          0 :         return -1;
     404                 :            :     }
     405                 :            : 
     406         [ +  + ]:       1660 :     for (Py_ssize_t i=0; i < list2->length; i++) {
     407                 :       1385 :         wchar_t *item = _PyMem_RawWcsdup(list2->items[i]);
     408         [ -  + ]:       1385 :         if (item == NULL) {
     409                 :          0 :             _PyWideStringList_Clear(&copy);
     410                 :          0 :             return -1;
     411                 :            :         }
     412                 :       1385 :         copy.items[i] = item;
     413                 :       1385 :         copy.length = i + 1;
     414                 :            :     }
     415                 :            : 
     416                 :        275 :     _PyWideStringList_Clear(list);
     417                 :        275 :     *list = copy;
     418                 :        275 :     return 0;
     419                 :            : }
     420                 :            : 
     421                 :            : 
     422                 :            : PyStatus
     423                 :        335 : PyWideStringList_Insert(PyWideStringList *list,
     424                 :            :                         Py_ssize_t index, const wchar_t *item)
     425                 :            : {
     426                 :        335 :     Py_ssize_t len = list->length;
     427         [ -  + ]:        335 :     if (len == PY_SSIZE_T_MAX) {
     428                 :            :         /* length+1 would overflow */
     429                 :          0 :         return _PyStatus_NO_MEMORY();
     430                 :            :     }
     431         [ -  + ]:        335 :     if (index < 0) {
     432                 :          0 :         return _PyStatus_ERR("PyWideStringList_Insert index must be >= 0");
     433                 :            :     }
     434         [ -  + ]:        335 :     if (index > len) {
     435                 :          0 :         index = len;
     436                 :            :     }
     437                 :            : 
     438                 :        335 :     wchar_t *item2 = _PyMem_RawWcsdup(item);
     439         [ -  + ]:        335 :     if (item2 == NULL) {
     440                 :          0 :         return _PyStatus_NO_MEMORY();
     441                 :            :     }
     442                 :            : 
     443                 :        335 :     size_t size = (len + 1) * sizeof(list->items[0]);
     444                 :        335 :     wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size);
     445         [ -  + ]:        335 :     if (items2 == NULL) {
     446                 :          0 :         PyMem_RawFree(item2);
     447                 :          0 :         return _PyStatus_NO_MEMORY();
     448                 :            :     }
     449                 :            : 
     450         [ -  + ]:        335 :     if (index < len) {
     451                 :          0 :         memmove(&items2[index + 1],
     452                 :          0 :                 &items2[index],
     453                 :          0 :                 (len - index) * sizeof(items2[0]));
     454                 :            :     }
     455                 :            : 
     456                 :        335 :     items2[index] = item2;
     457                 :        335 :     list->items = items2;
     458                 :        335 :     list->length++;
     459                 :        335 :     return _PyStatus_OK();
     460                 :            : }
     461                 :            : 
     462                 :            : 
     463                 :            : PyStatus
     464                 :        335 : PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
     465                 :            : {
     466                 :        335 :     return PyWideStringList_Insert(list, list->length, item);
     467                 :            : }
     468                 :            : 
     469                 :            : 
     470                 :            : PyStatus
     471                 :        100 : _PyWideStringList_Extend(PyWideStringList *list, const PyWideStringList *list2)
     472                 :            : {
     473         [ -  + ]:        100 :     for (Py_ssize_t i = 0; i < list2->length; i++) {
     474                 :          0 :         PyStatus status = PyWideStringList_Append(list, list2->items[i]);
     475         [ #  # ]:          0 :         if (_PyStatus_EXCEPTION(status)) {
     476                 :          0 :             return status;
     477                 :            :         }
     478                 :            :     }
     479                 :        100 :     return _PyStatus_OK();
     480                 :            : }
     481                 :            : 
     482                 :            : 
     483                 :            : static int
     484                 :          0 : _PyWideStringList_Find(PyWideStringList *list, const wchar_t *item)
     485                 :            : {
     486         [ #  # ]:          0 :     for (Py_ssize_t i = 0; i < list->length; i++) {
     487         [ #  # ]:          0 :         if (wcscmp(list->items[i], item) == 0) {
     488                 :          0 :             return 1;
     489                 :            :         }
     490                 :            :     }
     491                 :          0 :     return 0;
     492                 :            : }
     493                 :            : 
     494                 :            : 
     495                 :            : PyObject*
     496                 :        225 : _PyWideStringList_AsList(const PyWideStringList *list)
     497                 :            : {
     498                 :            :     assert(_PyWideStringList_CheckConsistency(list));
     499                 :            : 
     500                 :        225 :     PyObject *pylist = PyList_New(list->length);
     501         [ -  + ]:        225 :     if (pylist == NULL) {
     502                 :          0 :         return NULL;
     503                 :            :     }
     504                 :            : 
     505         [ +  + ]:        812 :     for (Py_ssize_t i = 0; i < list->length; i++) {
     506                 :        587 :         PyObject *item = PyUnicode_FromWideChar(list->items[i], -1);
     507         [ -  + ]:        587 :         if (item == NULL) {
     508                 :          0 :             Py_DECREF(pylist);
     509                 :          0 :             return NULL;
     510                 :            :         }
     511                 :        587 :         PyList_SET_ITEM(pylist, i, item);
     512                 :            :     }
     513                 :        225 :     return pylist;
     514                 :            : }
     515                 :            : 
     516                 :            : 
     517                 :            : /* --- Py_SetStandardStreamEncoding() ----------------------------- */
     518                 :            : 
     519                 :            : /* Helper to allow an embedding application to override the normal
     520                 :            :  * mechanism that attempts to figure out an appropriate IO encoding
     521                 :            :  */
     522                 :            : 
     523                 :            : static char *_Py_StandardStreamEncoding = NULL;
     524                 :            : static char *_Py_StandardStreamErrors = NULL;
     525                 :            : 
     526                 :            : int
     527                 :          0 : Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
     528                 :            : {
     529         [ #  # ]:          0 :     if (Py_IsInitialized()) {
     530                 :            :         /* This is too late to have any effect */
     531                 :          0 :         return -1;
     532                 :            :     }
     533                 :            : 
     534                 :          0 :     int res = 0;
     535                 :            : 
     536                 :            :     /* Py_SetStandardStreamEncoding() can be called before Py_Initialize(),
     537                 :            :        but Py_Initialize() can change the allocator. Use a known allocator
     538                 :            :        to be able to release the memory later. */
     539                 :            :     PyMemAllocatorEx old_alloc;
     540                 :          0 :     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
     541                 :            : 
     542                 :            :     /* Can't call PyErr_NoMemory() on errors, as Python hasn't been
     543                 :            :      * initialised yet.
     544                 :            :      *
     545                 :            :      * However, the raw memory allocators are initialised appropriately
     546                 :            :      * as C static variables, so _PyMem_RawStrdup is OK even though
     547                 :            :      * Py_Initialize hasn't been called yet.
     548                 :            :      */
     549         [ #  # ]:          0 :     if (encoding) {
     550                 :          0 :         PyMem_RawFree(_Py_StandardStreamEncoding);
     551                 :          0 :         _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding);
     552         [ #  # ]:          0 :         if (!_Py_StandardStreamEncoding) {
     553                 :          0 :             res = -2;
     554                 :          0 :             goto done;
     555                 :            :         }
     556                 :            :     }
     557         [ #  # ]:          0 :     if (errors) {
     558                 :          0 :         PyMem_RawFree(_Py_StandardStreamErrors);
     559                 :          0 :         _Py_StandardStreamErrors = _PyMem_RawStrdup(errors);
     560         [ #  # ]:          0 :         if (!_Py_StandardStreamErrors) {
     561                 :          0 :             PyMem_RawFree(_Py_StandardStreamEncoding);
     562                 :          0 :             _Py_StandardStreamEncoding = NULL;
     563                 :          0 :             res = -3;
     564                 :          0 :             goto done;
     565                 :            :         }
     566                 :            :     }
     567                 :            : #ifdef MS_WINDOWS
     568                 :            :     if (_Py_StandardStreamEncoding) {
     569                 :            : _Py_COMP_DIAG_PUSH
     570                 :            : _Py_COMP_DIAG_IGNORE_DEPR_DECLS
     571                 :            :         /* Overriding the stream encoding implies legacy streams */
     572                 :            :         Py_LegacyWindowsStdioFlag = 1;
     573                 :            : _Py_COMP_DIAG_POP
     574                 :            :     }
     575                 :            : #endif
     576                 :            : 
     577                 :          0 : done:
     578                 :          0 :     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
     579                 :            : 
     580                 :          0 :     return res;
     581                 :            : }
     582                 :            : 
     583                 :            : 
     584                 :            : void
     585                 :         50 : _Py_ClearStandardStreamEncoding(void)
     586                 :            : {
     587                 :            :     /* Use the same allocator than Py_SetStandardStreamEncoding() */
     588                 :            :     PyMemAllocatorEx old_alloc;
     589                 :         50 :     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
     590                 :            : 
     591                 :            :     /* We won't need them anymore. */
     592         [ -  + ]:         50 :     if (_Py_StandardStreamEncoding) {
     593                 :          0 :         PyMem_RawFree(_Py_StandardStreamEncoding);
     594                 :          0 :         _Py_StandardStreamEncoding = NULL;
     595                 :            :     }
     596         [ -  + ]:         50 :     if (_Py_StandardStreamErrors) {
     597                 :          0 :         PyMem_RawFree(_Py_StandardStreamErrors);
     598                 :          0 :         _Py_StandardStreamErrors = NULL;
     599                 :            :     }
     600                 :            : 
     601                 :         50 :     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
     602                 :         50 : }
     603                 :            : 
     604                 :            : 
     605                 :            : /* --- Py_GetArgcArgv() ------------------------------------------- */
     606                 :            : 
     607                 :            : void
     608                 :         25 : _Py_ClearArgcArgv(void)
     609                 :            : {
     610                 :            :     PyMemAllocatorEx old_alloc;
     611                 :         25 :     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
     612                 :            : 
     613                 :         25 :     _PyWideStringList_Clear(&_PyRuntime.orig_argv);
     614                 :            : 
     615                 :         25 :     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
     616                 :         25 : }
     617                 :            : 
     618                 :            : 
     619                 :            : static int
     620                 :         29 : _Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv)
     621                 :            : {
     622                 :         29 :     const PyWideStringList argv_list = {.length = argc, .items = (wchar_t **)argv};
     623                 :            :     int res;
     624                 :            : 
     625                 :            :     PyMemAllocatorEx old_alloc;
     626                 :         29 :     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
     627                 :            : 
     628                 :            :     // XXX _PyRuntime.orig_argv only gets cleared by Py_Main(),
     629                 :            :     // so it it currently leaks for embedders.
     630                 :         29 :     res = _PyWideStringList_Copy(&_PyRuntime.orig_argv, &argv_list);
     631                 :            : 
     632                 :         29 :     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
     633                 :         29 :     return res;
     634                 :            : }
     635                 :            : 
     636                 :            : 
     637                 :            : // _PyConfig_Write() calls _Py_SetArgcArgv() with PyConfig.orig_argv.
     638                 :            : void
     639                 :          0 : Py_GetArgcArgv(int *argc, wchar_t ***argv)
     640                 :            : {
     641                 :          0 :     *argc = (int)_PyRuntime.orig_argv.length;
     642                 :          0 :     *argv = _PyRuntime.orig_argv.items;
     643                 :          0 : }
     644                 :            : 
     645                 :            : 
     646                 :            : /* --- PyConfig ---------------------------------------------- */
     647                 :            : 
     648                 :            : #define MAX_HASH_SEED 4294967295UL
     649                 :            : 
     650                 :            : 
     651                 :            : #ifndef NDEBUG
     652                 :            : static int
     653                 :            : config_check_consistency(const PyConfig *config)
     654                 :            : {
     655                 :            :     /* Check config consistency */
     656                 :            :     assert(config->isolated >= 0);
     657                 :            :     assert(config->use_environment >= 0);
     658                 :            :     assert(config->dev_mode >= 0);
     659                 :            :     assert(config->install_signal_handlers >= 0);
     660                 :            :     assert(config->use_hash_seed >= 0);
     661                 :            :     assert(config->hash_seed <= MAX_HASH_SEED);
     662                 :            :     assert(config->faulthandler >= 0);
     663                 :            :     assert(config->tracemalloc >= 0);
     664                 :            :     assert(config->import_time >= 0);
     665                 :            :     assert(config->code_debug_ranges >= 0);
     666                 :            :     assert(config->show_ref_count >= 0);
     667                 :            :     assert(config->dump_refs >= 0);
     668                 :            :     assert(config->malloc_stats >= 0);
     669                 :            :     assert(config->site_import >= 0);
     670                 :            :     assert(config->bytes_warning >= 0);
     671                 :            :     assert(config->warn_default_encoding >= 0);
     672                 :            :     assert(config->inspect >= 0);
     673                 :            :     assert(config->interactive >= 0);
     674                 :            :     assert(config->optimization_level >= 0);
     675                 :            :     assert(config->parser_debug >= 0);
     676                 :            :     assert(config->write_bytecode >= 0);
     677                 :            :     assert(config->verbose >= 0);
     678                 :            :     assert(config->quiet >= 0);
     679                 :            :     assert(config->user_site_directory >= 0);
     680                 :            :     assert(config->parse_argv >= 0);
     681                 :            :     assert(config->configure_c_stdio >= 0);
     682                 :            :     assert(config->buffered_stdio >= 0);
     683                 :            :     assert(_PyWideStringList_CheckConsistency(&config->orig_argv));
     684                 :            :     assert(_PyWideStringList_CheckConsistency(&config->argv));
     685                 :            :     /* sys.argv must be non-empty: empty argv is replaced with [''] */
     686                 :            :     assert(config->argv.length >= 1);
     687                 :            :     assert(_PyWideStringList_CheckConsistency(&config->xoptions));
     688                 :            :     assert(_PyWideStringList_CheckConsistency(&config->warnoptions));
     689                 :            :     assert(_PyWideStringList_CheckConsistency(&config->module_search_paths));
     690                 :            :     assert(config->module_search_paths_set >= 0);
     691                 :            :     assert(config->filesystem_encoding != NULL);
     692                 :            :     assert(config->filesystem_errors != NULL);
     693                 :            :     assert(config->stdio_encoding != NULL);
     694                 :            :     assert(config->stdio_errors != NULL);
     695                 :            : #ifdef MS_WINDOWS
     696                 :            :     assert(config->legacy_windows_stdio >= 0);
     697                 :            : #endif
     698                 :            :     /* -c and -m options are exclusive */
     699                 :            :     assert(!(config->run_command != NULL && config->run_module != NULL));
     700                 :            :     assert(config->check_hash_pycs_mode != NULL);
     701                 :            :     assert(config->_install_importlib >= 0);
     702                 :            :     assert(config->pathconfig_warnings >= 0);
     703                 :            :     assert(config->_is_python_build >= 0);
     704                 :            :     assert(config->safe_path >= 0);
     705                 :            :     assert(config->int_max_str_digits >= 0);
     706                 :            :     // config->use_frozen_modules is initialized later
     707                 :            :     // by _PyConfig_InitImportConfig().
     708                 :            :     return 1;
     709                 :            : }
     710                 :            : #endif
     711                 :            : 
     712                 :            : 
     713                 :            : /* Free memory allocated in config, but don't clear all attributes */
     714                 :            : void
     715                 :        141 : PyConfig_Clear(PyConfig *config)
     716                 :            : {
     717                 :            : #define CLEAR(ATTR) \
     718                 :            :     do { \
     719                 :            :         PyMem_RawFree(ATTR); \
     720                 :            :         ATTR = NULL; \
     721                 :            :     } while (0)
     722                 :            : 
     723                 :        141 :     CLEAR(config->pycache_prefix);
     724                 :        141 :     CLEAR(config->pythonpath_env);
     725                 :        141 :     CLEAR(config->home);
     726                 :        141 :     CLEAR(config->program_name);
     727                 :            : 
     728                 :        141 :     _PyWideStringList_Clear(&config->argv);
     729                 :        141 :     _PyWideStringList_Clear(&config->warnoptions);
     730                 :        141 :     _PyWideStringList_Clear(&config->xoptions);
     731                 :        141 :     _PyWideStringList_Clear(&config->module_search_paths);
     732                 :        141 :     config->module_search_paths_set = 0;
     733                 :        141 :     CLEAR(config->stdlib_dir);
     734                 :            : 
     735                 :        141 :     CLEAR(config->executable);
     736                 :        141 :     CLEAR(config->base_executable);
     737                 :        141 :     CLEAR(config->prefix);
     738                 :        141 :     CLEAR(config->base_prefix);
     739                 :        141 :     CLEAR(config->exec_prefix);
     740                 :        141 :     CLEAR(config->base_exec_prefix);
     741                 :        141 :     CLEAR(config->platlibdir);
     742                 :            : 
     743                 :        141 :     CLEAR(config->filesystem_encoding);
     744                 :        141 :     CLEAR(config->filesystem_errors);
     745                 :        141 :     CLEAR(config->stdio_encoding);
     746                 :        141 :     CLEAR(config->stdio_errors);
     747                 :        141 :     CLEAR(config->run_command);
     748                 :        141 :     CLEAR(config->run_module);
     749                 :        141 :     CLEAR(config->run_filename);
     750                 :        141 :     CLEAR(config->check_hash_pycs_mode);
     751                 :            : 
     752                 :        141 :     _PyWideStringList_Clear(&config->orig_argv);
     753                 :            : #undef CLEAR
     754                 :        141 : }
     755                 :            : 
     756                 :            : 
     757                 :            : void
     758                 :         87 : _PyConfig_InitCompatConfig(PyConfig *config)
     759                 :            : {
     760                 :         87 :     memset(config, 0, sizeof(*config));
     761                 :            : 
     762                 :         87 :     config->_config_init = (int)_PyConfig_INIT_COMPAT;
     763                 :         87 :     config->isolated = -1;
     764                 :         87 :     config->use_environment = -1;
     765                 :         87 :     config->dev_mode = -1;
     766                 :         87 :     config->install_signal_handlers = 1;
     767                 :         87 :     config->use_hash_seed = -1;
     768                 :         87 :     config->faulthandler = -1;
     769                 :         87 :     config->tracemalloc = -1;
     770                 :         87 :     config->perf_profiling = -1;
     771                 :         87 :     config->module_search_paths_set = 0;
     772                 :         87 :     config->parse_argv = 0;
     773                 :         87 :     config->site_import = -1;
     774                 :         87 :     config->bytes_warning = -1;
     775                 :         87 :     config->warn_default_encoding = 0;
     776                 :         87 :     config->inspect = -1;
     777                 :         87 :     config->interactive = -1;
     778                 :         87 :     config->optimization_level = -1;
     779                 :         87 :     config->parser_debug= -1;
     780                 :         87 :     config->write_bytecode = -1;
     781                 :         87 :     config->verbose = -1;
     782                 :         87 :     config->quiet = -1;
     783                 :         87 :     config->user_site_directory = -1;
     784                 :         87 :     config->configure_c_stdio = 0;
     785                 :         87 :     config->buffered_stdio = -1;
     786                 :         87 :     config->_install_importlib = 1;
     787                 :         87 :     config->check_hash_pycs_mode = NULL;
     788                 :         87 :     config->pathconfig_warnings = -1;
     789                 :         87 :     config->_init_main = 1;
     790                 :            : #ifdef MS_WINDOWS
     791                 :            :     config->legacy_windows_stdio = -1;
     792                 :            : #endif
     793                 :            : #ifdef Py_DEBUG
     794                 :            :     config->use_frozen_modules = 0;
     795                 :            : #else
     796                 :         87 :     config->use_frozen_modules = 1;
     797                 :            : #endif
     798                 :         87 :     config->safe_path = 0;
     799                 :         87 :     config->int_max_str_digits = -1;
     800                 :         87 :     config->_is_python_build = 0;
     801                 :         87 :     config->code_debug_ranges = 1;
     802                 :         87 : }
     803                 :            : 
     804                 :            : 
     805                 :            : static void
     806                 :         87 : config_init_defaults(PyConfig *config)
     807                 :            : {
     808                 :         87 :     _PyConfig_InitCompatConfig(config);
     809                 :            : 
     810                 :         87 :     config->isolated = 0;
     811                 :         87 :     config->use_environment = 1;
     812                 :         87 :     config->site_import = 1;
     813                 :         87 :     config->bytes_warning = 0;
     814                 :         87 :     config->inspect = 0;
     815                 :         87 :     config->interactive = 0;
     816                 :         87 :     config->optimization_level = 0;
     817                 :         87 :     config->parser_debug= 0;
     818                 :         87 :     config->write_bytecode = 1;
     819                 :         87 :     config->verbose = 0;
     820                 :         87 :     config->quiet = 0;
     821                 :         87 :     config->user_site_directory = 1;
     822                 :         87 :     config->buffered_stdio = 1;
     823                 :         87 :     config->pathconfig_warnings = 1;
     824                 :            : #ifdef MS_WINDOWS
     825                 :            :     config->legacy_windows_stdio = 0;
     826                 :            : #endif
     827                 :         87 : }
     828                 :            : 
     829                 :            : 
     830                 :            : void
     831                 :         62 : PyConfig_InitPythonConfig(PyConfig *config)
     832                 :            : {
     833                 :         62 :     config_init_defaults(config);
     834                 :            : 
     835                 :         62 :     config->_config_init = (int)_PyConfig_INIT_PYTHON;
     836                 :         62 :     config->configure_c_stdio = 1;
     837                 :         62 :     config->parse_argv = 1;
     838                 :         62 : }
     839                 :            : 
     840                 :            : 
     841                 :            : void
     842                 :         25 : PyConfig_InitIsolatedConfig(PyConfig *config)
     843                 :            : {
     844                 :         25 :     config_init_defaults(config);
     845                 :            : 
     846                 :         25 :     config->_config_init = (int)_PyConfig_INIT_ISOLATED;
     847                 :         25 :     config->isolated = 1;
     848                 :         25 :     config->use_environment = 0;
     849                 :         25 :     config->user_site_directory = 0;
     850                 :         25 :     config->dev_mode = 0;
     851                 :         25 :     config->install_signal_handlers = 0;
     852                 :         25 :     config->use_hash_seed = 0;
     853                 :         25 :     config->faulthandler = 0;
     854                 :         25 :     config->tracemalloc = 0;
     855                 :         25 :     config->perf_profiling = 0;
     856                 :         25 :     config->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;
     857                 :         25 :     config->safe_path = 1;
     858                 :         25 :     config->pathconfig_warnings = 0;
     859                 :            : #ifdef MS_WINDOWS
     860                 :            :     config->legacy_windows_stdio = 0;
     861                 :            : #endif
     862                 :         25 : }
     863                 :            : 
     864                 :            : 
     865                 :            : /* Copy str into *config_str (duplicate the string) */
     866                 :            : PyStatus
     867                 :       1809 : PyConfig_SetString(PyConfig *config, wchar_t **config_str, const wchar_t *str)
     868                 :            : {
     869                 :       1809 :     PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
     870         [ -  + ]:       1809 :     if (_PyStatus_EXCEPTION(status)) {
     871                 :          0 :         return status;
     872                 :            :     }
     873                 :            : 
     874                 :            :     wchar_t *str2;
     875         [ +  + ]:       1809 :     if (str != NULL) {
     876                 :        828 :         str2 = _PyMem_RawWcsdup(str);
     877         [ -  + ]:        828 :         if (str2 == NULL) {
     878                 :          0 :             return _PyStatus_NO_MEMORY();
     879                 :            :         }
     880                 :            :     }
     881                 :            :     else {
     882                 :        981 :         str2 = NULL;
     883                 :            :     }
     884                 :       1809 :     PyMem_RawFree(*config_str);
     885                 :       1809 :     *config_str = str2;
     886                 :       1809 :     return _PyStatus_OK();
     887                 :            : }
     888                 :            : 
     889                 :            : 
     890                 :            : static PyStatus
     891                 :          0 : config_set_bytes_string(PyConfig *config, wchar_t **config_str,
     892                 :            :                         const char *str, const char *decode_err_msg)
     893                 :            : {
     894                 :          0 :     PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
     895         [ #  # ]:          0 :     if (_PyStatus_EXCEPTION(status)) {
     896                 :          0 :         return status;
     897                 :            :     }
     898                 :            : 
     899                 :            :     wchar_t *str2;
     900         [ #  # ]:          0 :     if (str != NULL) {
     901                 :            :         size_t len;
     902                 :          0 :         str2 = Py_DecodeLocale(str, &len);
     903         [ #  # ]:          0 :         if (str2 == NULL) {
     904         [ #  # ]:          0 :             if (len == (size_t)-2) {
     905                 :          0 :                 return _PyStatus_ERR(decode_err_msg);
     906                 :            :             }
     907                 :            :             else {
     908                 :          0 :                 return  _PyStatus_NO_MEMORY();
     909                 :            :             }
     910                 :            :         }
     911                 :            :     }
     912                 :            :     else {
     913                 :          0 :         str2 = NULL;
     914                 :            :     }
     915                 :          0 :     PyMem_RawFree(*config_str);
     916                 :          0 :     *config_str = str2;
     917                 :          0 :     return _PyStatus_OK();
     918                 :            : }
     919                 :            : 
     920                 :            : 
     921                 :            : #define CONFIG_SET_BYTES_STR(config, config_str, str, NAME) \
     922                 :            :     config_set_bytes_string(config, config_str, str, "cannot decode " NAME)
     923                 :            : 
     924                 :            : 
     925                 :            : /* Decode str using Py_DecodeLocale() and set the result into *config_str.
     926                 :            :    Pre-initialize Python if needed to ensure that encodings are properly
     927                 :            :    configured. */
     928                 :            : PyStatus
     929                 :          0 : PyConfig_SetBytesString(PyConfig *config, wchar_t **config_str,
     930                 :            :                         const char *str)
     931                 :            : {
     932                 :          0 :     return CONFIG_SET_BYTES_STR(config, config_str, str, "string");
     933                 :            : }
     934                 :            : 
     935                 :            : 
     936                 :            : PyStatus
     937                 :         58 : _PyConfig_Copy(PyConfig *config, const PyConfig *config2)
     938                 :            : {
     939                 :            :     PyStatus status;
     940                 :            : 
     941                 :         58 :     PyConfig_Clear(config);
     942                 :            : 
     943                 :            : #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
     944                 :            : #define COPY_WSTR_ATTR(ATTR) \
     945                 :            :     do { \
     946                 :            :         status = PyConfig_SetString(config, &config->ATTR, config2->ATTR); \
     947                 :            :         if (_PyStatus_EXCEPTION(status)) { \
     948                 :            :             return status; \
     949                 :            :         } \
     950                 :            :     } while (0)
     951                 :            : #define COPY_WSTRLIST(LIST) \
     952                 :            :     do { \
     953                 :            :         if (_PyWideStringList_Copy(&config->LIST, &config2->LIST) < 0) { \
     954                 :            :             return _PyStatus_NO_MEMORY(); \
     955                 :            :         } \
     956                 :            :     } while (0)
     957                 :            : 
     958                 :         58 :     COPY_ATTR(_config_init);
     959                 :         58 :     COPY_ATTR(isolated);
     960                 :         58 :     COPY_ATTR(use_environment);
     961                 :         58 :     COPY_ATTR(dev_mode);
     962                 :         58 :     COPY_ATTR(install_signal_handlers);
     963                 :         58 :     COPY_ATTR(use_hash_seed);
     964                 :         58 :     COPY_ATTR(hash_seed);
     965                 :         58 :     COPY_ATTR(_install_importlib);
     966                 :         58 :     COPY_ATTR(faulthandler);
     967                 :         58 :     COPY_ATTR(tracemalloc);
     968                 :         58 :     COPY_ATTR(perf_profiling);
     969                 :         58 :     COPY_ATTR(import_time);
     970                 :         58 :     COPY_ATTR(code_debug_ranges);
     971                 :         58 :     COPY_ATTR(show_ref_count);
     972                 :         58 :     COPY_ATTR(dump_refs);
     973                 :         58 :     COPY_ATTR(dump_refs_file);
     974                 :         58 :     COPY_ATTR(malloc_stats);
     975                 :            : 
     976         [ -  + ]:         58 :     COPY_WSTR_ATTR(pycache_prefix);
     977         [ -  + ]:         58 :     COPY_WSTR_ATTR(pythonpath_env);
     978         [ -  + ]:         58 :     COPY_WSTR_ATTR(home);
     979         [ -  + ]:         58 :     COPY_WSTR_ATTR(program_name);
     980                 :            : 
     981                 :         58 :     COPY_ATTR(parse_argv);
     982         [ -  + ]:         58 :     COPY_WSTRLIST(argv);
     983         [ -  + ]:         58 :     COPY_WSTRLIST(warnoptions);
     984         [ -  + ]:         58 :     COPY_WSTRLIST(xoptions);
     985         [ -  + ]:         58 :     COPY_WSTRLIST(module_search_paths);
     986                 :         58 :     COPY_ATTR(module_search_paths_set);
     987         [ -  + ]:         58 :     COPY_WSTR_ATTR(stdlib_dir);
     988                 :            : 
     989         [ -  + ]:         58 :     COPY_WSTR_ATTR(executable);
     990         [ -  + ]:         58 :     COPY_WSTR_ATTR(base_executable);
     991         [ -  + ]:         58 :     COPY_WSTR_ATTR(prefix);
     992         [ -  + ]:         58 :     COPY_WSTR_ATTR(base_prefix);
     993         [ -  + ]:         58 :     COPY_WSTR_ATTR(exec_prefix);
     994         [ -  + ]:         58 :     COPY_WSTR_ATTR(base_exec_prefix);
     995         [ -  + ]:         58 :     COPY_WSTR_ATTR(platlibdir);
     996                 :            : 
     997                 :         58 :     COPY_ATTR(site_import);
     998                 :         58 :     COPY_ATTR(bytes_warning);
     999                 :         58 :     COPY_ATTR(warn_default_encoding);
    1000                 :         58 :     COPY_ATTR(inspect);
    1001                 :         58 :     COPY_ATTR(interactive);
    1002                 :         58 :     COPY_ATTR(optimization_level);
    1003                 :         58 :     COPY_ATTR(parser_debug);
    1004                 :         58 :     COPY_ATTR(write_bytecode);
    1005                 :         58 :     COPY_ATTR(verbose);
    1006                 :         58 :     COPY_ATTR(quiet);
    1007                 :         58 :     COPY_ATTR(user_site_directory);
    1008                 :         58 :     COPY_ATTR(configure_c_stdio);
    1009                 :         58 :     COPY_ATTR(buffered_stdio);
    1010         [ -  + ]:         58 :     COPY_WSTR_ATTR(filesystem_encoding);
    1011         [ -  + ]:         58 :     COPY_WSTR_ATTR(filesystem_errors);
    1012         [ -  + ]:         58 :     COPY_WSTR_ATTR(stdio_encoding);
    1013         [ -  + ]:         58 :     COPY_WSTR_ATTR(stdio_errors);
    1014                 :            : #ifdef MS_WINDOWS
    1015                 :            :     COPY_ATTR(legacy_windows_stdio);
    1016                 :            : #endif
    1017                 :         58 :     COPY_ATTR(skip_source_first_line);
    1018         [ -  + ]:         58 :     COPY_WSTR_ATTR(run_command);
    1019         [ -  + ]:         58 :     COPY_WSTR_ATTR(run_module);
    1020         [ -  + ]:         58 :     COPY_WSTR_ATTR(run_filename);
    1021         [ -  + ]:         58 :     COPY_WSTR_ATTR(check_hash_pycs_mode);
    1022                 :         58 :     COPY_ATTR(pathconfig_warnings);
    1023                 :         58 :     COPY_ATTR(_init_main);
    1024                 :         58 :     COPY_ATTR(use_frozen_modules);
    1025                 :         58 :     COPY_ATTR(safe_path);
    1026         [ -  + ]:         58 :     COPY_WSTRLIST(orig_argv);
    1027                 :         58 :     COPY_ATTR(_is_python_build);
    1028                 :         58 :     COPY_ATTR(int_max_str_digits);
    1029                 :            : 
    1030                 :            : #undef COPY_ATTR
    1031                 :            : #undef COPY_WSTR_ATTR
    1032                 :            : #undef COPY_WSTRLIST
    1033                 :         58 :     return _PyStatus_OK();
    1034                 :            : }
    1035                 :            : 
    1036                 :            : 
    1037                 :            : PyObject *
    1038                 :         25 : _PyConfig_AsDict(const PyConfig *config)
    1039                 :            : {
    1040                 :         25 :     PyObject *dict = PyDict_New();
    1041         [ -  + ]:         25 :     if (dict == NULL) {
    1042                 :          0 :         return NULL;
    1043                 :            :     }
    1044                 :            : 
    1045                 :            : #define SET_ITEM(KEY, EXPR) \
    1046                 :            :         do { \
    1047                 :            :             PyObject *obj = (EXPR); \
    1048                 :            :             if (obj == NULL) { \
    1049                 :            :                 goto fail; \
    1050                 :            :             } \
    1051                 :            :             int res = PyDict_SetItemString(dict, (KEY), obj); \
    1052                 :            :             Py_DECREF(obj); \
    1053                 :            :             if (res < 0) { \
    1054                 :            :                 goto fail; \
    1055                 :            :             } \
    1056                 :            :         } while (0)
    1057                 :            : #define SET_ITEM_INT(ATTR) \
    1058                 :            :     SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
    1059                 :            : #define SET_ITEM_UINT(ATTR) \
    1060                 :            :     SET_ITEM(#ATTR, PyLong_FromUnsignedLong(config->ATTR))
    1061                 :            : #define FROM_WSTRING(STR) \
    1062                 :            :     ((STR != NULL) ? \
    1063                 :            :         PyUnicode_FromWideChar(STR, -1) \
    1064                 :            :         : Py_NewRef(Py_None))
    1065                 :            : #define SET_ITEM_WSTR(ATTR) \
    1066                 :            :     SET_ITEM(#ATTR, FROM_WSTRING(config->ATTR))
    1067                 :            : #define SET_ITEM_WSTRLIST(LIST) \
    1068                 :            :     SET_ITEM(#LIST, _PyWideStringList_AsList(&config->LIST))
    1069                 :            : 
    1070   [ -  +  -  + ]:         25 :     SET_ITEM_INT(_config_init);
    1071   [ -  +  -  + ]:         25 :     SET_ITEM_INT(isolated);
    1072   [ -  +  -  + ]:         25 :     SET_ITEM_INT(use_environment);
    1073   [ -  +  -  + ]:         25 :     SET_ITEM_INT(dev_mode);
    1074   [ -  +  -  + ]:         25 :     SET_ITEM_INT(install_signal_handlers);
    1075   [ -  +  -  + ]:         25 :     SET_ITEM_INT(use_hash_seed);
    1076   [ -  +  -  + ]:         25 :     SET_ITEM_UINT(hash_seed);
    1077   [ -  +  -  + ]:         25 :     SET_ITEM_INT(faulthandler);
    1078   [ -  +  -  + ]:         25 :     SET_ITEM_INT(tracemalloc);
    1079   [ -  +  -  + ]:         25 :     SET_ITEM_INT(perf_profiling);
    1080   [ -  +  -  + ]:         25 :     SET_ITEM_INT(import_time);
    1081   [ -  +  -  + ]:         25 :     SET_ITEM_INT(code_debug_ranges);
    1082   [ -  +  -  + ]:         25 :     SET_ITEM_INT(show_ref_count);
    1083   [ -  +  -  + ]:         25 :     SET_ITEM_INT(dump_refs);
    1084   [ -  +  -  + ]:         25 :     SET_ITEM_INT(malloc_stats);
    1085   [ +  -  -  +  :         25 :     SET_ITEM_WSTR(filesystem_encoding);
                   -  + ]
    1086   [ +  -  -  +  :         25 :     SET_ITEM_WSTR(filesystem_errors);
                   -  + ]
    1087   [ -  +  -  +  :         25 :     SET_ITEM_WSTR(pycache_prefix);
                   -  + ]
    1088   [ -  +  -  +  :         25 :     SET_ITEM_WSTR(program_name);
                   -  + ]
    1089   [ -  +  -  + ]:         25 :     SET_ITEM_INT(parse_argv);
    1090   [ -  +  -  + ]:         25 :     SET_ITEM_WSTRLIST(argv);
    1091   [ -  +  -  + ]:         25 :     SET_ITEM_WSTRLIST(xoptions);
    1092   [ -  +  -  + ]:         25 :     SET_ITEM_WSTRLIST(warnoptions);
    1093   [ -  +  -  +  :         25 :     SET_ITEM_WSTR(pythonpath_env);
                   -  + ]
    1094   [ -  +  -  +  :         25 :     SET_ITEM_WSTR(home);
                   -  + ]
    1095   [ -  +  -  + ]:         25 :     SET_ITEM_INT(module_search_paths_set);
    1096   [ -  +  -  + ]:         25 :     SET_ITEM_WSTRLIST(module_search_paths);
    1097   [ -  +  -  +  :         25 :     SET_ITEM_WSTR(stdlib_dir);
                   -  + ]
    1098   [ -  +  -  +  :         25 :     SET_ITEM_WSTR(executable);
                   -  + ]
    1099   [ -  +  -  +  :         25 :     SET_ITEM_WSTR(base_executable);
                   -  + ]
    1100   [ -  +  -  +  :         25 :     SET_ITEM_WSTR(prefix);
                   -  + ]
    1101   [ -  +  -  +  :         25 :     SET_ITEM_WSTR(base_prefix);
                   -  + ]
    1102   [ -  +  -  +  :         25 :     SET_ITEM_WSTR(exec_prefix);
                   -  + ]
    1103   [ -  +  -  +  :         25 :     SET_ITEM_WSTR(base_exec_prefix);
                   -  + ]
    1104   [ -  +  -  +  :         25 :     SET_ITEM_WSTR(platlibdir);
                   -  + ]
    1105   [ -  +  -  + ]:         25 :     SET_ITEM_INT(site_import);
    1106   [ -  +  -  + ]:         25 :     SET_ITEM_INT(bytes_warning);
    1107   [ -  +  -  + ]:         25 :     SET_ITEM_INT(warn_default_encoding);
    1108   [ -  +  -  + ]:         25 :     SET_ITEM_INT(inspect);
    1109   [ -  +  -  + ]:         25 :     SET_ITEM_INT(interactive);
    1110   [ -  +  -  + ]:         25 :     SET_ITEM_INT(optimization_level);
    1111   [ -  +  -  + ]:         25 :     SET_ITEM_INT(parser_debug);
    1112   [ -  +  -  + ]:         25 :     SET_ITEM_INT(write_bytecode);
    1113   [ -  +  -  + ]:         25 :     SET_ITEM_INT(verbose);
    1114   [ -  +  -  + ]:         25 :     SET_ITEM_INT(quiet);
    1115   [ -  +  -  + ]:         25 :     SET_ITEM_INT(user_site_directory);
    1116   [ -  +  -  + ]:         25 :     SET_ITEM_INT(configure_c_stdio);
    1117   [ -  +  -  + ]:         25 :     SET_ITEM_INT(buffered_stdio);
    1118   [ +  -  -  +  :         25 :     SET_ITEM_WSTR(stdio_encoding);
                   -  + ]
    1119   [ +  -  -  +  :         25 :     SET_ITEM_WSTR(stdio_errors);
                   -  + ]
    1120                 :            : #ifdef MS_WINDOWS
    1121                 :            :     SET_ITEM_INT(legacy_windows_stdio);
    1122                 :            : #endif
    1123   [ -  +  -  + ]:         25 :     SET_ITEM_INT(skip_source_first_line);
    1124   [ +  +  -  +  :         25 :     SET_ITEM_WSTR(run_command);
                   -  + ]
    1125   [ +  +  -  +  :         25 :     SET_ITEM_WSTR(run_module);
                   -  + ]
    1126   [ +  +  -  +  :         25 :     SET_ITEM_WSTR(run_filename);
                   -  + ]
    1127   [ -  +  -  + ]:         25 :     SET_ITEM_INT(_install_importlib);
    1128   [ +  -  -  +  :         25 :     SET_ITEM_WSTR(check_hash_pycs_mode);
                   -  + ]
    1129   [ -  +  -  + ]:         25 :     SET_ITEM_INT(pathconfig_warnings);
    1130   [ -  +  -  + ]:         25 :     SET_ITEM_INT(_init_main);
    1131   [ -  +  -  + ]:         25 :     SET_ITEM_WSTRLIST(orig_argv);
    1132   [ -  +  -  + ]:         25 :     SET_ITEM_INT(use_frozen_modules);
    1133   [ -  +  -  + ]:         25 :     SET_ITEM_INT(safe_path);
    1134   [ -  +  -  + ]:         25 :     SET_ITEM_INT(_is_python_build);
    1135   [ -  +  -  + ]:         25 :     SET_ITEM_INT(int_max_str_digits);
    1136                 :            : 
    1137                 :         25 :     return dict;
    1138                 :            : 
    1139                 :          0 : fail:
    1140                 :          0 :     Py_DECREF(dict);
    1141                 :          0 :     return NULL;
    1142                 :            : 
    1143                 :            : #undef FROM_WSTRING
    1144                 :            : #undef SET_ITEM
    1145                 :            : #undef SET_ITEM_INT
    1146                 :            : #undef SET_ITEM_UINT
    1147                 :            : #undef SET_ITEM_WSTR
    1148                 :            : #undef SET_ITEM_WSTRLIST
    1149                 :            : }
    1150                 :            : 
    1151                 :            : 
    1152                 :            : static PyObject*
    1153                 :       1575 : config_dict_get(PyObject *dict, const char *name)
    1154                 :            : {
    1155                 :       1575 :     PyObject *item = _PyDict_GetItemStringWithError(dict, name);
    1156   [ -  +  -  - ]:       1575 :     if (item == NULL && !PyErr_Occurred()) {
    1157                 :          0 :         PyErr_Format(PyExc_ValueError, "missing config key: %s", name);
    1158                 :          0 :         return NULL;
    1159                 :            :     }
    1160                 :       1575 :     return item;
    1161                 :            : }
    1162                 :            : 
    1163                 :            : 
    1164                 :            : static void
    1165                 :          0 : config_dict_invalid_value(const char *name)
    1166                 :            : {
    1167                 :          0 :     PyErr_Format(PyExc_ValueError, "invalid config value: %s", name);
    1168                 :          0 : }
    1169                 :            : 
    1170                 :            : 
    1171                 :            : static void
    1172                 :          0 : config_dict_invalid_type(const char *name)
    1173                 :            : {
    1174                 :          0 :     PyErr_Format(PyExc_TypeError, "invalid config type: %s", name);
    1175                 :          0 : }
    1176                 :            : 
    1177                 :            : 
    1178                 :            : static int
    1179                 :        925 : config_dict_get_int(PyObject *dict, const char *name, int *result)
    1180                 :            : {
    1181                 :        925 :     PyObject *item = config_dict_get(dict, name);
    1182         [ -  + ]:        925 :     if (item == NULL) {
    1183                 :          0 :         return -1;
    1184                 :            :     }
    1185                 :        925 :     int value = _PyLong_AsInt(item);
    1186   [ -  +  -  - ]:        925 :     if (value == -1 && PyErr_Occurred()) {
    1187         [ #  # ]:          0 :         if (PyErr_ExceptionMatches(PyExc_TypeError)) {
    1188                 :          0 :             config_dict_invalid_type(name);
    1189                 :            :         }
    1190         [ #  # ]:          0 :         else if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
    1191                 :          0 :             config_dict_invalid_value(name);
    1192                 :            :         }
    1193                 :          0 :         return -1;
    1194                 :            :     }
    1195                 :        925 :     *result = value;
    1196                 :        925 :     return 0;
    1197                 :            : }
    1198                 :            : 
    1199                 :            : 
    1200                 :            : static int
    1201                 :         25 : config_dict_get_ulong(PyObject *dict, const char *name, unsigned long *result)
    1202                 :            : {
    1203                 :         25 :     PyObject *item = config_dict_get(dict, name);
    1204         [ -  + ]:         25 :     if (item == NULL) {
    1205                 :          0 :         return -1;
    1206                 :            :     }
    1207                 :         25 :     unsigned long value = PyLong_AsUnsignedLong(item);
    1208   [ -  +  -  - ]:         25 :     if (value == (unsigned long)-1 && PyErr_Occurred()) {
    1209         [ #  # ]:          0 :         if (PyErr_ExceptionMatches(PyExc_TypeError)) {
    1210                 :          0 :             config_dict_invalid_type(name);
    1211                 :            :         }
    1212         [ #  # ]:          0 :         else if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
    1213                 :          0 :             config_dict_invalid_value(name);
    1214                 :            :         }
    1215                 :          0 :         return -1;
    1216                 :            :     }
    1217                 :         25 :     *result = value;
    1218                 :         25 :     return 0;
    1219                 :            : }
    1220                 :            : 
    1221                 :            : 
    1222                 :            : static int
    1223                 :        500 : config_dict_get_wstr(PyObject *dict, const char *name, PyConfig *config,
    1224                 :            :                      wchar_t **result)
    1225                 :            : {
    1226                 :        500 :     PyObject *item = config_dict_get(dict, name);
    1227         [ -  + ]:        500 :     if (item == NULL) {
    1228                 :          0 :         return -1;
    1229                 :            :     }
    1230                 :            :     PyStatus status;
    1231         [ +  + ]:        500 :     if (item == Py_None) {
    1232                 :        125 :         status = PyConfig_SetString(config, result, NULL);
    1233                 :            :     }
    1234         [ -  + ]:        375 :     else if (!PyUnicode_Check(item)) {
    1235                 :          0 :         config_dict_invalid_type(name);
    1236                 :          0 :         return -1;
    1237                 :            :     }
    1238                 :            :     else {
    1239                 :        375 :         wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);
    1240         [ -  + ]:        375 :         if (wstr == NULL) {
    1241                 :          0 :             return -1;
    1242                 :            :         }
    1243                 :        375 :         status = PyConfig_SetString(config, result, wstr);
    1244                 :        375 :         PyMem_Free(wstr);
    1245                 :            :     }
    1246         [ -  + ]:        500 :     if (_PyStatus_EXCEPTION(status)) {
    1247                 :          0 :         PyErr_NoMemory();
    1248                 :          0 :         return -1;
    1249                 :            :     }
    1250                 :        500 :     return 0;
    1251                 :            : }
    1252                 :            : 
    1253                 :            : 
    1254                 :            : static int
    1255                 :        125 : config_dict_get_wstrlist(PyObject *dict, const char *name, PyConfig *config,
    1256                 :            :                          PyWideStringList *result)
    1257                 :            : {
    1258                 :        125 :     PyObject *list = config_dict_get(dict, name);
    1259         [ -  + ]:        125 :     if (list == NULL) {
    1260                 :          0 :         return -1;
    1261                 :            :     }
    1262                 :            : 
    1263         [ -  + ]:        125 :     if (!PyList_CheckExact(list)) {
    1264                 :          0 :         config_dict_invalid_type(name);
    1265                 :          0 :         return -1;
    1266                 :            :     }
    1267                 :            : 
    1268                 :        125 :     PyWideStringList wstrlist = _PyWideStringList_INIT;
    1269         [ +  + ]:        456 :     for (Py_ssize_t i=0; i < PyList_GET_SIZE(list); i++) {
    1270                 :        331 :         PyObject *item = PyList_GET_ITEM(list, i);
    1271                 :            : 
    1272         [ -  + ]:        331 :         if (item == Py_None) {
    1273                 :          0 :             config_dict_invalid_value(name);
    1274                 :          0 :             goto error;
    1275                 :            :         }
    1276         [ -  + ]:        331 :         else if (!PyUnicode_Check(item)) {
    1277                 :          0 :             config_dict_invalid_type(name);
    1278                 :          0 :             goto error;
    1279                 :            :         }
    1280                 :        331 :         wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);
    1281         [ -  + ]:        331 :         if (wstr == NULL) {
    1282                 :          0 :             goto error;
    1283                 :            :         }
    1284                 :        331 :         PyStatus status = PyWideStringList_Append(&wstrlist, wstr);
    1285                 :        331 :         PyMem_Free(wstr);
    1286         [ -  + ]:        331 :         if (_PyStatus_EXCEPTION(status)) {
    1287                 :          0 :             PyErr_NoMemory();
    1288                 :          0 :             goto error;
    1289                 :            :         }
    1290                 :            :     }
    1291                 :            : 
    1292         [ -  + ]:        125 :     if (_PyWideStringList_Copy(result, &wstrlist) < 0) {
    1293                 :          0 :         PyErr_NoMemory();
    1294                 :          0 :         goto error;
    1295                 :            :     }
    1296                 :        125 :     _PyWideStringList_Clear(&wstrlist);
    1297                 :        125 :     return 0;
    1298                 :            : 
    1299                 :          0 : error:
    1300                 :          0 :     _PyWideStringList_Clear(&wstrlist);
    1301                 :          0 :     return -1;
    1302                 :            : }
    1303                 :            : 
    1304                 :            : 
    1305                 :            : int
    1306                 :         25 : _PyConfig_FromDict(PyConfig *config, PyObject *dict)
    1307                 :            : {
    1308         [ -  + ]:         25 :     if (!PyDict_Check(dict)) {
    1309                 :          0 :         PyErr_SetString(PyExc_TypeError, "dict expected");
    1310                 :          0 :         return -1;
    1311                 :            :     }
    1312                 :            : 
    1313                 :            : #define CHECK_VALUE(NAME, TEST) \
    1314                 :            :     if (!(TEST)) { \
    1315                 :            :         config_dict_invalid_value(NAME); \
    1316                 :            :         return -1; \
    1317                 :            :     }
    1318                 :            : #define GET_UINT(KEY) \
    1319                 :            :     do { \
    1320                 :            :         if (config_dict_get_int(dict, #KEY, &config->KEY) < 0) { \
    1321                 :            :             return -1; \
    1322                 :            :         } \
    1323                 :            :         CHECK_VALUE(#KEY, config->KEY >= 0); \
    1324                 :            :     } while (0)
    1325                 :            : #define GET_INT(KEY) \
    1326                 :            :     do { \
    1327                 :            :         if (config_dict_get_int(dict, #KEY, &config->KEY) < 0) { \
    1328                 :            :             return -1; \
    1329                 :            :         } \
    1330                 :            :     } while (0)
    1331                 :            : #define GET_WSTR(KEY) \
    1332                 :            :     do { \
    1333                 :            :         if (config_dict_get_wstr(dict, #KEY, config, &config->KEY) < 0) { \
    1334                 :            :             return -1; \
    1335                 :            :         } \
    1336                 :            :         CHECK_VALUE(#KEY, config->KEY != NULL); \
    1337                 :            :     } while (0)
    1338                 :            : #define GET_WSTR_OPT(KEY) \
    1339                 :            :     do { \
    1340                 :            :         if (config_dict_get_wstr(dict, #KEY, config, &config->KEY) < 0) { \
    1341                 :            :             return -1; \
    1342                 :            :         } \
    1343                 :            :     } while (0)
    1344                 :            : #define GET_WSTRLIST(KEY) \
    1345                 :            :     do { \
    1346                 :            :         if (config_dict_get_wstrlist(dict, #KEY, config, &config->KEY) < 0) { \
    1347                 :            :             return -1; \
    1348                 :            :         } \
    1349                 :            :     } while (0)
    1350                 :            : 
    1351   [ -  +  -  + ]:         25 :     GET_UINT(_config_init);
    1352   [ +  -  +  +  :         25 :     CHECK_VALUE("_config_init",
                   -  + ]
    1353                 :            :                 config->_config_init == _PyConfig_INIT_COMPAT
    1354                 :            :                 || config->_config_init == _PyConfig_INIT_PYTHON
    1355                 :            :                 || config->_config_init == _PyConfig_INIT_ISOLATED);
    1356   [ -  +  -  + ]:         25 :     GET_UINT(isolated);
    1357   [ -  +  -  + ]:         25 :     GET_UINT(use_environment);
    1358   [ -  +  -  + ]:         25 :     GET_UINT(dev_mode);
    1359   [ -  +  -  + ]:         25 :     GET_UINT(install_signal_handlers);
    1360   [ -  +  -  + ]:         25 :     GET_UINT(use_hash_seed);
    1361         [ -  + ]:         25 :     if (config_dict_get_ulong(dict, "hash_seed", &config->hash_seed) < 0) {
    1362                 :          0 :         return -1;
    1363                 :            :     }
    1364         [ -  + ]:         25 :     CHECK_VALUE("hash_seed", config->hash_seed <= MAX_HASH_SEED);
    1365   [ -  +  -  + ]:         25 :     GET_UINT(faulthandler);
    1366   [ -  +  -  + ]:         25 :     GET_UINT(tracemalloc);
    1367   [ -  +  -  + ]:         25 :     GET_UINT(perf_profiling);
    1368   [ -  +  -  + ]:         25 :     GET_UINT(import_time);
    1369   [ -  +  -  + ]:         25 :     GET_UINT(code_debug_ranges);
    1370   [ -  +  -  + ]:         25 :     GET_UINT(show_ref_count);
    1371   [ -  +  -  + ]:         25 :     GET_UINT(dump_refs);
    1372   [ -  +  -  + ]:         25 :     GET_UINT(malloc_stats);
    1373   [ -  +  -  + ]:         25 :     GET_WSTR(filesystem_encoding);
    1374   [ -  +  -  + ]:         25 :     GET_WSTR(filesystem_errors);
    1375         [ -  + ]:         25 :     GET_WSTR_OPT(pycache_prefix);
    1376   [ -  +  -  + ]:         25 :     GET_UINT(parse_argv);
    1377         [ -  + ]:         25 :     GET_WSTRLIST(orig_argv);
    1378         [ -  + ]:         25 :     GET_WSTRLIST(argv);
    1379         [ -  + ]:         25 :     GET_WSTRLIST(xoptions);
    1380         [ -  + ]:         25 :     GET_WSTRLIST(warnoptions);
    1381   [ -  +  -  + ]:         25 :     GET_UINT(site_import);
    1382   [ -  +  -  + ]:         25 :     GET_UINT(bytes_warning);
    1383   [ -  +  -  + ]:         25 :     GET_UINT(warn_default_encoding);
    1384   [ -  +  -  + ]:         25 :     GET_UINT(inspect);
    1385   [ -  +  -  + ]:         25 :     GET_UINT(interactive);
    1386   [ -  +  -  + ]:         25 :     GET_UINT(optimization_level);
    1387   [ -  +  -  + ]:         25 :     GET_UINT(parser_debug);
    1388   [ -  +  -  + ]:         25 :     GET_UINT(write_bytecode);
    1389   [ -  +  -  + ]:         25 :     GET_UINT(verbose);
    1390   [ -  +  -  + ]:         25 :     GET_UINT(quiet);
    1391   [ -  +  -  + ]:         25 :     GET_UINT(user_site_directory);
    1392   [ -  +  -  + ]:         25 :     GET_UINT(configure_c_stdio);
    1393   [ -  +  -  + ]:         25 :     GET_UINT(buffered_stdio);
    1394   [ -  +  -  + ]:         25 :     GET_WSTR(stdio_encoding);
    1395   [ -  +  -  + ]:         25 :     GET_WSTR(stdio_errors);
    1396                 :            : #ifdef MS_WINDOWS
    1397                 :            :     GET_UINT(legacy_windows_stdio);
    1398                 :            : #endif
    1399   [ -  +  -  + ]:         25 :     GET_WSTR(check_hash_pycs_mode);
    1400                 :            : 
    1401   [ -  +  -  + ]:         25 :     GET_UINT(pathconfig_warnings);
    1402   [ -  +  -  + ]:         25 :     GET_WSTR(program_name);
    1403         [ -  + ]:         25 :     GET_WSTR_OPT(pythonpath_env);
    1404         [ -  + ]:         25 :     GET_WSTR_OPT(home);
    1405   [ -  +  -  + ]:         25 :     GET_WSTR(platlibdir);
    1406                 :            : 
    1407                 :            :     // Path configuration output
    1408   [ -  +  -  + ]:         25 :     GET_UINT(module_search_paths_set);
    1409         [ -  + ]:         25 :     GET_WSTRLIST(module_search_paths);
    1410         [ -  + ]:         25 :     GET_WSTR_OPT(stdlib_dir);
    1411         [ -  + ]:         25 :     GET_WSTR_OPT(executable);
    1412         [ -  + ]:         25 :     GET_WSTR_OPT(base_executable);
    1413         [ -  + ]:         25 :     GET_WSTR_OPT(prefix);
    1414         [ -  + ]:         25 :     GET_WSTR_OPT(base_prefix);
    1415         [ -  + ]:         25 :     GET_WSTR_OPT(exec_prefix);
    1416         [ -  + ]:         25 :     GET_WSTR_OPT(base_exec_prefix);
    1417                 :            : 
    1418   [ -  +  -  + ]:         25 :     GET_UINT(skip_source_first_line);
    1419         [ -  + ]:         25 :     GET_WSTR_OPT(run_command);
    1420         [ -  + ]:         25 :     GET_WSTR_OPT(run_module);
    1421         [ -  + ]:         25 :     GET_WSTR_OPT(run_filename);
    1422                 :            : 
    1423   [ -  +  -  + ]:         25 :     GET_UINT(_install_importlib);
    1424   [ -  +  -  + ]:         25 :     GET_UINT(_init_main);
    1425   [ -  +  -  + ]:         25 :     GET_UINT(use_frozen_modules);
    1426   [ -  +  -  + ]:         25 :     GET_UINT(safe_path);
    1427   [ -  +  -  + ]:         25 :     GET_UINT(_is_python_build);
    1428         [ -  + ]:         25 :     GET_INT(int_max_str_digits);
    1429                 :            : 
    1430                 :            : #undef CHECK_VALUE
    1431                 :            : #undef GET_UINT
    1432                 :            : #undef GET_INT
    1433                 :            : #undef GET_WSTR
    1434                 :            : #undef GET_WSTR_OPT
    1435                 :         25 :     return 0;
    1436                 :            : }
    1437                 :            : 
    1438                 :            : 
    1439                 :            : static const char*
    1440                 :        149 : config_get_env(const PyConfig *config, const char *name)
    1441                 :            : {
    1442                 :        149 :     return _Py_GetEnv(config->use_environment, name);
    1443                 :            : }
    1444                 :            : 
    1445                 :            : 
    1446                 :            : /* Get a copy of the environment variable as wchar_t*.
    1447                 :            :    Return 0 on success, but *dest can be NULL.
    1448                 :            :    Return -1 on memory allocation failure. Return -2 on decoding error. */
    1449                 :            : static PyStatus
    1450                 :         54 : config_get_env_dup(PyConfig *config,
    1451                 :            :                    wchar_t **dest,
    1452                 :            :                    wchar_t *wname, char *name,
    1453                 :            :                    const char *decode_err_msg)
    1454                 :            : {
    1455                 :            :     assert(*dest == NULL);
    1456                 :            :     assert(config->use_environment >= 0);
    1457                 :            : 
    1458         [ +  + ]:         54 :     if (!config->use_environment) {
    1459                 :         49 :         *dest = NULL;
    1460                 :         49 :         return _PyStatus_OK();
    1461                 :            :     }
    1462                 :            : 
    1463                 :            : #ifdef MS_WINDOWS
    1464                 :            :     const wchar_t *var = _wgetenv(wname);
    1465                 :            :     if (!var || var[0] == '\0') {
    1466                 :            :         *dest = NULL;
    1467                 :            :         return _PyStatus_OK();
    1468                 :            :     }
    1469                 :            : 
    1470                 :            :     return PyConfig_SetString(config, dest, var);
    1471                 :            : #else
    1472                 :          5 :     const char *var = getenv(name);
    1473   [ -  +  -  - ]:          5 :     if (!var || var[0] == '\0') {
    1474                 :          5 :         *dest = NULL;
    1475                 :          5 :         return _PyStatus_OK();
    1476                 :            :     }
    1477                 :            : 
    1478                 :          0 :     return config_set_bytes_string(config, dest, var, decode_err_msg);
    1479                 :            : #endif
    1480                 :            : }
    1481                 :            : 
    1482                 :            : 
    1483                 :            : #define CONFIG_GET_ENV_DUP(CONFIG, DEST, WNAME, NAME) \
    1484                 :            :     config_get_env_dup(CONFIG, DEST, WNAME, NAME, "cannot decode " NAME)
    1485                 :            : 
    1486                 :            : 
    1487                 :            : static void
    1488                 :         50 : config_get_global_vars(PyConfig *config)
    1489                 :            : {
    1490                 :            : _Py_COMP_DIAG_PUSH
    1491                 :            : _Py_COMP_DIAG_IGNORE_DEPR_DECLS
    1492         [ +  - ]:         50 :     if (config->_config_init != _PyConfig_INIT_COMPAT) {
    1493                 :            :         /* Python and Isolated configuration ignore global variables */
    1494                 :         50 :         return;
    1495                 :            :     }
    1496                 :            : 
    1497                 :            : #define COPY_FLAG(ATTR, VALUE) \
    1498                 :            :         if (config->ATTR == -1) { \
    1499                 :            :             config->ATTR = VALUE; \
    1500                 :            :         }
    1501                 :            : #define COPY_NOT_FLAG(ATTR, VALUE) \
    1502                 :            :         if (config->ATTR == -1) { \
    1503                 :            :             config->ATTR = !(VALUE); \
    1504                 :            :         }
    1505                 :            : 
    1506         [ #  # ]:          0 :     COPY_FLAG(isolated, Py_IsolatedFlag);
    1507         [ #  # ]:          0 :     COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
    1508         [ #  # ]:          0 :     COPY_FLAG(bytes_warning, Py_BytesWarningFlag);
    1509         [ #  # ]:          0 :     COPY_FLAG(inspect, Py_InspectFlag);
    1510         [ #  # ]:          0 :     COPY_FLAG(interactive, Py_InteractiveFlag);
    1511         [ #  # ]:          0 :     COPY_FLAG(optimization_level, Py_OptimizeFlag);
    1512         [ #  # ]:          0 :     COPY_FLAG(parser_debug, Py_DebugFlag);
    1513         [ #  # ]:          0 :     COPY_FLAG(verbose, Py_VerboseFlag);
    1514         [ #  # ]:          0 :     COPY_FLAG(quiet, Py_QuietFlag);
    1515                 :            : #ifdef MS_WINDOWS
    1516                 :            :     COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);
    1517                 :            : #endif
    1518         [ #  # ]:          0 :     COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag);
    1519                 :            : 
    1520         [ #  # ]:          0 :     COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);
    1521         [ #  # ]:          0 :     COPY_NOT_FLAG(site_import, Py_NoSiteFlag);
    1522         [ #  # ]:          0 :     COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);
    1523         [ #  # ]:          0 :     COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);
    1524                 :            : 
    1525                 :            : #undef COPY_FLAG
    1526                 :            : #undef COPY_NOT_FLAG
    1527                 :            : _Py_COMP_DIAG_POP
    1528                 :            : }
    1529                 :            : 
    1530                 :            : 
    1531                 :            : /* Set Py_xxx global configuration variables from 'config' configuration. */
    1532                 :            : static void
    1533                 :         29 : config_set_global_vars(const PyConfig *config)
    1534                 :            : {
    1535                 :            : _Py_COMP_DIAG_PUSH
    1536                 :            : _Py_COMP_DIAG_IGNORE_DEPR_DECLS
    1537                 :            : #define COPY_FLAG(ATTR, VAR) \
    1538                 :            :         if (config->ATTR != -1) { \
    1539                 :            :             VAR = config->ATTR; \
    1540                 :            :         }
    1541                 :            : #define COPY_NOT_FLAG(ATTR, VAR) \
    1542                 :            :         if (config->ATTR != -1) { \
    1543                 :            :             VAR = !config->ATTR; \
    1544                 :            :         }
    1545                 :            : 
    1546         [ +  - ]:         29 :     COPY_FLAG(isolated, Py_IsolatedFlag);
    1547         [ +  - ]:         29 :     COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
    1548         [ +  - ]:         29 :     COPY_FLAG(bytes_warning, Py_BytesWarningFlag);
    1549         [ +  - ]:         29 :     COPY_FLAG(inspect, Py_InspectFlag);
    1550         [ +  - ]:         29 :     COPY_FLAG(interactive, Py_InteractiveFlag);
    1551         [ +  - ]:         29 :     COPY_FLAG(optimization_level, Py_OptimizeFlag);
    1552         [ +  - ]:         29 :     COPY_FLAG(parser_debug, Py_DebugFlag);
    1553         [ +  - ]:         29 :     COPY_FLAG(verbose, Py_VerboseFlag);
    1554         [ +  - ]:         29 :     COPY_FLAG(quiet, Py_QuietFlag);
    1555                 :            : #ifdef MS_WINDOWS
    1556                 :            :     COPY_FLAG(legacy_windows_stdio, Py_LegacyWindowsStdioFlag);
    1557                 :            : #endif
    1558         [ +  - ]:         29 :     COPY_NOT_FLAG(pathconfig_warnings, Py_FrozenFlag);
    1559                 :            : 
    1560         [ +  - ]:         29 :     COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag);
    1561         [ +  - ]:         29 :     COPY_NOT_FLAG(site_import, Py_NoSiteFlag);
    1562         [ +  - ]:         29 :     COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag);
    1563         [ +  - ]:         29 :     COPY_NOT_FLAG(user_site_directory, Py_NoUserSiteDirectory);
    1564                 :            : 
    1565                 :            :     /* Random or non-zero hash seed */
    1566         [ -  + ]:         29 :     Py_HashRandomizationFlag = (config->use_hash_seed == 0 ||
    1567         [ #  # ]:          0 :                                 config->hash_seed != 0);
    1568                 :            : 
    1569                 :            : #undef COPY_FLAG
    1570                 :            : #undef COPY_NOT_FLAG
    1571                 :            : _Py_COMP_DIAG_POP
    1572                 :         29 : }
    1573                 :            : 
    1574                 :            : 
    1575                 :            : static const wchar_t*
    1576                 :        287 : config_get_xoption(const PyConfig *config, wchar_t *name)
    1577                 :            : {
    1578                 :        287 :     return _Py_get_xoption(&config->xoptions, name);
    1579                 :            : }
    1580                 :            : 
    1581                 :            : static const wchar_t*
    1582                 :         71 : config_get_xoption_value(const PyConfig *config, wchar_t *name)
    1583                 :            : {
    1584                 :         71 :     const wchar_t *xoption = config_get_xoption(config, name);
    1585         [ +  - ]:         71 :     if (xoption == NULL) {
    1586                 :         71 :         return NULL;
    1587                 :            :     }
    1588                 :          0 :     const wchar_t *sep = wcschr(xoption, L'=');
    1589         [ #  # ]:          0 :     return sep ? sep + 1 : L"";
    1590                 :            : }
    1591                 :            : 
    1592                 :            : 
    1593                 :            : static PyStatus
    1594                 :          1 : config_init_hash_seed(PyConfig *config)
    1595                 :            : {
    1596                 :            :     static_assert(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc),
    1597                 :            :                   "_Py_HashSecret_t has wrong size");
    1598                 :            : 
    1599                 :          1 :     const char *seed_text = config_get_env(config, "PYTHONHASHSEED");
    1600                 :            : 
    1601                 :            :     /* Convert a text seed to a numeric one */
    1602   [ -  +  -  - ]:          1 :     if (seed_text && strcmp(seed_text, "random") != 0) {
    1603                 :          0 :         const char *endptr = seed_text;
    1604                 :            :         unsigned long seed;
    1605                 :          0 :         errno = 0;
    1606                 :          0 :         seed = strtoul(seed_text, (char **)&endptr, 10);
    1607         [ #  # ]:          0 :         if (*endptr != '\0'
    1608         [ #  # ]:          0 :             || seed > MAX_HASH_SEED
    1609   [ #  #  #  # ]:          0 :             || (errno == ERANGE && seed == ULONG_MAX))
    1610                 :            :         {
    1611                 :          0 :             return _PyStatus_ERR("PYTHONHASHSEED must be \"random\" "
    1612                 :            :                                 "or an integer in range [0; 4294967295]");
    1613                 :            :         }
    1614                 :            :         /* Use a specific hash */
    1615                 :          0 :         config->use_hash_seed = 1;
    1616                 :          0 :         config->hash_seed = seed;
    1617                 :            :     }
    1618                 :            :     else {
    1619                 :            :         /* Use a random hash */
    1620                 :          1 :         config->use_hash_seed = 0;
    1621                 :          1 :         config->hash_seed = 0;
    1622                 :            :     }
    1623                 :          1 :     return _PyStatus_OK();
    1624                 :            : }
    1625                 :            : 
    1626                 :            : 
    1627                 :            : static int
    1628                 :          0 : config_wstr_to_int(const wchar_t *wstr, int *result)
    1629                 :            : {
    1630                 :          0 :     const wchar_t *endptr = wstr;
    1631                 :          0 :     errno = 0;
    1632                 :          0 :     long value = wcstol(wstr, (wchar_t **)&endptr, 10);
    1633   [ #  #  #  # ]:          0 :     if (*endptr != '\0' || errno == ERANGE) {
    1634                 :          0 :         return -1;
    1635                 :            :     }
    1636   [ #  #  #  # ]:          0 :     if (value < INT_MIN || value > INT_MAX) {
    1637                 :          0 :         return -1;
    1638                 :            :     }
    1639                 :            : 
    1640                 :          0 :     *result = (int)value;
    1641                 :          0 :     return 0;
    1642                 :            : }
    1643                 :            : 
    1644                 :            : 
    1645                 :            : static PyStatus
    1646                 :          1 : config_read_env_vars(PyConfig *config)
    1647                 :            : {
    1648                 :            :     PyStatus status;
    1649                 :          1 :     int use_env = config->use_environment;
    1650                 :            : 
    1651                 :            :     /* Get environment variables */
    1652                 :          1 :     _Py_get_env_flag(use_env, &config->parser_debug, "PYTHONDEBUG");
    1653                 :          1 :     _Py_get_env_flag(use_env, &config->verbose, "PYTHONVERBOSE");
    1654                 :          1 :     _Py_get_env_flag(use_env, &config->optimization_level, "PYTHONOPTIMIZE");
    1655                 :          1 :     _Py_get_env_flag(use_env, &config->inspect, "PYTHONINSPECT");
    1656                 :            : 
    1657                 :          1 :     int dont_write_bytecode = 0;
    1658                 :          1 :     _Py_get_env_flag(use_env, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE");
    1659         [ -  + ]:          1 :     if (dont_write_bytecode) {
    1660                 :          0 :         config->write_bytecode = 0;
    1661                 :            :     }
    1662                 :            : 
    1663                 :          1 :     int no_user_site_directory = 0;
    1664                 :          1 :     _Py_get_env_flag(use_env, &no_user_site_directory, "PYTHONNOUSERSITE");
    1665         [ -  + ]:          1 :     if (no_user_site_directory) {
    1666                 :          0 :         config->user_site_directory = 0;
    1667                 :            :     }
    1668                 :            : 
    1669                 :          1 :     int unbuffered_stdio = 0;
    1670                 :          1 :     _Py_get_env_flag(use_env, &unbuffered_stdio, "PYTHONUNBUFFERED");
    1671         [ -  + ]:          1 :     if (unbuffered_stdio) {
    1672                 :          0 :         config->buffered_stdio = 0;
    1673                 :            :     }
    1674                 :            : 
    1675                 :            : #ifdef MS_WINDOWS
    1676                 :            :     _Py_get_env_flag(use_env, &config->legacy_windows_stdio,
    1677                 :            :                      "PYTHONLEGACYWINDOWSSTDIO");
    1678                 :            : #endif
    1679                 :            : 
    1680         [ -  + ]:          1 :     if (config_get_env(config, "PYTHONDUMPREFS")) {
    1681                 :          0 :         config->dump_refs = 1;
    1682                 :            :     }
    1683         [ -  + ]:          1 :     if (config_get_env(config, "PYTHONMALLOCSTATS")) {
    1684                 :          0 :         config->malloc_stats = 1;
    1685                 :            :     }
    1686                 :            : 
    1687         [ +  - ]:          1 :     if (config->dump_refs_file == NULL) {
    1688                 :          1 :         status = CONFIG_GET_ENV_DUP(config, &config->dump_refs_file,
    1689                 :            :                                     L"PYTHONDUMPREFSFILE", "PYTHONDUMPREFSFILE");
    1690         [ -  + ]:          1 :         if (_PyStatus_EXCEPTION(status)) {
    1691                 :          0 :             return status;
    1692                 :            :         }
    1693                 :            :     }
    1694                 :            : 
    1695         [ +  - ]:          1 :     if (config->pythonpath_env == NULL) {
    1696                 :          1 :         status = CONFIG_GET_ENV_DUP(config, &config->pythonpath_env,
    1697                 :            :                                     L"PYTHONPATH", "PYTHONPATH");
    1698         [ -  + ]:          1 :         if (_PyStatus_EXCEPTION(status)) {
    1699                 :          0 :             return status;
    1700                 :            :         }
    1701                 :            :     }
    1702                 :            : 
    1703         [ +  - ]:          1 :     if(config->platlibdir == NULL) {
    1704                 :          1 :         status = CONFIG_GET_ENV_DUP(config, &config->platlibdir,
    1705                 :            :                                     L"PYTHONPLATLIBDIR", "PYTHONPLATLIBDIR");
    1706         [ -  + ]:          1 :         if (_PyStatus_EXCEPTION(status)) {
    1707                 :          0 :             return status;
    1708                 :            :         }
    1709                 :            :     }
    1710                 :            : 
    1711         [ +  - ]:          1 :     if (config->use_hash_seed < 0) {
    1712                 :          1 :         status = config_init_hash_seed(config);
    1713         [ -  + ]:          1 :         if (_PyStatus_EXCEPTION(status)) {
    1714                 :          0 :             return status;
    1715                 :            :         }
    1716                 :            :     }
    1717                 :            : 
    1718         [ -  + ]:          1 :     if (config_get_env(config, "PYTHONSAFEPATH")) {
    1719                 :          0 :         config->safe_path = 1;
    1720                 :            :     }
    1721                 :            : 
    1722                 :          1 :     return _PyStatus_OK();
    1723                 :            : }
    1724                 :            : 
    1725                 :            : static PyStatus
    1726                 :          4 : config_init_perf_profiling(PyConfig *config)
    1727                 :            : {
    1728                 :          4 :     int active = 0;
    1729                 :          4 :     const char *env = config_get_env(config, "PYTHONPERFSUPPORT");
    1730         [ -  + ]:          4 :     if (env) {
    1731         [ #  # ]:          0 :         if (_Py_str_to_int(env, &active) != 0) {
    1732                 :          0 :             active = 0;
    1733                 :            :         }
    1734         [ #  # ]:          0 :         if (active) {
    1735                 :          0 :             config->perf_profiling = 1;
    1736                 :            :         }
    1737                 :            :     }
    1738                 :          4 :     const wchar_t *xoption = config_get_xoption(config, L"perf");
    1739         [ -  + ]:          4 :     if (xoption) {
    1740                 :          0 :         config->perf_profiling = 1;
    1741                 :            :     }
    1742                 :          4 :     return _PyStatus_OK();
    1743                 :            : 
    1744                 :            : }
    1745                 :            : 
    1746                 :            : static PyStatus
    1747                 :          4 : config_init_tracemalloc(PyConfig *config)
    1748                 :            : {
    1749                 :            :     int nframe;
    1750                 :            :     int valid;
    1751                 :            : 
    1752                 :          4 :     const char *env = config_get_env(config, "PYTHONTRACEMALLOC");
    1753         [ -  + ]:          4 :     if (env) {
    1754         [ #  # ]:          0 :         if (!_Py_str_to_int(env, &nframe)) {
    1755                 :          0 :             valid = (nframe >= 0);
    1756                 :            :         }
    1757                 :            :         else {
    1758                 :          0 :             valid = 0;
    1759                 :            :         }
    1760         [ #  # ]:          0 :         if (!valid) {
    1761                 :          0 :             return _PyStatus_ERR("PYTHONTRACEMALLOC: invalid number of frames");
    1762                 :            :         }
    1763                 :          0 :         config->tracemalloc = nframe;
    1764                 :            :     }
    1765                 :            : 
    1766                 :          4 :     const wchar_t *xoption = config_get_xoption(config, L"tracemalloc");
    1767         [ -  + ]:          4 :     if (xoption) {
    1768                 :          0 :         const wchar_t *sep = wcschr(xoption, L'=');
    1769         [ #  # ]:          0 :         if (sep) {
    1770         [ #  # ]:          0 :             if (!config_wstr_to_int(sep + 1, &nframe)) {
    1771                 :          0 :                 valid = (nframe >= 0);
    1772                 :            :             }
    1773                 :            :             else {
    1774                 :          0 :                 valid = 0;
    1775                 :            :             }
    1776         [ #  # ]:          0 :             if (!valid) {
    1777                 :          0 :                 return _PyStatus_ERR("-X tracemalloc=NFRAME: "
    1778                 :            :                                      "invalid number of frames");
    1779                 :            :             }
    1780                 :            :         }
    1781                 :            :         else {
    1782                 :            :             /* -X tracemalloc behaves as -X tracemalloc=1 */
    1783                 :          0 :             nframe = 1;
    1784                 :            :         }
    1785                 :          0 :         config->tracemalloc = nframe;
    1786                 :            :     }
    1787                 :          4 :     return _PyStatus_OK();
    1788                 :            : }
    1789                 :            : 
    1790                 :            : static PyStatus
    1791                 :          4 : config_init_int_max_str_digits(PyConfig *config)
    1792                 :            : {
    1793                 :            :     int maxdigits;
    1794                 :            : 
    1795                 :          4 :     const char *env = config_get_env(config, "PYTHONINTMAXSTRDIGITS");
    1796         [ -  + ]:          4 :     if (env) {
    1797                 :          0 :         bool valid = 0;
    1798         [ #  # ]:          0 :         if (!_Py_str_to_int(env, &maxdigits)) {
    1799   [ #  #  #  # ]:          0 :             valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
    1800                 :            :         }
    1801         [ #  # ]:          0 :         if (!valid) {
    1802                 :            : #define STRINGIFY(VAL) _STRINGIFY(VAL)
    1803                 :            : #define _STRINGIFY(VAL) #VAL
    1804                 :          0 :             return _PyStatus_ERR(
    1805                 :            :                     "PYTHONINTMAXSTRDIGITS: invalid limit; must be >= "
    1806                 :            :                     STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)
    1807                 :            :                     " or 0 for unlimited.");
    1808                 :            :         }
    1809                 :          0 :         config->int_max_str_digits = maxdigits;
    1810                 :            :     }
    1811                 :            : 
    1812                 :          4 :     const wchar_t *xoption = config_get_xoption(config, L"int_max_str_digits");
    1813         [ -  + ]:          4 :     if (xoption) {
    1814                 :          0 :         const wchar_t *sep = wcschr(xoption, L'=');
    1815                 :          0 :         bool valid = 0;
    1816         [ #  # ]:          0 :         if (sep) {
    1817         [ #  # ]:          0 :             if (!config_wstr_to_int(sep + 1, &maxdigits)) {
    1818   [ #  #  #  # ]:          0 :                 valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
    1819                 :            :             }
    1820                 :            :         }
    1821         [ #  # ]:          0 :         if (!valid) {
    1822                 :          0 :             return _PyStatus_ERR(
    1823                 :            :                     "-X int_max_str_digits: invalid limit; must be >= "
    1824                 :            :                     STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)
    1825                 :            :                     " or 0 for unlimited.");
    1826                 :            : #undef _STRINGIFY
    1827                 :            : #undef STRINGIFY
    1828                 :            :         }
    1829                 :          0 :         config->int_max_str_digits = maxdigits;
    1830                 :            :     }
    1831         [ +  - ]:          4 :     if (config->int_max_str_digits < 0) {
    1832                 :          4 :         config->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;
    1833                 :            :     }
    1834                 :          4 :     return _PyStatus_OK();
    1835                 :            : }
    1836                 :            : 
    1837                 :            : static PyStatus
    1838                 :         50 : config_init_pycache_prefix(PyConfig *config)
    1839                 :            : {
    1840                 :            :     assert(config->pycache_prefix == NULL);
    1841                 :            : 
    1842                 :         50 :     const wchar_t *xoption = config_get_xoption(config, L"pycache_prefix");
    1843         [ -  + ]:         50 :     if (xoption) {
    1844                 :          0 :         const wchar_t *sep = wcschr(xoption, L'=');
    1845   [ #  #  #  # ]:          0 :         if (sep && wcslen(sep) > 1) {
    1846                 :          0 :             config->pycache_prefix = _PyMem_RawWcsdup(sep + 1);
    1847         [ #  # ]:          0 :             if (config->pycache_prefix == NULL) {
    1848                 :          0 :                 return _PyStatus_NO_MEMORY();
    1849                 :            :             }
    1850                 :            :         }
    1851                 :            :         else {
    1852                 :            :             // PYTHONPYCACHEPREFIX env var ignored
    1853                 :            :             // if "-X pycache_prefix=" option is used
    1854                 :          0 :             config->pycache_prefix = NULL;
    1855                 :            :         }
    1856                 :          0 :         return _PyStatus_OK();
    1857                 :            :     }
    1858                 :            : 
    1859                 :         50 :     return CONFIG_GET_ENV_DUP(config, &config->pycache_prefix,
    1860                 :            :                               L"PYTHONPYCACHEPREFIX",
    1861                 :            :                               "PYTHONPYCACHEPREFIX");
    1862                 :            : }
    1863                 :            : 
    1864                 :            : 
    1865                 :            : static PyStatus
    1866                 :         50 : config_read_complex_options(PyConfig *config)
    1867                 :            : {
    1868                 :            :     /* More complex options configured by env var and -X option */
    1869         [ +  + ]:         50 :     if (config->faulthandler < 0) {
    1870         [ +  - ]:          4 :         if (config_get_env(config, "PYTHONFAULTHANDLER")
    1871         [ -  + ]:          4 :            || config_get_xoption(config, L"faulthandler")) {
    1872                 :          0 :             config->faulthandler = 1;
    1873                 :            :         }
    1874                 :            :     }
    1875         [ +  - ]:         50 :     if (config_get_env(config, "PYTHONPROFILEIMPORTTIME")
    1876         [ -  + ]:         50 :        || config_get_xoption(config, L"importtime")) {
    1877                 :          0 :         config->import_time = 1;
    1878                 :            :     }
    1879                 :            : 
    1880         [ +  - ]:         50 :     if (config_get_env(config, "PYTHONNODEBUGRANGES")
    1881         [ -  + ]:         50 :        || config_get_xoption(config, L"no_debug_ranges")) {
    1882                 :          0 :         config->code_debug_ranges = 0;
    1883                 :            :     }
    1884                 :            : 
    1885                 :            :     PyStatus status;
    1886         [ +  + ]:         50 :     if (config->tracemalloc < 0) {
    1887                 :          4 :         status = config_init_tracemalloc(config);
    1888         [ -  + ]:          4 :         if (_PyStatus_EXCEPTION(status)) {
    1889                 :          0 :             return status;
    1890                 :            :         }
    1891                 :            :     }
    1892                 :            : 
    1893         [ +  + ]:         50 :     if (config->perf_profiling < 0) {
    1894                 :          4 :         status = config_init_perf_profiling(config);
    1895         [ -  + ]:          4 :         if (_PyStatus_EXCEPTION(status)) {
    1896                 :          0 :             return status;
    1897                 :            :         }
    1898                 :            :     }
    1899                 :            : 
    1900         [ +  + ]:         50 :     if (config->int_max_str_digits < 0) {
    1901                 :          4 :         status = config_init_int_max_str_digits(config);
    1902         [ -  + ]:          4 :         if (_PyStatus_EXCEPTION(status)) {
    1903                 :          0 :             return status;
    1904                 :            :         }
    1905                 :            :     }
    1906                 :            : 
    1907         [ +  - ]:         50 :     if (config->pycache_prefix == NULL) {
    1908                 :         50 :         status = config_init_pycache_prefix(config);
    1909         [ -  + ]:         50 :         if (_PyStatus_EXCEPTION(status)) {
    1910                 :          0 :             return status;
    1911                 :            :         }
    1912                 :            :     }
    1913                 :         50 :     return _PyStatus_OK();
    1914                 :            : }
    1915                 :            : 
    1916                 :            : 
    1917                 :            : static const wchar_t *
    1918                 :         29 : config_get_stdio_errors(const PyPreConfig *preconfig)
    1919                 :            : {
    1920         [ -  + ]:         29 :     if (preconfig->utf8_mode) {
    1921                 :            :         /* UTF-8 Mode uses UTF-8/surrogateescape */
    1922                 :          0 :         return L"surrogateescape";
    1923                 :            :     }
    1924                 :            : 
    1925                 :            : #ifndef MS_WINDOWS
    1926                 :         29 :     const char *loc = setlocale(LC_CTYPE, NULL);
    1927         [ +  - ]:         29 :     if (loc != NULL) {
    1928                 :            :         /* surrogateescape is the default in the legacy C and POSIX locales */
    1929   [ +  +  -  + ]:         29 :         if (strcmp(loc, "C") == 0 || strcmp(loc, "POSIX") == 0) {
    1930                 :         25 :             return L"surrogateescape";
    1931                 :            :         }
    1932                 :            : 
    1933                 :            : #ifdef PY_COERCE_C_LOCALE
    1934                 :            :         /* surrogateescape is the default in locale coercion target locales */
    1935         [ -  + ]:          4 :         if (_Py_IsLocaleCoercionTarget(loc)) {
    1936                 :          0 :             return L"surrogateescape";
    1937                 :            :         }
    1938                 :            : #endif
    1939                 :            :     }
    1940                 :            : 
    1941                 :          4 :     return L"strict";
    1942                 :            : #else
    1943                 :            :     /* On Windows, always use surrogateescape by default */
    1944                 :            :     return L"surrogateescape";
    1945                 :            : #endif
    1946                 :            : }
    1947                 :            : 
    1948                 :            : 
    1949                 :            : // See also config_get_fs_encoding()
    1950                 :            : static PyStatus
    1951                 :         58 : config_get_locale_encoding(PyConfig *config, const PyPreConfig *preconfig,
    1952                 :            :                            wchar_t **locale_encoding)
    1953                 :            : {
    1954                 :            :     wchar_t *encoding;
    1955         [ -  + ]:         58 :     if (preconfig->utf8_mode) {
    1956                 :          0 :         encoding = _PyMem_RawWcsdup(L"utf-8");
    1957                 :            :     }
    1958                 :            :     else {
    1959                 :         58 :         encoding = _Py_GetLocaleEncoding();
    1960                 :            :     }
    1961         [ -  + ]:         58 :     if (encoding == NULL) {
    1962                 :          0 :         return _PyStatus_NO_MEMORY();
    1963                 :            :     }
    1964                 :         58 :     PyStatus status = PyConfig_SetString(config, locale_encoding, encoding);
    1965                 :         58 :     PyMem_RawFree(encoding);
    1966                 :         58 :     return status;
    1967                 :            : }
    1968                 :            : 
    1969                 :            : 
    1970                 :            : static PyStatus
    1971                 :         50 : config_init_stdio_encoding(PyConfig *config,
    1972                 :            :                            const PyPreConfig *preconfig)
    1973                 :            : {
    1974                 :            :     PyStatus status;
    1975                 :            : 
    1976                 :            :     /* If Py_SetStandardStreamEncoding() has been called, use its
    1977                 :            :         arguments if they are not NULL. */
    1978   [ +  +  -  + ]:         50 :     if (config->stdio_encoding == NULL && _Py_StandardStreamEncoding != NULL) {
    1979                 :          0 :         status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding,
    1980                 :            :                                       _Py_StandardStreamEncoding,
    1981                 :            :                                       "_Py_StandardStreamEncoding");
    1982         [ #  # ]:          0 :         if (_PyStatus_EXCEPTION(status)) {
    1983                 :          0 :             return status;
    1984                 :            :         }
    1985                 :            :     }
    1986                 :            : 
    1987   [ +  +  -  + ]:         50 :     if (config->stdio_errors == NULL && _Py_StandardStreamErrors != NULL) {
    1988                 :          0 :         status = CONFIG_SET_BYTES_STR(config, &config->stdio_errors,
    1989                 :            :                                       _Py_StandardStreamErrors,
    1990                 :            :                                       "_Py_StandardStreamErrors");
    1991         [ #  # ]:          0 :         if (_PyStatus_EXCEPTION(status)) {
    1992                 :          0 :             return status;
    1993                 :            :         }
    1994                 :            :     }
    1995                 :            : 
    1996                 :            :     // Exit if encoding and errors are defined
    1997   [ +  +  +  - ]:         50 :     if (config->stdio_encoding != NULL && config->stdio_errors != NULL) {
    1998                 :         21 :         return _PyStatus_OK();
    1999                 :            :     }
    2000                 :            : 
    2001                 :            :     /* PYTHONIOENCODING environment variable */
    2002                 :         29 :     const char *opt = config_get_env(config, "PYTHONIOENCODING");
    2003         [ -  + ]:         29 :     if (opt) {
    2004                 :          0 :         char *pythonioencoding = _PyMem_RawStrdup(opt);
    2005         [ #  # ]:          0 :         if (pythonioencoding == NULL) {
    2006                 :          0 :             return _PyStatus_NO_MEMORY();
    2007                 :            :         }
    2008                 :            : 
    2009                 :          0 :         char *errors = strchr(pythonioencoding, ':');
    2010         [ #  # ]:          0 :         if (errors) {
    2011                 :          0 :             *errors = '\0';
    2012                 :          0 :             errors++;
    2013         [ #  # ]:          0 :             if (!errors[0]) {
    2014                 :          0 :                 errors = NULL;
    2015                 :            :             }
    2016                 :            :         }
    2017                 :            : 
    2018                 :            :         /* Does PYTHONIOENCODING contain an encoding? */
    2019         [ #  # ]:          0 :         if (pythonioencoding[0]) {
    2020         [ #  # ]:          0 :             if (config->stdio_encoding == NULL) {
    2021                 :          0 :                 status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding,
    2022                 :            :                                               pythonioencoding,
    2023                 :            :                                               "PYTHONIOENCODING environment variable");
    2024         [ #  # ]:          0 :                 if (_PyStatus_EXCEPTION(status)) {
    2025                 :          0 :                     PyMem_RawFree(pythonioencoding);
    2026                 :          0 :                     return status;
    2027                 :            :                 }
    2028                 :            :             }
    2029                 :            : 
    2030                 :            :             /* If the encoding is set but not the error handler,
    2031                 :            :                use "strict" error handler by default.
    2032                 :            :                PYTHONIOENCODING=latin1 behaves as
    2033                 :            :                PYTHONIOENCODING=latin1:strict. */
    2034         [ #  # ]:          0 :             if (!errors) {
    2035                 :          0 :                 errors = "strict";
    2036                 :            :             }
    2037                 :            :         }
    2038                 :            : 
    2039   [ #  #  #  # ]:          0 :         if (config->stdio_errors == NULL && errors != NULL) {
    2040                 :          0 :             status = CONFIG_SET_BYTES_STR(config, &config->stdio_errors,
    2041                 :            :                                           errors,
    2042                 :            :                                           "PYTHONIOENCODING environment variable");
    2043         [ #  # ]:          0 :             if (_PyStatus_EXCEPTION(status)) {
    2044                 :          0 :                 PyMem_RawFree(pythonioencoding);
    2045                 :          0 :                 return status;
    2046                 :            :             }
    2047                 :            :         }
    2048                 :            : 
    2049                 :          0 :         PyMem_RawFree(pythonioencoding);
    2050                 :            :     }
    2051                 :            : 
    2052                 :            :     /* Choose the default error handler based on the current locale. */
    2053         [ +  - ]:         29 :     if (config->stdio_encoding == NULL) {
    2054                 :         29 :         status = config_get_locale_encoding(config, preconfig,
    2055                 :            :                                             &config->stdio_encoding);
    2056         [ -  + ]:         29 :         if (_PyStatus_EXCEPTION(status)) {
    2057                 :          0 :             return status;
    2058                 :            :         }
    2059                 :            :     }
    2060         [ +  - ]:         29 :     if (config->stdio_errors == NULL) {
    2061                 :         29 :         const wchar_t *errors = config_get_stdio_errors(preconfig);
    2062                 :            :         assert(errors != NULL);
    2063                 :            : 
    2064                 :         29 :         status = PyConfig_SetString(config, &config->stdio_errors, errors);
    2065         [ -  + ]:         29 :         if (_PyStatus_EXCEPTION(status)) {
    2066                 :          0 :             return status;
    2067                 :            :         }
    2068                 :            :     }
    2069                 :            : 
    2070                 :         29 :     return _PyStatus_OK();
    2071                 :            : }
    2072                 :            : 
    2073                 :            : 
    2074                 :            : // See also config_get_locale_encoding()
    2075                 :            : static PyStatus
    2076                 :         29 : config_get_fs_encoding(PyConfig *config, const PyPreConfig *preconfig,
    2077                 :            :                        wchar_t **fs_encoding)
    2078                 :            : {
    2079                 :            : #ifdef _Py_FORCE_UTF8_FS_ENCODING
    2080                 :            :     return PyConfig_SetString(config, fs_encoding, L"utf-8");
    2081                 :            : #elif defined(MS_WINDOWS)
    2082                 :            :     const wchar_t *encoding;
    2083                 :            :     if (preconfig->legacy_windows_fs_encoding) {
    2084                 :            :         // Legacy Windows filesystem encoding: mbcs/replace
    2085                 :            :         encoding = L"mbcs";
    2086                 :            :     }
    2087                 :            :     else {
    2088                 :            :         // Windows defaults to utf-8/surrogatepass (PEP 529)
    2089                 :            :         encoding = L"utf-8";
    2090                 :            :     }
    2091                 :            :      return PyConfig_SetString(config, fs_encoding, encoding);
    2092                 :            : #else  // !MS_WINDOWS
    2093         [ -  + ]:         29 :     if (preconfig->utf8_mode) {
    2094                 :          0 :         return PyConfig_SetString(config, fs_encoding, L"utf-8");
    2095                 :            :     }
    2096                 :            : 
    2097         [ -  + ]:         29 :     if (_Py_GetForceASCII()) {
    2098                 :          0 :         return PyConfig_SetString(config, fs_encoding, L"ascii");
    2099                 :            :     }
    2100                 :            : 
    2101                 :         29 :     return config_get_locale_encoding(config, preconfig, fs_encoding);
    2102                 :            : #endif  // !MS_WINDOWS
    2103                 :            : }
    2104                 :            : 
    2105                 :            : 
    2106                 :            : static PyStatus
    2107                 :         29 : config_init_fs_encoding(PyConfig *config, const PyPreConfig *preconfig)
    2108                 :            : {
    2109                 :            :     PyStatus status;
    2110                 :            : 
    2111         [ +  - ]:         29 :     if (config->filesystem_encoding == NULL) {
    2112                 :         29 :         status = config_get_fs_encoding(config, preconfig,
    2113                 :            :                                         &config->filesystem_encoding);
    2114         [ -  + ]:         29 :         if (_PyStatus_EXCEPTION(status)) {
    2115                 :          0 :             return status;
    2116                 :            :         }
    2117                 :            :     }
    2118                 :            : 
    2119         [ +  - ]:         29 :     if (config->filesystem_errors == NULL) {
    2120                 :            :         const wchar_t *errors;
    2121                 :            : #ifdef MS_WINDOWS
    2122                 :            :         if (preconfig->legacy_windows_fs_encoding) {
    2123                 :            :             errors = L"replace";
    2124                 :            :         }
    2125                 :            :         else {
    2126                 :            :             errors = L"surrogatepass";
    2127                 :            :         }
    2128                 :            : #else
    2129                 :         29 :         errors = L"surrogateescape";
    2130                 :            : #endif
    2131                 :         29 :         status = PyConfig_SetString(config, &config->filesystem_errors, errors);
    2132         [ -  + ]:         29 :         if (_PyStatus_EXCEPTION(status)) {
    2133                 :          0 :             return status;
    2134                 :            :         }
    2135                 :            :     }
    2136                 :         29 :     return _PyStatus_OK();
    2137                 :            : }
    2138                 :            : 
    2139                 :            : 
    2140                 :            : static PyStatus
    2141                 :         71 : config_init_import(PyConfig *config, int compute_path_config)
    2142                 :            : {
    2143                 :            :     PyStatus status;
    2144                 :            : 
    2145                 :         71 :     status = _PyConfig_InitPathConfig(config, compute_path_config);
    2146         [ -  + ]:         71 :     if (_PyStatus_EXCEPTION(status)) {
    2147                 :          0 :         return status;
    2148                 :            :     }
    2149                 :            : 
    2150                 :            :     /* -X frozen_modules=[on|off] */
    2151                 :         71 :     const wchar_t *value = config_get_xoption_value(config, L"frozen_modules");
    2152         [ -  + ]:         71 :     if (value == NULL) {
    2153                 :            :     }
    2154         [ #  # ]:          0 :     else if (wcscmp(value, L"on") == 0) {
    2155                 :          0 :         config->use_frozen_modules = 1;
    2156                 :            :     }
    2157         [ #  # ]:          0 :     else if (wcscmp(value, L"off") == 0) {
    2158                 :          0 :         config->use_frozen_modules = 0;
    2159                 :            :     }
    2160         [ #  # ]:          0 :     else if (wcslen(value) == 0) {
    2161                 :            :         // "-X frozen_modules" and "-X frozen_modules=" both imply "on".
    2162                 :          0 :         config->use_frozen_modules = 1;
    2163                 :            :     }
    2164                 :            :     else {
    2165                 :          0 :         return PyStatus_Error("bad value for option -X frozen_modules "
    2166                 :            :                               "(expected \"on\" or \"off\")");
    2167                 :            :     }
    2168                 :            : 
    2169                 :            :     assert(config->use_frozen_modules >= 0);
    2170                 :         71 :     return _PyStatus_OK();
    2171                 :            : }
    2172                 :            : 
    2173                 :            : PyStatus
    2174                 :         25 : _PyConfig_InitImportConfig(PyConfig *config)
    2175                 :            : {
    2176                 :         25 :     return config_init_import(config, 1);
    2177                 :            : }
    2178                 :            : 
    2179                 :            : 
    2180                 :            : static PyStatus
    2181                 :         50 : config_read(PyConfig *config, int compute_path_config)
    2182                 :            : {
    2183                 :            :     PyStatus status;
    2184                 :         50 :     const PyPreConfig *preconfig = &_PyRuntime.preconfig;
    2185                 :            : 
    2186         [ +  + ]:         50 :     if (config->use_environment) {
    2187                 :          1 :         status = config_read_env_vars(config);
    2188         [ -  + ]:          1 :         if (_PyStatus_EXCEPTION(status)) {
    2189                 :          0 :             return status;
    2190                 :            :         }
    2191                 :            :     }
    2192                 :            : 
    2193                 :            :     /* -X options */
    2194         [ -  + ]:         50 :     if (config_get_xoption(config, L"showrefcount")) {
    2195                 :          0 :         config->show_ref_count = 1;
    2196                 :            :     }
    2197                 :            : 
    2198                 :            : #ifdef Py_STATS
    2199                 :            :     if (config_get_xoption(config, L"pystats")) {
    2200                 :            :         _py_stats = &_py_stats_struct;
    2201                 :            :     }
    2202                 :            : #endif
    2203                 :            : 
    2204                 :         50 :     status = config_read_complex_options(config);
    2205         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    2206                 :          0 :         return status;
    2207                 :            :     }
    2208                 :            : 
    2209         [ +  + ]:         50 :     if (config->_install_importlib) {
    2210                 :         46 :         status = config_init_import(config, compute_path_config);
    2211         [ -  + ]:         46 :         if (_PyStatus_EXCEPTION(status)) {
    2212                 :          0 :             return status;
    2213                 :            :         }
    2214                 :            :     }
    2215                 :            : 
    2216                 :            :     /* default values */
    2217         [ -  + ]:         50 :     if (config->dev_mode) {
    2218         [ #  # ]:          0 :         if (config->faulthandler < 0) {
    2219                 :          0 :             config->faulthandler = 1;
    2220                 :            :         }
    2221                 :            :     }
    2222         [ +  + ]:         50 :     if (config->faulthandler < 0) {
    2223                 :          4 :         config->faulthandler = 0;
    2224                 :            :     }
    2225         [ +  + ]:         50 :     if (config->tracemalloc < 0) {
    2226                 :          4 :         config->tracemalloc = 0;
    2227                 :            :     }
    2228         [ +  + ]:         50 :     if (config->perf_profiling < 0) {
    2229                 :          4 :         config->perf_profiling = 0;
    2230                 :            :     }
    2231         [ +  + ]:         50 :     if (config->use_hash_seed < 0) {
    2232                 :          3 :         config->use_hash_seed = 0;
    2233                 :          3 :         config->hash_seed = 0;
    2234                 :            :     }
    2235                 :            : 
    2236   [ +  +  -  + ]:         50 :     if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) {
    2237                 :         29 :         status = config_init_fs_encoding(config, preconfig);
    2238         [ -  + ]:         29 :         if (_PyStatus_EXCEPTION(status)) {
    2239                 :          0 :             return status;
    2240                 :            :         }
    2241                 :            :     }
    2242                 :            : 
    2243                 :         50 :     status = config_init_stdio_encoding(config, preconfig);
    2244         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    2245                 :          0 :         return status;
    2246                 :            :     }
    2247                 :            : 
    2248         [ +  + ]:         50 :     if (config->argv.length < 1) {
    2249                 :            :         /* Ensure at least one (empty) argument is seen */
    2250                 :          4 :         status = PyWideStringList_Append(&config->argv, L"");
    2251         [ -  + ]:          4 :         if (_PyStatus_EXCEPTION(status)) {
    2252                 :          0 :             return status;
    2253                 :            :         }
    2254                 :            :     }
    2255                 :            : 
    2256         [ +  + ]:         50 :     if (config->check_hash_pycs_mode == NULL) {
    2257                 :         29 :         status = PyConfig_SetString(config, &config->check_hash_pycs_mode,
    2258                 :            :                                     L"default");
    2259         [ -  + ]:         29 :         if (_PyStatus_EXCEPTION(status)) {
    2260                 :          0 :             return status;
    2261                 :            :         }
    2262                 :            :     }
    2263                 :            : 
    2264         [ -  + ]:         50 :     if (config->configure_c_stdio < 0) {
    2265                 :          0 :         config->configure_c_stdio = 1;
    2266                 :            :     }
    2267                 :            : 
    2268                 :            :     // Only parse arguments once.
    2269         [ +  + ]:         50 :     if (config->parse_argv == 1) {
    2270                 :         25 :         config->parse_argv = 2;
    2271                 :            :     }
    2272                 :            : 
    2273                 :         50 :     return _PyStatus_OK();
    2274                 :            : }
    2275                 :            : 
    2276                 :            : 
    2277                 :            : static void
    2278                 :          4 : config_init_stdio(const PyConfig *config)
    2279                 :            : {
    2280                 :            : #if defined(MS_WINDOWS) || defined(__CYGWIN__)
    2281                 :            :     /* don't translate newlines (\r\n <=> \n) */
    2282                 :            :     _setmode(fileno(stdin), O_BINARY);
    2283                 :            :     _setmode(fileno(stdout), O_BINARY);
    2284                 :            :     _setmode(fileno(stderr), O_BINARY);
    2285                 :            : #endif
    2286                 :            : 
    2287         [ -  + ]:          4 :     if (!config->buffered_stdio) {
    2288                 :            : #ifdef HAVE_SETVBUF
    2289                 :          0 :         setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);
    2290                 :          0 :         setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
    2291                 :          0 :         setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
    2292                 :            : #else /* !HAVE_SETVBUF */
    2293                 :            :         setbuf(stdin,  (char *)NULL);
    2294                 :            :         setbuf(stdout, (char *)NULL);
    2295                 :            :         setbuf(stderr, (char *)NULL);
    2296                 :            : #endif /* !HAVE_SETVBUF */
    2297                 :            :     }
    2298         [ -  + ]:          4 :     else if (config->interactive) {
    2299                 :            : #ifdef MS_WINDOWS
    2300                 :            :         /* Doesn't have to have line-buffered -- use unbuffered */
    2301                 :            :         /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */
    2302                 :            :         setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
    2303                 :            : #else /* !MS_WINDOWS */
    2304                 :            : #ifdef HAVE_SETVBUF
    2305                 :          0 :         setvbuf(stdin,  (char *)NULL, _IOLBF, BUFSIZ);
    2306                 :          0 :         setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
    2307                 :            : #endif /* HAVE_SETVBUF */
    2308                 :            : #endif /* !MS_WINDOWS */
    2309                 :            :         /* Leave stderr alone - it should be unbuffered anyway. */
    2310                 :            :     }
    2311                 :          4 : }
    2312                 :            : 
    2313                 :            : 
    2314                 :            : /* Write the configuration:
    2315                 :            : 
    2316                 :            :    - set Py_xxx global configuration variables
    2317                 :            :    - initialize C standard streams (stdin, stdout, stderr) */
    2318                 :            : PyStatus
    2319                 :         29 : _PyConfig_Write(const PyConfig *config, _PyRuntimeState *runtime)
    2320                 :            : {
    2321                 :         29 :     config_set_global_vars(config);
    2322                 :            : 
    2323         [ +  + ]:         29 :     if (config->configure_c_stdio) {
    2324                 :          4 :         config_init_stdio(config);
    2325                 :            :     }
    2326                 :            : 
    2327                 :            :     /* Write the new pre-configuration into _PyRuntime */
    2328                 :         29 :     PyPreConfig *preconfig = &runtime->preconfig;
    2329                 :         29 :     preconfig->isolated = config->isolated;
    2330                 :         29 :     preconfig->use_environment = config->use_environment;
    2331                 :         29 :     preconfig->dev_mode = config->dev_mode;
    2332                 :            : 
    2333         [ -  + ]:         29 :     if (_Py_SetArgcArgv(config->orig_argv.length,
    2334                 :         29 :                         config->orig_argv.items) < 0)
    2335                 :            :     {
    2336                 :          0 :         return _PyStatus_NO_MEMORY();
    2337                 :            :     }
    2338                 :         29 :     return _PyStatus_OK();
    2339                 :            : }
    2340                 :            : 
    2341                 :            : 
    2342                 :            : /* --- PyConfig command line parser -------------------------- */
    2343                 :            : 
    2344                 :            : static void
    2345                 :          0 : config_usage(int error, const wchar_t* program)
    2346                 :            : {
    2347         [ #  # ]:          0 :     FILE *f = error ? stderr : stdout;
    2348                 :            : 
    2349                 :          0 :     fprintf(f, usage_line, program);
    2350         [ #  # ]:          0 :     if (error)
    2351                 :          0 :         fprintf(f, "Try `python -h' for more information.\n");
    2352                 :            :     else {
    2353                 :          0 :         fputs(usage_help, f);
    2354                 :            :     }
    2355                 :          0 : }
    2356                 :            : 
    2357                 :            : static void
    2358                 :          0 : config_envvars_usage()
    2359                 :            : {
    2360                 :          0 :     printf(usage_envvars, (wint_t)DELIM, (wint_t)DELIM, PYTHONHOMEHELP);
    2361                 :          0 : }
    2362                 :            : 
    2363                 :            : static void
    2364                 :          0 : config_xoptions_usage()
    2365                 :            : {
    2366                 :          0 :     puts(usage_xoptions);
    2367                 :          0 : }
    2368                 :            : 
    2369                 :            : static void
    2370                 :          0 : config_complete_usage(const wchar_t* program)
    2371                 :            : {
    2372                 :          0 :    config_usage(0, program);
    2373                 :          0 :    puts("\n");
    2374                 :          0 :    config_envvars_usage();
    2375                 :          0 :    puts("\n");
    2376                 :          0 :    config_xoptions_usage();
    2377                 :          0 : }
    2378                 :            : 
    2379                 :            : 
    2380                 :            : /* Parse the command line arguments */
    2381                 :            : static PyStatus
    2382                 :         25 : config_parse_cmdline(PyConfig *config, PyWideStringList *warnoptions,
    2383                 :            :                      Py_ssize_t *opt_index)
    2384                 :            : {
    2385                 :            :     PyStatus status;
    2386                 :         25 :     const PyWideStringList *argv = &config->argv;
    2387                 :         25 :     int print_version = 0;
    2388                 :         25 :     const wchar_t* program = config->program_name;
    2389   [ +  -  +  - ]:         25 :     if (!program && argv->length >= 1) {
    2390                 :         25 :         program = argv->items[0];
    2391                 :            :     }
    2392                 :            : 
    2393                 :         25 :     _PyOS_ResetGetOpt();
    2394                 :          4 :     do {
    2395                 :         29 :         int longindex = -1;
    2396                 :         29 :         int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
    2397         [ +  + ]:         29 :         if (c == EOF) {
    2398                 :         22 :             break;
    2399                 :            :         }
    2400                 :            : 
    2401         [ +  + ]:          7 :         if (c == 'c') {
    2402         [ +  - ]:          1 :             if (config->run_command == NULL) {
    2403                 :            :                 /* -c is the last option; following arguments
    2404                 :            :                    that look like options are left for the
    2405                 :            :                    command to interpret. */
    2406                 :          1 :                 size_t len = wcslen(_PyOS_optarg) + 1 + 1;
    2407                 :          1 :                 wchar_t *command = PyMem_RawMalloc(sizeof(wchar_t) * len);
    2408         [ -  + ]:          1 :                 if (command == NULL) {
    2409                 :          0 :                     return _PyStatus_NO_MEMORY();
    2410                 :            :                 }
    2411                 :          1 :                 memcpy(command, _PyOS_optarg, (len - 2) * sizeof(wchar_t));
    2412                 :          1 :                 command[len - 2] = '\n';
    2413                 :          1 :                 command[len - 1] = 0;
    2414                 :          1 :                 config->run_command = command;
    2415                 :            :             }
    2416                 :          1 :             break;
    2417                 :            :         }
    2418                 :            : 
    2419         [ +  + ]:          6 :         if (c == 'm') {
    2420                 :            :             /* -m is the last option; following arguments
    2421                 :            :                that look like options are left for the
    2422                 :            :                module to interpret. */
    2423         [ +  - ]:          2 :             if (config->run_module == NULL) {
    2424                 :          2 :                 config->run_module = _PyMem_RawWcsdup(_PyOS_optarg);
    2425         [ -  + ]:          2 :                 if (config->run_module == NULL) {
    2426                 :          0 :                     return _PyStatus_NO_MEMORY();
    2427                 :            :                 }
    2428                 :            :             }
    2429                 :          2 :             break;
    2430                 :            :         }
    2431                 :            : 
    2432   [ -  -  -  -  :          4 :         switch (c) {
          -  -  -  +  -  
          -  -  -  +  -  
          -  -  -  -  -  
             -  -  -  - ]
    2433                 :            :         // Integers represent long options, see Python/getopt.c
    2434                 :          0 :         case 0:
    2435                 :            :             // check-hash-based-pycs
    2436         [ #  # ]:          0 :             if (wcscmp(_PyOS_optarg, L"always") == 0
    2437         [ #  # ]:          0 :                 || wcscmp(_PyOS_optarg, L"never") == 0
    2438         [ #  # ]:          0 :                 || wcscmp(_PyOS_optarg, L"default") == 0)
    2439                 :            :             {
    2440                 :          0 :                 status = PyConfig_SetString(config, &config->check_hash_pycs_mode,
    2441                 :            :                                             _PyOS_optarg);
    2442         [ #  # ]:          0 :                 if (_PyStatus_EXCEPTION(status)) {
    2443                 :          0 :                     return status;
    2444                 :            :                 }
    2445                 :            :             } else {
    2446                 :          0 :                 fprintf(stderr, "--check-hash-based-pycs must be one of "
    2447                 :            :                         "'default', 'always', or 'never'\n");
    2448                 :          0 :                 config_usage(1, program);
    2449                 :          0 :                 return _PyStatus_EXIT(2);
    2450                 :            :             }
    2451                 :          4 :             break;
    2452                 :            : 
    2453                 :          0 :         case 1:
    2454                 :            :             // help-all
    2455                 :          0 :             config_complete_usage(program);
    2456                 :          0 :             return _PyStatus_EXIT(0);
    2457                 :            : 
    2458                 :          0 :         case 2:
    2459                 :            :             // help-env
    2460                 :          0 :             config_envvars_usage();
    2461                 :          0 :             return _PyStatus_EXIT(0);
    2462                 :            : 
    2463                 :          0 :         case 3:
    2464                 :            :             // help-xoptions
    2465                 :          0 :             config_xoptions_usage();
    2466                 :          0 :             return _PyStatus_EXIT(0);
    2467                 :            : 
    2468                 :          0 :         case 'b':
    2469                 :          0 :             config->bytes_warning++;
    2470                 :          0 :             break;
    2471                 :            : 
    2472                 :          0 :         case 'd':
    2473                 :          0 :             config->parser_debug++;
    2474                 :          0 :             break;
    2475                 :            : 
    2476                 :          0 :         case 'i':
    2477                 :          0 :             config->inspect++;
    2478                 :          0 :             config->interactive++;
    2479                 :          0 :             break;
    2480                 :            : 
    2481                 :          3 :         case 'E':
    2482                 :            :         case 'I':
    2483                 :            :         case 'X':
    2484                 :            :             /* option handled by _PyPreCmdline_Read() */
    2485                 :          3 :             break;
    2486                 :            : 
    2487                 :            :         /* case 'J': reserved for Jython */
    2488                 :            : 
    2489                 :          0 :         case 'O':
    2490                 :          0 :             config->optimization_level++;
    2491                 :          0 :             break;
    2492                 :            : 
    2493                 :          0 :         case 'P':
    2494                 :          0 :             config->safe_path = 1;
    2495                 :          0 :             break;
    2496                 :            : 
    2497                 :          0 :         case 'B':
    2498                 :          0 :             config->write_bytecode = 0;
    2499                 :          0 :             break;
    2500                 :            : 
    2501                 :          0 :         case 's':
    2502                 :          0 :             config->user_site_directory = 0;
    2503                 :          0 :             break;
    2504                 :            : 
    2505                 :          1 :         case 'S':
    2506                 :          1 :             config->site_import = 0;
    2507                 :          1 :             break;
    2508                 :            : 
    2509                 :          0 :         case 't':
    2510                 :            :             /* ignored for backwards compatibility */
    2511                 :          0 :             break;
    2512                 :            : 
    2513                 :          0 :         case 'u':
    2514                 :          0 :             config->buffered_stdio = 0;
    2515                 :          0 :             break;
    2516                 :            : 
    2517                 :          0 :         case 'v':
    2518                 :          0 :             config->verbose++;
    2519                 :          0 :             break;
    2520                 :            : 
    2521                 :          0 :         case 'x':
    2522                 :          0 :             config->skip_source_first_line = 1;
    2523                 :          0 :             break;
    2524                 :            : 
    2525                 :          0 :         case 'h':
    2526                 :            :         case '?':
    2527                 :          0 :             config_usage(0, program);
    2528                 :          0 :             return _PyStatus_EXIT(0);
    2529                 :            : 
    2530                 :          0 :         case 'V':
    2531                 :          0 :             print_version++;
    2532                 :          0 :             break;
    2533                 :            : 
    2534                 :          0 :         case 'W':
    2535                 :          0 :             status = PyWideStringList_Append(warnoptions, _PyOS_optarg);
    2536         [ #  # ]:          0 :             if (_PyStatus_EXCEPTION(status)) {
    2537                 :          0 :                 return status;
    2538                 :            :             }
    2539                 :          0 :             break;
    2540                 :            : 
    2541                 :          0 :         case 'q':
    2542                 :          0 :             config->quiet++;
    2543                 :          0 :             break;
    2544                 :            : 
    2545                 :          0 :         case 'R':
    2546                 :          0 :             config->use_hash_seed = 0;
    2547                 :          0 :             break;
    2548                 :            : 
    2549                 :            :         /* This space reserved for other options */
    2550                 :            : 
    2551                 :          0 :         default:
    2552                 :            :             /* unknown argument: parsing failed */
    2553                 :          0 :             config_usage(1, program);
    2554                 :          0 :             return _PyStatus_EXIT(2);
    2555                 :            :         }
    2556                 :            :     } while (1);
    2557                 :            : 
    2558         [ -  + ]:         25 :     if (print_version) {
    2559         [ #  # ]:          0 :         printf("Python %s\n",
    2560                 :          0 :                 (print_version >= 2) ? Py_GetVersion() : PY_VERSION);
    2561                 :          0 :         return _PyStatus_EXIT(0);
    2562                 :            :     }
    2563                 :            : 
    2564   [ +  +  +  + ]:         25 :     if (config->run_command == NULL && config->run_module == NULL
    2565         [ +  - ]:         22 :         && _PyOS_optind < argv->length
    2566         [ +  - ]:         22 :         && wcscmp(argv->items[_PyOS_optind], L"-") != 0
    2567         [ +  - ]:         22 :         && config->run_filename == NULL)
    2568                 :            :     {
    2569                 :         22 :         config->run_filename = _PyMem_RawWcsdup(argv->items[_PyOS_optind]);
    2570         [ -  + ]:         22 :         if (config->run_filename == NULL) {
    2571                 :          0 :             return _PyStatus_NO_MEMORY();
    2572                 :            :         }
    2573                 :            :     }
    2574                 :            : 
    2575   [ +  +  +  + ]:         25 :     if (config->run_command != NULL || config->run_module != NULL) {
    2576                 :            :         /* Backup _PyOS_optind */
    2577                 :          3 :         _PyOS_optind--;
    2578                 :            :     }
    2579                 :            : 
    2580                 :         25 :     *opt_index = _PyOS_optind;
    2581                 :            : 
    2582                 :         25 :     return _PyStatus_OK();
    2583                 :            : }
    2584                 :            : 
    2585                 :            : 
    2586                 :            : #ifdef MS_WINDOWS
    2587                 :            : #  define WCSTOK wcstok_s
    2588                 :            : #else
    2589                 :            : #  define WCSTOK wcstok
    2590                 :            : #endif
    2591                 :            : 
    2592                 :            : /* Get warning options from PYTHONWARNINGS environment variable. */
    2593                 :            : static PyStatus
    2594                 :          1 : config_init_env_warnoptions(PyConfig *config, PyWideStringList *warnoptions)
    2595                 :            : {
    2596                 :            :     PyStatus status;
    2597                 :            :     /* CONFIG_GET_ENV_DUP requires dest to be initialized to NULL */
    2598                 :          1 :     wchar_t *env = NULL;
    2599                 :          1 :     status = CONFIG_GET_ENV_DUP(config, &env,
    2600                 :            :                              L"PYTHONWARNINGS", "PYTHONWARNINGS");
    2601         [ -  + ]:          1 :     if (_PyStatus_EXCEPTION(status)) {
    2602                 :          0 :         return status;
    2603                 :            :     }
    2604                 :            : 
    2605                 :            :     /* env var is not set or is empty */
    2606         [ +  - ]:          1 :     if (env == NULL) {
    2607                 :          1 :         return _PyStatus_OK();
    2608                 :            :     }
    2609                 :            : 
    2610                 :            : 
    2611                 :          0 :     wchar_t *warning, *context = NULL;
    2612         [ #  # ]:          0 :     for (warning = WCSTOK(env, L",", &context);
    2613                 :            :          warning != NULL;
    2614                 :          0 :          warning = WCSTOK(NULL, L",", &context))
    2615                 :            :     {
    2616                 :          0 :         status = PyWideStringList_Append(warnoptions, warning);
    2617         [ #  # ]:          0 :         if (_PyStatus_EXCEPTION(status)) {
    2618                 :          0 :             PyMem_RawFree(env);
    2619                 :          0 :             return status;
    2620                 :            :         }
    2621                 :            :     }
    2622                 :          0 :     PyMem_RawFree(env);
    2623                 :          0 :     return _PyStatus_OK();
    2624                 :            : }
    2625                 :            : 
    2626                 :            : 
    2627                 :            : static PyStatus
    2628                 :          0 : warnoptions_append(PyConfig *config, PyWideStringList *options,
    2629                 :            :                    const wchar_t *option)
    2630                 :            : {
    2631                 :            :     /* config_init_warnoptions() add existing config warnoptions at the end:
    2632                 :            :        ensure that the new option is not already present in this list to
    2633                 :            :        prevent change the options order when config_init_warnoptions() is
    2634                 :            :        called twice. */
    2635         [ #  # ]:          0 :     if (_PyWideStringList_Find(&config->warnoptions, option)) {
    2636                 :            :         /* Already present: do nothing */
    2637                 :          0 :         return _PyStatus_OK();
    2638                 :            :     }
    2639         [ #  # ]:          0 :     if (_PyWideStringList_Find(options, option)) {
    2640                 :            :         /* Already present: do nothing */
    2641                 :          0 :         return _PyStatus_OK();
    2642                 :            :     }
    2643                 :          0 :     return PyWideStringList_Append(options, option);
    2644                 :            : }
    2645                 :            : 
    2646                 :            : 
    2647                 :            : static PyStatus
    2648                 :        150 : warnoptions_extend(PyConfig *config, PyWideStringList *options,
    2649                 :            :                    const PyWideStringList *options2)
    2650                 :            : {
    2651                 :        150 :     const Py_ssize_t len = options2->length;
    2652                 :        150 :     wchar_t *const *items = options2->items;
    2653                 :            : 
    2654         [ -  + ]:        150 :     for (Py_ssize_t i = 0; i < len; i++) {
    2655                 :          0 :         PyStatus status = warnoptions_append(config, options, items[i]);
    2656         [ #  # ]:          0 :         if (_PyStatus_EXCEPTION(status)) {
    2657                 :          0 :             return status;
    2658                 :            :         }
    2659                 :            :     }
    2660                 :        150 :     return _PyStatus_OK();
    2661                 :            : }
    2662                 :            : 
    2663                 :            : 
    2664                 :            : static PyStatus
    2665                 :         50 : config_init_warnoptions(PyConfig *config,
    2666                 :            :                         const PyWideStringList *cmdline_warnoptions,
    2667                 :            :                         const PyWideStringList *env_warnoptions,
    2668                 :            :                         const PyWideStringList *sys_warnoptions)
    2669                 :            : {
    2670                 :            :     PyStatus status;
    2671                 :         50 :     PyWideStringList options = _PyWideStringList_INIT;
    2672                 :            : 
    2673                 :            :     /* Priority of warnings options, lowest to highest:
    2674                 :            :      *
    2675                 :            :      * - any implicit filters added by _warnings.c/warnings.py
    2676                 :            :      * - PyConfig.dev_mode: "default" filter
    2677                 :            :      * - PYTHONWARNINGS environment variable
    2678                 :            :      * - '-W' command line options
    2679                 :            :      * - PyConfig.bytes_warning ('-b' and '-bb' command line options):
    2680                 :            :      *   "default::BytesWarning" or "error::BytesWarning" filter
    2681                 :            :      * - early PySys_AddWarnOption() calls
    2682                 :            :      * - PyConfig.warnoptions
    2683                 :            :      *
    2684                 :            :      * PyConfig.warnoptions is copied to sys.warnoptions. Since the warnings
    2685                 :            :      * module works on the basis of "the most recently added filter will be
    2686                 :            :      * checked first", we add the lowest precedence entries first so that later
    2687                 :            :      * entries override them.
    2688                 :            :      */
    2689                 :            : 
    2690         [ -  + ]:         50 :     if (config->dev_mode) {
    2691                 :          0 :         status = warnoptions_append(config, &options, L"default");
    2692         [ #  # ]:          0 :         if (_PyStatus_EXCEPTION(status)) {
    2693                 :          0 :             goto error;
    2694                 :            :         }
    2695                 :            :     }
    2696                 :            : 
    2697                 :         50 :     status = warnoptions_extend(config, &options, env_warnoptions);
    2698         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    2699                 :          0 :         goto error;
    2700                 :            :     }
    2701                 :            : 
    2702                 :         50 :     status = warnoptions_extend(config, &options, cmdline_warnoptions);
    2703         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    2704                 :          0 :         goto error;
    2705                 :            :     }
    2706                 :            : 
    2707                 :            :     /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c
    2708                 :            :      * don't even try to emit a warning, so we skip setting the filter in that
    2709                 :            :      * case.
    2710                 :            :      */
    2711         [ -  + ]:         50 :     if (config->bytes_warning) {
    2712                 :            :         const wchar_t *filter;
    2713         [ #  # ]:          0 :         if (config->bytes_warning> 1) {
    2714                 :          0 :             filter = L"error::BytesWarning";
    2715                 :            :         }
    2716                 :            :         else {
    2717                 :          0 :             filter = L"default::BytesWarning";
    2718                 :            :         }
    2719                 :          0 :         status = warnoptions_append(config, &options, filter);
    2720         [ #  # ]:          0 :         if (_PyStatus_EXCEPTION(status)) {
    2721                 :          0 :             goto error;
    2722                 :            :         }
    2723                 :            :     }
    2724                 :            : 
    2725                 :         50 :     status = warnoptions_extend(config, &options, sys_warnoptions);
    2726         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    2727                 :          0 :         goto error;
    2728                 :            :     }
    2729                 :            : 
    2730                 :            :     /* Always add all PyConfig.warnoptions options */
    2731                 :         50 :     status = _PyWideStringList_Extend(&options, &config->warnoptions);
    2732         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    2733                 :          0 :         goto error;
    2734                 :            :     }
    2735                 :            : 
    2736                 :         50 :     _PyWideStringList_Clear(&config->warnoptions);
    2737                 :         50 :     config->warnoptions = options;
    2738                 :         50 :     return _PyStatus_OK();
    2739                 :            : 
    2740                 :          0 : error:
    2741                 :          0 :     _PyWideStringList_Clear(&options);
    2742                 :          0 :     return status;
    2743                 :            : }
    2744                 :            : 
    2745                 :            : 
    2746                 :            : static PyStatus
    2747                 :         25 : config_update_argv(PyConfig *config, Py_ssize_t opt_index)
    2748                 :            : {
    2749                 :         25 :     const PyWideStringList *cmdline_argv = &config->argv;
    2750                 :         25 :     PyWideStringList config_argv = _PyWideStringList_INIT;
    2751                 :            : 
    2752                 :            :     /* Copy argv to be able to modify it (to force -c/-m) */
    2753         [ -  + ]:         25 :     if (cmdline_argv->length <= opt_index) {
    2754                 :            :         /* Ensure at least one (empty) argument is seen */
    2755                 :          0 :         PyStatus status = PyWideStringList_Append(&config_argv, L"");
    2756         [ #  # ]:          0 :         if (_PyStatus_EXCEPTION(status)) {
    2757                 :          0 :             return status;
    2758                 :            :         }
    2759                 :            :     }
    2760                 :            :     else {
    2761                 :            :         PyWideStringList slice;
    2762                 :         25 :         slice.length = cmdline_argv->length - opt_index;
    2763                 :         25 :         slice.items = &cmdline_argv->items[opt_index];
    2764         [ -  + ]:         25 :         if (_PyWideStringList_Copy(&config_argv, &slice) < 0) {
    2765                 :          0 :             return _PyStatus_NO_MEMORY();
    2766                 :            :         }
    2767                 :            :     }
    2768                 :            :     assert(config_argv.length >= 1);
    2769                 :            : 
    2770                 :         25 :     wchar_t *arg0 = NULL;
    2771         [ +  + ]:         25 :     if (config->run_command != NULL) {
    2772                 :            :         /* Force sys.argv[0] = '-c' */
    2773                 :          1 :         arg0 = L"-c";
    2774                 :            :     }
    2775         [ +  + ]:         24 :     else if (config->run_module != NULL) {
    2776                 :            :         /* Force sys.argv[0] = '-m'*/
    2777                 :          2 :         arg0 = L"-m";
    2778                 :            :     }
    2779                 :            : 
    2780         [ +  + ]:         25 :     if (arg0 != NULL) {
    2781                 :          3 :         arg0 = _PyMem_RawWcsdup(arg0);
    2782         [ -  + ]:          3 :         if (arg0 == NULL) {
    2783                 :          0 :             _PyWideStringList_Clear(&config_argv);
    2784                 :          0 :             return _PyStatus_NO_MEMORY();
    2785                 :            :         }
    2786                 :            : 
    2787                 :          3 :         PyMem_RawFree(config_argv.items[0]);
    2788                 :          3 :         config_argv.items[0] = arg0;
    2789                 :            :     }
    2790                 :            : 
    2791                 :         25 :     _PyWideStringList_Clear(&config->argv);
    2792                 :         25 :     config->argv = config_argv;
    2793                 :         25 :     return _PyStatus_OK();
    2794                 :            : }
    2795                 :            : 
    2796                 :            : 
    2797                 :            : static PyStatus
    2798                 :         50 : core_read_precmdline(PyConfig *config, _PyPreCmdline *precmdline)
    2799                 :            : {
    2800                 :            :     PyStatus status;
    2801                 :            : 
    2802         [ +  + ]:         50 :     if (config->parse_argv == 1) {
    2803         [ -  + ]:         25 :         if (_PyWideStringList_Copy(&precmdline->argv, &config->argv) < 0) {
    2804                 :          0 :             return _PyStatus_NO_MEMORY();
    2805                 :            :         }
    2806                 :            :     }
    2807                 :            : 
    2808                 :            :     PyPreConfig preconfig;
    2809                 :            : 
    2810                 :         50 :     status = _PyPreConfig_InitFromPreConfig(&preconfig, &_PyRuntime.preconfig);
    2811         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    2812                 :          0 :         return status;
    2813                 :            :     }
    2814                 :            : 
    2815                 :         50 :     _PyPreConfig_GetConfig(&preconfig, config);
    2816                 :            : 
    2817                 :         50 :     status = _PyPreCmdline_Read(precmdline, &preconfig);
    2818         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    2819                 :          0 :         return status;
    2820                 :            :     }
    2821                 :            : 
    2822                 :         50 :     status = _PyPreCmdline_SetConfig(precmdline, config);
    2823         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    2824                 :          0 :         return status;
    2825                 :            :     }
    2826                 :         50 :     return _PyStatus_OK();
    2827                 :            : }
    2828                 :            : 
    2829                 :            : 
    2830                 :            : /* Get run_filename absolute path */
    2831                 :            : static PyStatus
    2832                 :         50 : config_run_filename_abspath(PyConfig *config)
    2833                 :            : {
    2834         [ +  + ]:         50 :     if (!config->run_filename) {
    2835                 :          7 :         return _PyStatus_OK();
    2836                 :            :     }
    2837                 :            : 
    2838                 :            : #ifndef MS_WINDOWS
    2839         [ +  + ]:         43 :     if (_Py_isabs(config->run_filename)) {
    2840                 :            :         /* path is already absolute */
    2841                 :         21 :         return _PyStatus_OK();
    2842                 :            :     }
    2843                 :            : #endif
    2844                 :            : 
    2845                 :            :     wchar_t *abs_filename;
    2846         [ -  + ]:         22 :     if (_Py_abspath(config->run_filename, &abs_filename) < 0) {
    2847                 :            :         /* failed to get the absolute path of the command line filename:
    2848                 :            :            ignore the error, keep the relative path */
    2849                 :          0 :         return _PyStatus_OK();
    2850                 :            :     }
    2851         [ -  + ]:         22 :     if (abs_filename == NULL) {
    2852                 :          0 :         return _PyStatus_NO_MEMORY();
    2853                 :            :     }
    2854                 :            : 
    2855                 :         22 :     PyMem_RawFree(config->run_filename);
    2856                 :         22 :     config->run_filename = abs_filename;
    2857                 :         22 :     return _PyStatus_OK();
    2858                 :            : }
    2859                 :            : 
    2860                 :            : 
    2861                 :            : static PyStatus
    2862                 :         50 : config_read_cmdline(PyConfig *config)
    2863                 :            : {
    2864                 :            :     PyStatus status;
    2865                 :         50 :     PyWideStringList cmdline_warnoptions = _PyWideStringList_INIT;
    2866                 :         50 :     PyWideStringList env_warnoptions = _PyWideStringList_INIT;
    2867                 :         50 :     PyWideStringList sys_warnoptions = _PyWideStringList_INIT;
    2868                 :            : 
    2869         [ -  + ]:         50 :     if (config->parse_argv < 0) {
    2870                 :          0 :         config->parse_argv = 1;
    2871                 :            :     }
    2872                 :            : 
    2873         [ +  + ]:         50 :     if (config->parse_argv == 1) {
    2874                 :            :         Py_ssize_t opt_index;
    2875                 :         25 :         status = config_parse_cmdline(config, &cmdline_warnoptions, &opt_index);
    2876         [ -  + ]:         25 :         if (_PyStatus_EXCEPTION(status)) {
    2877                 :          0 :             goto done;
    2878                 :            :         }
    2879                 :            : 
    2880                 :         25 :         status = config_run_filename_abspath(config);
    2881         [ -  + ]:         25 :         if (_PyStatus_EXCEPTION(status)) {
    2882                 :          0 :             goto done;
    2883                 :            :         }
    2884                 :            : 
    2885                 :         25 :         status = config_update_argv(config, opt_index);
    2886         [ -  + ]:         25 :         if (_PyStatus_EXCEPTION(status)) {
    2887                 :          0 :             goto done;
    2888                 :            :         }
    2889                 :            :     }
    2890                 :            :     else {
    2891                 :         25 :         status = config_run_filename_abspath(config);
    2892         [ -  + ]:         25 :         if (_PyStatus_EXCEPTION(status)) {
    2893                 :          0 :             goto done;
    2894                 :            :         }
    2895                 :            :     }
    2896                 :            : 
    2897         [ +  + ]:         50 :     if (config->use_environment) {
    2898                 :          1 :         status = config_init_env_warnoptions(config, &env_warnoptions);
    2899         [ -  + ]:          1 :         if (_PyStatus_EXCEPTION(status)) {
    2900                 :          0 :             goto done;
    2901                 :            :         }
    2902                 :            :     }
    2903                 :            : 
    2904                 :            :     /* Handle early PySys_AddWarnOption() calls */
    2905                 :         50 :     status = _PySys_ReadPreinitWarnOptions(&sys_warnoptions);
    2906         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    2907                 :          0 :         goto done;
    2908                 :            :     }
    2909                 :            : 
    2910                 :         50 :     status = config_init_warnoptions(config,
    2911                 :            :                                      &cmdline_warnoptions,
    2912                 :            :                                      &env_warnoptions,
    2913                 :            :                                      &sys_warnoptions);
    2914         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    2915                 :          0 :         goto done;
    2916                 :            :     }
    2917                 :            : 
    2918                 :         50 :     status = _PyStatus_OK();
    2919                 :            : 
    2920                 :         50 : done:
    2921                 :         50 :     _PyWideStringList_Clear(&cmdline_warnoptions);
    2922                 :         50 :     _PyWideStringList_Clear(&env_warnoptions);
    2923                 :         50 :     _PyWideStringList_Clear(&sys_warnoptions);
    2924                 :         50 :     return status;
    2925                 :            : }
    2926                 :            : 
    2927                 :            : 
    2928                 :            : PyStatus
    2929                 :         25 : _PyConfig_SetPyArgv(PyConfig *config, const _PyArgv *args)
    2930                 :            : {
    2931                 :         25 :     PyStatus status = _Py_PreInitializeFromConfig(config, args);
    2932         [ -  + ]:         25 :     if (_PyStatus_EXCEPTION(status)) {
    2933                 :          0 :         return status;
    2934                 :            :     }
    2935                 :            : 
    2936                 :         25 :     return _PyArgv_AsWstrList(args, &config->argv);
    2937                 :            : }
    2938                 :            : 
    2939                 :            : 
    2940                 :            : /* Set config.argv: decode argv using Py_DecodeLocale(). Pre-initialize Python
    2941                 :            :    if needed to ensure that encodings are properly configured. */
    2942                 :            : PyStatus
    2943                 :         25 : PyConfig_SetBytesArgv(PyConfig *config, Py_ssize_t argc, char * const *argv)
    2944                 :            : {
    2945                 :         25 :     _PyArgv args = {
    2946                 :            :         .argc = argc,
    2947                 :            :         .use_bytes_argv = 1,
    2948                 :            :         .bytes_argv = argv,
    2949                 :            :         .wchar_argv = NULL};
    2950                 :         25 :     return _PyConfig_SetPyArgv(config, &args);
    2951                 :            : }
    2952                 :            : 
    2953                 :            : 
    2954                 :            : PyStatus
    2955                 :          0 : PyConfig_SetArgv(PyConfig *config, Py_ssize_t argc, wchar_t * const *argv)
    2956                 :            : {
    2957                 :          0 :     _PyArgv args = {
    2958                 :            :         .argc = argc,
    2959                 :            :         .use_bytes_argv = 0,
    2960                 :            :         .bytes_argv = NULL,
    2961                 :            :         .wchar_argv = argv};
    2962                 :          0 :     return _PyConfig_SetPyArgv(config, &args);
    2963                 :            : }
    2964                 :            : 
    2965                 :            : 
    2966                 :            : PyStatus
    2967                 :          0 : PyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list,
    2968                 :            :                            Py_ssize_t length, wchar_t **items)
    2969                 :            : {
    2970                 :          0 :     PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
    2971         [ #  # ]:          0 :     if (_PyStatus_EXCEPTION(status)) {
    2972                 :          0 :         return status;
    2973                 :            :     }
    2974                 :            : 
    2975                 :          0 :     PyWideStringList list2 = {.length = length, .items = items};
    2976         [ #  # ]:          0 :     if (_PyWideStringList_Copy(list, &list2) < 0) {
    2977                 :          0 :         return _PyStatus_NO_MEMORY();
    2978                 :            :     }
    2979                 :          0 :     return _PyStatus_OK();
    2980                 :            : }
    2981                 :            : 
    2982                 :            : 
    2983                 :            : /* Read the configuration into PyConfig from:
    2984                 :            : 
    2985                 :            :    * Command line arguments
    2986                 :            :    * Environment variables
    2987                 :            :    * Py_xxx global configuration variables
    2988                 :            : 
    2989                 :            :    The only side effects are to modify config and to call _Py_SetArgcArgv(). */
    2990                 :            : PyStatus
    2991                 :         50 : _PyConfig_Read(PyConfig *config, int compute_path_config)
    2992                 :            : {
    2993                 :            :     PyStatus status;
    2994                 :            : 
    2995                 :         50 :     status = _Py_PreInitializeFromConfig(config, NULL);
    2996         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    2997                 :          0 :         return status;
    2998                 :            :     }
    2999                 :            : 
    3000                 :         50 :     config_get_global_vars(config);
    3001                 :            : 
    3002         [ +  + ]:         50 :     if (config->orig_argv.length == 0
    3003         [ -  + ]:         29 :         && !(config->argv.length == 1
    3004         [ #  # ]:          0 :              && wcscmp(config->argv.items[0], L"") == 0))
    3005                 :            :     {
    3006         [ -  + ]:         29 :         if (_PyWideStringList_Copy(&config->orig_argv, &config->argv) < 0) {
    3007                 :          0 :             return _PyStatus_NO_MEMORY();
    3008                 :            :         }
    3009                 :            :     }
    3010                 :            : 
    3011                 :         50 :     _PyPreCmdline precmdline = _PyPreCmdline_INIT;
    3012                 :         50 :     status = core_read_precmdline(config, &precmdline);
    3013         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    3014                 :          0 :         goto done;
    3015                 :            :     }
    3016                 :            : 
    3017                 :            :     assert(config->isolated >= 0);
    3018         [ +  + ]:         50 :     if (config->isolated) {
    3019                 :          4 :         config->safe_path = 1;
    3020                 :          4 :         config->use_environment = 0;
    3021                 :          4 :         config->user_site_directory = 0;
    3022                 :            :     }
    3023                 :            : 
    3024                 :         50 :     status = config_read_cmdline(config);
    3025         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    3026                 :          0 :         goto done;
    3027                 :            :     }
    3028                 :            : 
    3029                 :            :     /* Handle early PySys_AddXOption() calls */
    3030                 :         50 :     status = _PySys_ReadPreinitXOptions(config);
    3031         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    3032                 :          0 :         goto done;
    3033                 :            :     }
    3034                 :            : 
    3035                 :         50 :     status = config_read(config, compute_path_config);
    3036         [ -  + ]:         50 :     if (_PyStatus_EXCEPTION(status)) {
    3037                 :          0 :         goto done;
    3038                 :            :     }
    3039                 :            : 
    3040                 :            :     assert(config_check_consistency(config));
    3041                 :            : 
    3042                 :         50 :     status = _PyStatus_OK();
    3043                 :            : 
    3044                 :         50 : done:
    3045                 :         50 :     _PyPreCmdline_Clear(&precmdline);
    3046                 :         50 :     return status;
    3047                 :            : }
    3048                 :            : 
    3049                 :            : 
    3050                 :            : PyStatus
    3051                 :         21 : PyConfig_Read(PyConfig *config)
    3052                 :            : {
    3053                 :         21 :     return _PyConfig_Read(config, 0);
    3054                 :            : }
    3055                 :            : 
    3056                 :            : 
    3057                 :            : PyObject*
    3058                 :          0 : _Py_GetConfigsAsDict(void)
    3059                 :            : {
    3060                 :          0 :     PyObject *result = NULL;
    3061                 :          0 :     PyObject *dict = NULL;
    3062                 :            : 
    3063                 :          0 :     result = PyDict_New();
    3064         [ #  # ]:          0 :     if (result == NULL) {
    3065                 :          0 :         goto error;
    3066                 :            :     }
    3067                 :            : 
    3068                 :            :     /* global result */
    3069                 :          0 :     dict = _Py_GetGlobalVariablesAsDict();
    3070         [ #  # ]:          0 :     if (dict == NULL) {
    3071                 :          0 :         goto error;
    3072                 :            :     }
    3073         [ #  # ]:          0 :     if (PyDict_SetItemString(result, "global_config", dict) < 0) {
    3074                 :          0 :         goto error;
    3075                 :            :     }
    3076         [ #  # ]:          0 :     Py_CLEAR(dict);
    3077                 :            : 
    3078                 :            :     /* pre config */
    3079                 :          0 :     PyInterpreterState *interp = _PyInterpreterState_GET();
    3080                 :          0 :     const PyPreConfig *pre_config = &interp->runtime->preconfig;
    3081                 :          0 :     dict = _PyPreConfig_AsDict(pre_config);
    3082         [ #  # ]:          0 :     if (dict == NULL) {
    3083                 :          0 :         goto error;
    3084                 :            :     }
    3085         [ #  # ]:          0 :     if (PyDict_SetItemString(result, "pre_config", dict) < 0) {
    3086                 :          0 :         goto error;
    3087                 :            :     }
    3088         [ #  # ]:          0 :     Py_CLEAR(dict);
    3089                 :            : 
    3090                 :            :     /* core config */
    3091                 :          0 :     const PyConfig *config = _PyInterpreterState_GetConfig(interp);
    3092                 :          0 :     dict = _PyConfig_AsDict(config);
    3093         [ #  # ]:          0 :     if (dict == NULL) {
    3094                 :          0 :         goto error;
    3095                 :            :     }
    3096         [ #  # ]:          0 :     if (PyDict_SetItemString(result, "config", dict) < 0) {
    3097                 :          0 :         goto error;
    3098                 :            :     }
    3099         [ #  # ]:          0 :     Py_CLEAR(dict);
    3100                 :            : 
    3101                 :          0 :     return result;
    3102                 :            : 
    3103                 :          0 : error:
    3104                 :          0 :     Py_XDECREF(result);
    3105                 :          0 :     Py_XDECREF(dict);
    3106                 :          0 :     return NULL;
    3107                 :            : }
    3108                 :            : 
    3109                 :            : 
    3110                 :            : static void
    3111                 :          0 : init_dump_ascii_wstr(const wchar_t *str)
    3112                 :            : {
    3113         [ #  # ]:          0 :     if (str == NULL) {
    3114                 :          0 :         PySys_WriteStderr("(not set)");
    3115                 :          0 :         return;
    3116                 :            :     }
    3117                 :            : 
    3118                 :          0 :     PySys_WriteStderr("'");
    3119         [ #  # ]:          0 :     for (; *str != L'\0'; str++) {
    3120                 :          0 :         unsigned int ch = (unsigned int)*str;
    3121         [ #  # ]:          0 :         if (ch == L'\'') {
    3122                 :          0 :             PySys_WriteStderr("\\'");
    3123   [ #  #  #  # ]:          0 :         } else if (0x20 <= ch && ch < 0x7f) {
    3124                 :          0 :             PySys_WriteStderr("%c", ch);
    3125                 :            :         }
    3126         [ #  # ]:          0 :         else if (ch <= 0xff) {
    3127                 :          0 :             PySys_WriteStderr("\\x%02x", ch);
    3128                 :            :         }
    3129                 :            : #if SIZEOF_WCHAR_T > 2
    3130         [ #  # ]:          0 :         else if (ch > 0xffff) {
    3131                 :          0 :             PySys_WriteStderr("\\U%08x", ch);
    3132                 :            :         }
    3133                 :            : #endif
    3134                 :            :         else {
    3135                 :          0 :             PySys_WriteStderr("\\u%04x", ch);
    3136                 :            :         }
    3137                 :            :     }
    3138                 :          0 :     PySys_WriteStderr("'");
    3139                 :            : }
    3140                 :            : 
    3141                 :            : 
    3142                 :            : /* Dump the Python path configuration into sys.stderr */
    3143                 :            : void
    3144                 :          0 : _Py_DumpPathConfig(PyThreadState *tstate)
    3145                 :            : {
    3146                 :          0 :     PyObject *exc = _PyErr_GetRaisedException(tstate);
    3147                 :            : 
    3148                 :          0 :     PySys_WriteStderr("Python path configuration:\n");
    3149                 :            : 
    3150                 :            : #define DUMP_CONFIG(NAME, FIELD) \
    3151                 :            :         do { \
    3152                 :            :             PySys_WriteStderr("  " NAME " = "); \
    3153                 :            :             init_dump_ascii_wstr(config->FIELD); \
    3154                 :            :             PySys_WriteStderr("\n"); \
    3155                 :            :         } while (0)
    3156                 :            : 
    3157                 :          0 :     const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
    3158                 :          0 :     DUMP_CONFIG("PYTHONHOME", home);
    3159                 :          0 :     DUMP_CONFIG("PYTHONPATH", pythonpath_env);
    3160                 :          0 :     DUMP_CONFIG("program name", program_name);
    3161                 :          0 :     PySys_WriteStderr("  isolated = %i\n", config->isolated);
    3162                 :          0 :     PySys_WriteStderr("  environment = %i\n", config->use_environment);
    3163                 :          0 :     PySys_WriteStderr("  user site = %i\n", config->user_site_directory);
    3164                 :          0 :     PySys_WriteStderr("  safe_path = %i\n", config->safe_path);
    3165                 :          0 :     PySys_WriteStderr("  import site = %i\n", config->site_import);
    3166                 :          0 :     PySys_WriteStderr("  is in build tree = %i\n", config->_is_python_build);
    3167                 :          0 :     DUMP_CONFIG("stdlib dir", stdlib_dir);
    3168                 :            : #undef DUMP_CONFIG
    3169                 :            : 
    3170                 :            : #define DUMP_SYS(NAME) \
    3171                 :            :         do { \
    3172                 :            :             obj = PySys_GetObject(#NAME); \
    3173                 :            :             PySys_FormatStderr("  sys.%s = ", #NAME); \
    3174                 :            :             if (obj != NULL) { \
    3175                 :            :                 PySys_FormatStderr("%A", obj); \
    3176                 :            :             } \
    3177                 :            :             else { \
    3178                 :            :                 PySys_WriteStderr("(not set)"); \
    3179                 :            :             } \
    3180                 :            :             PySys_FormatStderr("\n"); \
    3181                 :            :         } while (0)
    3182                 :            : 
    3183                 :            :     PyObject *obj;
    3184         [ #  # ]:          0 :     DUMP_SYS(_base_executable);
    3185         [ #  # ]:          0 :     DUMP_SYS(base_prefix);
    3186         [ #  # ]:          0 :     DUMP_SYS(base_exec_prefix);
    3187         [ #  # ]:          0 :     DUMP_SYS(platlibdir);
    3188         [ #  # ]:          0 :     DUMP_SYS(executable);
    3189         [ #  # ]:          0 :     DUMP_SYS(prefix);
    3190         [ #  # ]:          0 :     DUMP_SYS(exec_prefix);
    3191                 :            : #undef DUMP_SYS
    3192                 :            : 
    3193                 :          0 :     PyObject *sys_path = PySys_GetObject("path");  /* borrowed reference */
    3194   [ #  #  #  # ]:          0 :     if (sys_path != NULL && PyList_Check(sys_path)) {
    3195                 :          0 :         PySys_WriteStderr("  sys.path = [\n");
    3196                 :          0 :         Py_ssize_t len = PyList_GET_SIZE(sys_path);
    3197         [ #  # ]:          0 :         for (Py_ssize_t i=0; i < len; i++) {
    3198                 :          0 :             PyObject *path = PyList_GET_ITEM(sys_path, i);
    3199                 :          0 :             PySys_FormatStderr("    %A,\n", path);
    3200                 :            :         }
    3201                 :          0 :         PySys_WriteStderr("  ]\n");
    3202                 :            :     }
    3203                 :            : 
    3204                 :          0 :     _PyErr_SetRaisedException(tstate, exc);
    3205                 :          0 : }

Generated by: LCOV version 1.14