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