LCOV - code coverage report
Current view: top level - Python - initconfig.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 1219 1437 84.8 %
Date: 2022-07-07 18:19:46 Functions: 79 87 90.8 %

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

Generated by: LCOV version 1.14