Coverage Report

Created: 2022-07-08 09:39

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