Coverage Report

Created: 2026-07-14 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Python/initconfig.c
Line
Count
Source
1
#include "Python.h"
2
#include "pycore_fileutils.h"     // _Py_HasFileSystemDefaultEncodeErrors
3
#include "pycore_getopt.h"        // _PyOS_GetOpt()
4
#include "pycore_initconfig.h"    // _PyStatus_OK()
5
#include "pycore_interp.h"        // _PyInterpreterState.runtime
6
#include "pycore_long.h"          // _PY_LONG_MAX_STR_DIGITS_THRESHOLD
7
#include "pycore_pathconfig.h"    // _Py_path_config
8
#include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
9
#include "pycore_pylifecycle.h"   // _Py_PreInitializeFromConfig()
10
#include "pycore_pymem.h"         // _PyMem_DefaultRawMalloc()
11
#include "pycore_pyhash.h"        // _Py_HashSecret
12
#include "pycore_pystate.h"       // _PyThreadState_GET()
13
#include "pycore_pystats.h"       // _Py_StatsOn()
14
#include "pycore_sysmodule.h"     // _PySys_SetIntMaxStrDigits()
15
16
#include "osdefs.h"               // DELIM
17
18
#include <locale.h>               // setlocale()
19
#include <stdlib.h>               // getenv()
20
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
21
#  ifdef HAVE_IO_H
22
#    include <io.h>
23
#  endif
24
#  ifdef HAVE_FCNTL_H
25
#    include <fcntl.h>            // O_BINARY
26
#  endif
27
#endif
28
29
#ifdef __APPLE__
30
/* Enable system log by default on non-macOS Apple platforms */
31
#  if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
32
#define USE_SYSTEM_LOGGER_DEFAULT 1;
33
#  else
34
#define USE_SYSTEM_LOGGER_DEFAULT 0;
35
#  endif
36
#endif
37
38
#include "config_common.h"
39
40
/* --- PyConfig setters ------------------------------------------- */
41
42
typedef PyObject* (*config_sys_flag_setter) (int value);
43
44
static PyObject*
45
config_sys_flag_long(int value)
46
0
{
47
0
    return PyLong_FromLong(value);
48
0
}
49
50
static PyObject*
51
config_sys_flag_not(int value)
52
0
{
53
0
    value = (!value);
54
0
    return config_sys_flag_long(value);
55
0
}
56
57
/* --- PyConfig spec ---------------------------------------------- */
58
59
typedef enum {
60
    PyConfig_MEMBER_INT = 0,
61
    PyConfig_MEMBER_UINT = 1,
62
    PyConfig_MEMBER_ULONG = 2,
63
    PyConfig_MEMBER_BOOL = 3,
64
65
    PyConfig_MEMBER_WSTR = 10,
66
    PyConfig_MEMBER_WSTR_OPT = 11,
67
    PyConfig_MEMBER_WSTR_LIST = 12,
68
} PyConfigMemberType;
69
70
typedef enum {
71
    // Option which cannot be get or set by PyConfig_Get() and PyConfig_Set()
72
    PyConfig_MEMBER_INIT_ONLY = 0,
73
74
    // Option which cannot be set by PyConfig_Set()
75
    PyConfig_MEMBER_READ_ONLY = 1,
76
77
    // Public option: can be get and set by PyConfig_Get() and PyConfig_Set()
78
    PyConfig_MEMBER_PUBLIC = 2,
79
} PyConfigMemberVisibility;
80
81
typedef struct {
82
    const char *attr;
83
    int flag_index;
84
    config_sys_flag_setter flag_setter;
85
} PyConfigSysSpec;
86
87
typedef struct {
88
    int *ptr;
89
    int not;
90
} PyConfigGlobalVar;
91
92
typedef struct {
93
    const char *name;
94
    size_t offset;
95
    PyConfigMemberType type;
96
    PyConfigMemberVisibility visibility;
97
    PyConfigSysSpec sys;
98
    PyConfigGlobalVar global_var;
99
} PyConfigSpec;
100
101
#define SPEC(MEMBER, TYPE, VISIBILITY, sys, global_var) \
102
    {#MEMBER, offsetof(PyConfig, MEMBER), \
103
     PyConfig_MEMBER_##TYPE, PyConfig_MEMBER_##VISIBILITY, sys, global_var}
104
105
#define SYS_ATTR(name) {name, -1, NULL}
106
#define SYS_FLAG_SETTER(index, setter) {NULL, index, setter}
107
#define SYS_FLAG(index) SYS_FLAG_SETTER(index, NULL)
108
#define NO_SYS SYS_ATTR(NULL)
109
110
#define GLOBAL(ptr, not) {ptr, not}
111
#define NO_GLOBAL GLOBAL(NULL, 0)
112
113
// Ignore deprecations on global variables such as Py_IsolatedFlag
114
_Py_COMP_DIAG_PUSH
115
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
116
117
// Update _test_embed_set_config when adding new members
118
static const PyConfigSpec PYCONFIG_SPEC[] = {
119
    // --- Public options -----------
120
121
    SPEC(argv, WSTR_LIST, PUBLIC, SYS_ATTR("argv"), NO_GLOBAL),
122
    SPEC(base_exec_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("base_exec_prefix"), NO_GLOBAL),
123
    SPEC(base_executable, WSTR_OPT, PUBLIC, SYS_ATTR("_base_executable"), NO_GLOBAL),
124
    SPEC(base_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("base_prefix"), NO_GLOBAL),
125
    SPEC(bytes_warning, UINT, PUBLIC, SYS_FLAG(9), GLOBAL(&Py_BytesWarningFlag, 0)),
126
    SPEC(cpu_count, INT, PUBLIC, NO_SYS, NO_GLOBAL),
127
    SPEC(lazy_imports, INT, PUBLIC, NO_SYS, NO_GLOBAL),
128
    SPEC(exec_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("exec_prefix"), NO_GLOBAL),
129
    SPEC(executable, WSTR_OPT, PUBLIC, SYS_ATTR("executable"), NO_GLOBAL),
130
    SPEC(inspect, BOOL, PUBLIC, SYS_FLAG(1), GLOBAL(&Py_InspectFlag, 0)),
131
    SPEC(int_max_str_digits, UINT, PUBLIC, NO_SYS, NO_GLOBAL),
132
    SPEC(interactive, BOOL, PUBLIC, SYS_FLAG(2), GLOBAL(&Py_InteractiveFlag, 0)),
133
    SPEC(module_search_paths, WSTR_LIST, PUBLIC, SYS_ATTR("path"), NO_GLOBAL),
134
    SPEC(optimization_level, UINT, PUBLIC, SYS_FLAG(3), GLOBAL(&Py_OptimizeFlag, 0)),
135
    SPEC(parser_debug, BOOL, PUBLIC, SYS_FLAG(0), GLOBAL(&Py_DebugFlag, 0)),
136
    SPEC(platlibdir, WSTR, PUBLIC, SYS_ATTR("platlibdir"), NO_GLOBAL),
137
    SPEC(prefix, WSTR_OPT, PUBLIC, SYS_ATTR("prefix"), NO_GLOBAL),
138
    SPEC(pycache_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("pycache_prefix"), NO_GLOBAL),
139
    SPEC(quiet, BOOL, PUBLIC, SYS_FLAG(10), GLOBAL(&Py_QuietFlag, 0)),
140
    SPEC(stdlib_dir, WSTR_OPT, PUBLIC, SYS_ATTR("_stdlib_dir"), NO_GLOBAL),
141
    SPEC(use_environment, BOOL, PUBLIC,
142
         SYS_FLAG_SETTER(7, config_sys_flag_not), GLOBAL(&Py_IgnoreEnvironmentFlag, 1)),
143
    SPEC(verbose, UINT, PUBLIC, SYS_FLAG(8), GLOBAL(&Py_VerboseFlag, 0)),
144
    SPEC(warnoptions, WSTR_LIST, PUBLIC, SYS_ATTR("warnoptions"), NO_GLOBAL),
145
    SPEC(write_bytecode, BOOL, PUBLIC, SYS_FLAG_SETTER(4, config_sys_flag_not),
146
         GLOBAL(&Py_DontWriteBytecodeFlag, 1)),
147
    SPEC(xoptions, WSTR_LIST, PUBLIC, SYS_ATTR("_xoptions"), NO_GLOBAL),
148
149
    // --- Read-only options -----------
150
151
#ifdef Py_STATS
152
    SPEC(_pystats, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
153
#endif
154
    SPEC(buffered_stdio, BOOL, READ_ONLY, NO_SYS,
155
         GLOBAL(&Py_UnbufferedStdioFlag, 1)),
156
    SPEC(check_hash_pycs_mode, WSTR, READ_ONLY, NO_SYS, NO_GLOBAL),
157
    SPEC(code_debug_ranges, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
158
    SPEC(configure_c_stdio, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
159
    SPEC(dev_mode, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),  // sys.flags.dev_mode
160
    SPEC(dump_refs, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
161
    SPEC(dump_refs_file, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL),
162
#ifdef Py_GIL_DISABLED
163
    SPEC(enable_gil, INT, READ_ONLY, NO_SYS, NO_GLOBAL),
164
    SPEC(tlbc_enabled, INT, READ_ONLY, NO_SYS, NO_GLOBAL),
165
#endif
166
    SPEC(faulthandler, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
167
    SPEC(filesystem_encoding, WSTR, READ_ONLY, NO_SYS, NO_GLOBAL),
168
    SPEC(filesystem_errors, WSTR, READ_ONLY, NO_SYS, NO_GLOBAL),
169
    SPEC(hash_seed, ULONG, READ_ONLY, NO_SYS, NO_GLOBAL),
170
    SPEC(home, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL),
171
    SPEC(thread_inherit_context, INT, READ_ONLY, NO_SYS, NO_GLOBAL),
172
    SPEC(context_aware_warnings, INT, READ_ONLY, NO_SYS, NO_GLOBAL),
173
    SPEC(import_time, UINT, READ_ONLY, NO_SYS, NO_GLOBAL),
174
    SPEC(install_signal_handlers, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
175
    SPEC(isolated, BOOL, READ_ONLY, NO_SYS, GLOBAL(&Py_IsolatedFlag, 0)),  // sys.flags.isolated
176
#ifdef MS_WINDOWS
177
    SPEC(legacy_windows_stdio, BOOL, READ_ONLY, NO_SYS,
178
         GLOBAL(&Py_LegacyWindowsStdioFlag, 0)),
179
#endif
180
    SPEC(malloc_stats, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
181
    SPEC(pymalloc_hugepages, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
182
    SPEC(orig_argv, WSTR_LIST, READ_ONLY, SYS_ATTR("orig_argv"), NO_GLOBAL),
183
    SPEC(parse_argv, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
184
    SPEC(pathconfig_warnings, BOOL, READ_ONLY, NO_SYS,
185
         GLOBAL(&Py_FrozenFlag, 1)),
186
    SPEC(perf_profiling, UINT, READ_ONLY, NO_SYS, NO_GLOBAL),
187
    SPEC(remote_debug, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
188
    SPEC(program_name, WSTR, READ_ONLY, NO_SYS, NO_GLOBAL),
189
    SPEC(run_command, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL),
190
    SPEC(run_filename, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL),
191
    SPEC(run_module, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL),
192
#ifdef Py_DEBUG
193
    SPEC(run_presite, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL),
194
#endif
195
    SPEC(safe_path, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
196
    SPEC(show_ref_count, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
197
    SPEC(site_import, BOOL, READ_ONLY, NO_SYS, GLOBAL(&Py_NoSiteFlag, 1)),  // sys.flags.no_site
198
    SPEC(skip_source_first_line, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
199
    SPEC(stdio_encoding, WSTR, READ_ONLY, NO_SYS, NO_GLOBAL),
200
    SPEC(stdio_errors, WSTR, READ_ONLY, NO_SYS, NO_GLOBAL),
201
    SPEC(tracemalloc, UINT, READ_ONLY, NO_SYS, NO_GLOBAL),
202
    SPEC(use_frozen_modules, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
203
    SPEC(use_hash_seed, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
204
#ifdef __APPLE__
205
    SPEC(use_system_logger, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
206
#endif
207
    SPEC(user_site_directory, BOOL, READ_ONLY, NO_SYS,
208
         GLOBAL(&Py_NoUserSiteDirectory, 1)),  // sys.flags.no_user_site
209
    SPEC(warn_default_encoding, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL),
210
211
    // --- Init-only options -----------
212
213
    SPEC(_config_init, UINT, INIT_ONLY, NO_SYS, NO_GLOBAL),
214
    SPEC(_init_main, BOOL, INIT_ONLY, NO_SYS, NO_GLOBAL),
215
    SPEC(_install_importlib, BOOL, INIT_ONLY, NO_SYS, NO_GLOBAL),
216
    SPEC(_is_python_build, BOOL, INIT_ONLY, NO_SYS, NO_GLOBAL),
217
    SPEC(module_search_paths_set, BOOL, INIT_ONLY, NO_SYS, NO_GLOBAL),
218
    SPEC(pythonpath_env, WSTR_OPT, INIT_ONLY, NO_SYS, NO_GLOBAL),
219
    SPEC(sys_path_0, WSTR_OPT, INIT_ONLY, NO_SYS, NO_GLOBAL),
220
221
    // Array terminator
222
    {NULL, 0, 0, 0, NO_SYS},
223
};
224
225
#undef SPEC
226
#define SPEC(MEMBER, TYPE, VISIBILITY) \
227
    {#MEMBER, offsetof(PyPreConfig, MEMBER), PyConfig_MEMBER_##TYPE, \
228
     PyConfig_MEMBER_##VISIBILITY, NO_SYS}
229
230
static const PyConfigSpec PYPRECONFIG_SPEC[] = {
231
    // --- Read-only options -----------
232
233
    SPEC(allocator, INT, READ_ONLY),
234
    SPEC(coerce_c_locale, BOOL, READ_ONLY),
235
    SPEC(coerce_c_locale_warn, BOOL, READ_ONLY),
236
    SPEC(configure_locale, BOOL, READ_ONLY),
237
#ifdef MS_WINDOWS
238
    SPEC(legacy_windows_fs_encoding, BOOL, READ_ONLY),
239
#endif
240
    SPEC(utf8_mode, BOOL, READ_ONLY),
241
242
    // --- Init-only options -----------
243
    // Members already present in PYCONFIG_SPEC
244
245
    SPEC(_config_init, INT, INIT_ONLY),
246
    SPEC(dev_mode, BOOL, INIT_ONLY),
247
    SPEC(isolated, BOOL, INIT_ONLY),
248
    SPEC(parse_argv, BOOL, INIT_ONLY),
249
    SPEC(use_environment, BOOL, INIT_ONLY),
250
251
    // Array terminator
252
    {NULL, 0, 0, 0, NO_SYS},
253
};
254
255
// End of ignoring deprecations on global variables
256
_Py_COMP_DIAG_POP
257
258
#undef SPEC
259
#undef SYS_ATTR
260
#undef SYS_FLAG_SETTER
261
#undef SYS_FLAG
262
#undef NO_SYS
263
#undef GLOBAL
264
#undef NO_GLOBAL
265
266
267
// Forward declarations
268
static PyObject* config_get(const PyConfig *config, const PyConfigSpec *spec,
269
                            int use_sys);
270
static void initconfig_free_wstr(wchar_t *member);
271
static void initconfig_free_wstr_list(PyWideStringList *list);
272
static void initconfig_free_config(const PyConfig *config);
273
274
275
/* --- Command line options --------------------------------------- */
276
277
/*
278
 * Help text markup (matching Lib/_colorize.py Argparse theme).
279
 *
280
 * Color spans, #X{...}  where "}" resets to default color:
281
 *   #b{...}  label              bold yellow
282
 *   #B{...}  summary label      yellow
283
 *   #E{...}  env var (primary)  bold cyan
284
 *   #e{...}  env var reference  cyan
285
 *   #h{...}  heading            bold blue
286
 *   #L{...}  long option        bold cyan
287
 *   #s{...}  short option       bold green
288
 *   #S{...}  summary short opt  green
289
 *
290
 * Runtime substitutions (no "{" follows):
291
 *   #P  program name (bold magenta)
292
 *   #D  path separator (DELIM)
293
 *   #H  PYTHONHOMEHELP default search path
294
 *
295
 * fprint_help() walks the string, expanding color codes only when colorize=1
296
 * and substituting runtime values regardless.
297
 */
298
299
#if defined(MS_WINDOWS)
300
#  define PYTHONHOMEHELP "<prefix>\\python{major}{minor}"
301
#else
302
0
#  define PYTHONHOMEHELP "<prefix>/lib/pythonX.X"
303
#endif
304
305
/* Determine if we can emit ANSI color codes on the given stream.
306
 * Logic mirrors Lib/_colorize.py:can_colorize(). */
307
static int
308
_Py_can_colorize(FILE *f)
309
0
{
310
0
    const char *env;
311
312
0
    env = Py_GETENV("PYTHON_COLORS");
313
0
    if (env) {
314
0
        if (strcmp(env, "0") == 0) {
315
0
            return 0;
316
0
        }
317
0
        if (strcmp(env, "1") == 0) {
318
0
            return 1;
319
0
        }
320
0
    }
321
0
    if (getenv("NO_COLOR")) {
322
0
        return 0;
323
0
    }
324
0
    if (getenv("FORCE_COLOR")) {
325
0
        return 1;
326
0
    }
327
0
    env = getenv("TERM");
328
0
    if (env && strcmp(env, "dumb") == 0) {
329
0
        return 0;
330
0
    }
331
#if defined(MS_WINDOWS) && defined(HAVE_WINDOWS_CONSOLE_IO)
332
    {
333
        DWORD mode = 0;
334
        DWORD nStdHandle = (f == stderr) ? STD_ERROR_HANDLE
335
                                         : STD_OUTPUT_HANDLE;
336
        HANDLE handle = GetStdHandle(nStdHandle);
337
        if (!GetConsoleMode(handle, &mode)
338
            || !(mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING))
339
        {
340
            return 0;
341
        }
342
    }
343
#endif
344
0
    return isatty(fileno(f));
345
0
}
346
347
/* Walk help text, expanding markup:
348
 *   #X{...}  color span (only emitted when colorize=1; '}' resets).
349
 *   #X       runtime substitution (program name, DELIM, PYTHONHOMEHELP).
350
 * See the markup table above the macro/comment block. */
351
static void
352
fprint_help(FILE *f, const char *text, int colorize, const wchar_t *program)
353
0
{
354
0
    for (const char *p = text; *p; ) {
355
0
        if (*p == '#' && p[1]) {
356
0
            char code = p[1];
357
0
            if (p[2] == '{') {
358
                /* Color span open */
359
0
                const char *seq = NULL;
360
0
                switch (code) {
361
0
                case 'h': seq = "\x1b[1;34m"; break;  // heading
362
0
                case 'E': seq = "\x1b[1;36m"; break;  // env var primary
363
0
                case 'e': seq = "\x1b[36m";   break;  // env var reference
364
0
                case 'L': seq = "\x1b[1;36m"; break;  // long option
365
0
                case 'b': seq = "\x1b[1;33m"; break;  // label
366
0
                case 'B': seq = "\x1b[33m";   break;  // summary label
367
0
                case 's': seq = "\x1b[1;32m"; break;  // short option
368
0
                case 'S': seq = "\x1b[32m";   break;  // summary short option
369
0
                }
370
0
                if (colorize && seq) fputs(seq, f);
371
0
                p += 3;  // skip "#X{"
372
0
                continue;
373
0
            }
374
            /* Runtime substitution */
375
0
            switch (code) {
376
0
            case 'P':  // program name with bold magenta
377
0
                if (colorize) fputs("\x1b[1;35m", f);
378
0
                if (program) fprintf(f, "%ls", program);
379
0
                if (colorize) fputs("\x1b[0m", f);
380
0
                break;
381
0
            case 'D':
382
0
                fputc((char)DELIM, f);
383
0
                break;
384
0
            case 'H':
385
0
                fputs(PYTHONHOMEHELP, f);
386
0
                break;
387
0
            default:  // unknown: emit literally
388
0
                fputc('#', f);
389
0
                fputc(code, f);
390
0
                break;
391
0
            }
392
0
            p += 2;  // skip "#X"
393
0
            continue;
394
0
        }
395
0
        if (*p == '}') {
396
0
            if (colorize) fputs("\x1b[0m", f);
397
0
            p++;
398
0
            continue;
399
0
        }
400
0
        fputc(*p++, f);
401
0
    }
402
0
}
403
404
/* Short usage message */
405
static const char usage_line[] =
406
"#h{usage:} #P [#S{option}] #S{...} "
407
"[#S{-c} #B{cmd} | #S{-m} #B{mod} | #S{file} | #S{-}] "
408
"[#S{arg}] #S{...}\n"
409
;
410
411
/* Long help message */
412
/* Lines sorted by option name; keep in sync with usage_envvars* below */
413
static const char usage_help[] =
414
"#h{Options (and corresponding environment variables):}\n"
415
"#s{-b}     : issue warnings about converting bytes/bytearray to str and comparing\n"
416
"         bytes/bytearray with str or bytes with int. (#S{-bb}: issue errors)\n"
417
"         deprecated since 3.15 and will become no-op in 3.17.\n"
418
"#s{-B}     : don't write .pyc files on import; also #e{PYTHONDONTWRITEBYTECODE}#B{=x}\n"
419
"#s{-c} #b{cmd} : program passed in as string (terminates option list)\n"
420
"#s{-d}     : turn on parser debugging output (for experts only, only works on\n"
421
"         debug builds); also #e{PYTHONDEBUG}#B{=x}\n"
422
"#s{-E}     : ignore #e{PYTHON*} environment variables (such as #e{PYTHONPATH})\n"
423
"#s{-h}     : print this help message and exit (also #S{-?} or #e{--help})\n"
424
"#s{-i}     : inspect interactively after running script; forces a prompt even\n"
425
"         if stdin does not appear to be a terminal; also #e{PYTHONINSPECT}#B{=x}\n"
426
"#s{-I}     : isolate Python from the user's environment (implies #S{-E}, #S{-P} and #S{-s})\n"
427
"#s{-m} #b{mod} : run library module as a script (terminates option list)\n"
428
"#s{-O}     : remove assert and __debug__-dependent statements; add .opt-1 before\n"
429
"         .pyc extension; also #e{PYTHONOPTIMIZE}#B{=x}\n"
430
"#s{-OO}    : do #S{-O} changes and also discard docstrings; add .opt-2 before\n"
431
"         .pyc extension\n"
432
"#s{-P}     : don't prepend a potentially unsafe path to sys.path; also\n"
433
"         #e{PYTHONSAFEPATH}\n"
434
"#s{-q}     : don't print version and copyright messages on interactive startup\n"
435
"#s{-s}     : don't add user site directory to sys.path; also #e{PYTHONNOUSERSITE}#B{=x}\n"
436
"#s{-S}     : don't imply 'import site' on initialization\n"
437
"#s{-u}     : force the stdout and stderr streams to be unbuffered;\n"
438
"         this option has no effect on stdin; also #e{PYTHONUNBUFFERED}#B{=x}\n"
439
"#s{-v}     : verbose (trace import statements); also #e{PYTHONVERBOSE}#B{=x}\n"
440
"         can be supplied multiple times to increase verbosity\n"
441
"#s{-V}     : print the Python version number and exit (also #e{--version})\n"
442
"         when given twice, print more information about the build\n"
443
"#s{-W} #b{arg} : warning control; #B{arg} is action:message:category:module:lineno\n"
444
"         also #e{PYTHONWARNINGS}#B{=arg}\n"
445
"#s{-x}     : skip first line of source, allowing use of non-Unix forms of #!cmd\n"
446
"#s{-X} #b{opt} : set implementation-specific option\n"
447
"#L{--check-hash-based-pycs} #b{always|default|never}:\n"
448
"         control how Python invalidates hash-based .pyc files\n"
449
"#L{--help-env}: print help about Python environment variables and exit\n"
450
"#L{--help-xoptions}: print help about implementation-specific #S{-X} options and exit\n"
451
"#L{--help-all}: print complete help information and exit\n"
452
"\n"
453
"#h{Arguments:}\n"
454
"#s{file}   : program read from script file\n"
455
"#s{-}      : program read from stdin (default; interactive mode if a tty)\n"
456
"#s{arg} #b{...}: arguments passed to program in sys.argv[1:]\n"
457
;
458
459
static const char usage_xoptions[] =
460
"#h{The following implementation-specific options are available:}\n"
461
"#s{-X} #L{context_aware_warnings}#b{=[0|1]}: if true (#B{1}) then the warnings module will\n"
462
"         use a context variables; if false (#B{0}) then the warnings module will\n"
463
"         use module globals, which is not concurrent-safe; set to true for\n"
464
"         free-threaded builds and false otherwise; also\n"
465
"         #e{PYTHON_CONTEXT_AWARE_WARNINGS}\n"
466
"#s{-X} #L{cpu_count}#b{=N}: override the return value of os.cpu_count();\n"
467
"         #S{-X} #e{cpu_count}#B{=default} cancels overriding; also #e{PYTHON_CPU_COUNT}\n"
468
"#s{-X} #L{dev} : enable Python Development Mode; also #e{PYTHONDEVMODE}\n"
469
"#s{-X} #L{disable-remote-debug}: disable remote debugging; also #e{PYTHON_DISABLE_REMOTE_DEBUG}\n"
470
"#s{-X} #L{faulthandler}: dump the Python traceback on fatal errors;\n"
471
"         also #e{PYTHONFAULTHANDLER}\n"
472
"#s{-X} #L{frozen_modules}#b{=[on|off]}: whether to use frozen modules; the default is \"#B{on}\"\n"
473
"         for installed Python and \"#B{off}\" for a local build;\n"
474
"         also #e{PYTHON_FROZEN_MODULES}\n"
475
#ifdef Py_GIL_DISABLED
476
"#s{-X} #L{gil}#b{=[0|1]}: enable (#B{1}) or disable (#B{0}) the GIL; also #e{PYTHON_GIL}\n"
477
#endif
478
"#s{-X} #L{importtime}#b{[=2]}: show how long each import takes; use #S{-X} #e{importtime}#B{=2} to\n"
479
"         log imports of already-loaded modules; also #e{PYTHONPROFILEIMPORTTIME}\n"
480
"#s{-X} #L{int_max_str_digits}#b{=N}: limit the size of int<->str conversions;\n"
481
"         0 disables the limit; also #e{PYTHONINTMAXSTRDIGITS}\n"
482
"#s{-X} #L{lazy_imports}#b{=[all|normal]}: control global lazy imports;\n"
483
"         default is #B{normal}; also #e{PYTHON_LAZY_IMPORTS}\n"
484
"#s{-X} #L{no_debug_ranges}: don't include extra location information in code objects;\n"
485
"         also #e{PYTHONNODEBUGRANGES}\n"
486
"#s{-X} #L{pathconfig_warnings}#b{=[0|1]}: if true (#B{1}) then path configuration is allowed\n"
487
"         to log warnings into stderr; if false (#B{0}) suppress these warnings;\n"
488
"         set to true by default; also #e{PYTHON_PATHCONFIG_WARNINGS}\n"
489
"#s{-X} #L{perf}: support the Linux \"perf\" profiler; also #e{PYTHONPERFSUPPORT}#B{=1}\n"
490
"#s{-X} #L{perf_jit}: support the Linux \"perf\" profiler with DWARF support;\n"
491
"         also #e{PYTHON_PERF_JIT_SUPPORT}#B{=1}\n"
492
#ifdef Py_DEBUG
493
"#s{-X} #L{presite}#b{=MOD}: import this module before site; also #e{PYTHON_PRESITE}\n"
494
#endif
495
"#s{-X} #L{pycache_prefix}#b{=PATH}: write .pyc files to a parallel tree instead of to the\n"
496
"         code tree; also #e{PYTHONPYCACHEPREFIX}\n"
497
#ifdef Py_STATS
498
"#s{-X} #L{pystats}: enable pystats collection at startup; also #e{PYTHONSTATS}\n"
499
#endif
500
"#s{-X} #L{showrefcount}: output the total reference count and number of used\n"
501
"         memory blocks when the program finishes or after each statement in\n"
502
"         the interactive interpreter; only works on debug builds\n"
503
"#s{-X} #L{thread_inherit_context}#b{=[0|1]}: enable (#B{1}) or disable (#B{0}) threads inheriting\n"
504
"         context vars by default; enabled by default in the free-threaded\n"
505
"         build and disabled otherwise; also #e{PYTHON_THREAD_INHERIT_CONTEXT}\n"
506
#ifdef Py_GIL_DISABLED
507
"#s{-X} #L{tlbc}#b{=[0|1]}: enable (#B{1}) or disable (#B{0}) thread-local bytecode. Also\n"
508
"         #e{PYTHON_TLBC}\n"
509
#endif
510
"#s{-X} #L{tracemalloc}#b{[=N]}: trace Python memory allocations; N sets a traceback limit\n"
511
"         of #B{N} frames (default: #B{1}); also #e{PYTHONTRACEMALLOC}#B{=N}\n"
512
"#s{-X} #L{utf8}#b{[=0|1]}: enable (#B{1}) or disable (#B{0}) UTF-8 mode; also #e{PYTHONUTF8}\n"
513
"#s{-X} #L{warn_default_encoding}: enable opt-in EncodingWarning for 'encoding=None';\n"
514
"         also #e{PYTHONWARNDEFAULTENCODING}\n"
515
;
516
517
/* Envvars that don't have equivalent command-line options are listed first */
518
static const char usage_envvars[] =
519
"#h{Environment variables that change behavior:}\n"
520
"#E{PYTHONASYNCIODEBUG}: enable asyncio debug mode\n"
521
"#E{PYTHON_BASIC_REPL}: use the traditional parser-based REPL\n"
522
"#E{PYTHONBREAKPOINT}: if this variable is set to #B{0}, it disables the default\n"
523
"                  debugger.  It can be set to the callable of your debugger of\n"
524
"                  choice.\n"
525
"#E{PYTHONCASEOK}    : ignore case in 'import' statements (Windows)\n"
526
"#E{PYTHONCOERCECLOCALE}: if this variable is set to #B{0}, it disables the locale\n"
527
"                  coercion behavior.  Use #e{PYTHONCOERCECLOCALE}#B{=warn} to request\n"
528
"                  display of locale coercion and locale compatibility warnings\n"
529
"                  on stderr.\n"
530
"#E{PYTHON_COLORS}   : if this variable is set to #B{1}, the interpreter will colorize\n"
531
"                  various kinds of output.  Setting it to #B{0} deactivates\n"
532
"                  this behavior.\n"
533
#ifdef Py_TRACE_REFS
534
"#E{PYTHONDUMPREFS}  : dump objects and reference counts still alive after shutdown\n"
535
"#E{PYTHONDUMPREFSFILE}: dump objects and reference counts to the specified file\n"
536
#endif
537
#ifdef __APPLE__
538
"#E{PYTHONEXECUTABLE}: set sys.argv[0] to this value (macOS only)\n"
539
#endif
540
"#E{PYTHONHASHSEED}  : if this variable is set to 'random', a random value is used\n"
541
"                  to seed the hashes of str and bytes objects.  It can also be\n"
542
"                  set to an integer in the range [0,4294967295] to get hash\n"
543
"                  values with a predictable seed.\n"
544
"#E{PYTHON_HISTORY}  : the location of a .python_history file.\n"
545
"#E{PYTHONHOME}      : alternate <prefix> directory (or <prefix>#D<exec_prefix>).\n"
546
"                  The default module search path uses #H.\n"
547
"#E{PYTHONIOENCODING}: encoding[:errors] used for stdin/stdout/stderr\n"
548
#ifdef MS_WINDOWS
549
"#E{PYTHONLEGACYWINDOWSFSENCODING}: use legacy \"mbcs\" encoding for file system\n"
550
"#E{PYTHONLEGACYWINDOWSSTDIO}: use legacy Windows stdio\n"
551
#endif
552
"#E{PYTHONMALLOC}    : set the Python memory allocators and/or install debug hooks\n"
553
"                  on Python memory allocators.  Use #e{PYTHONMALLOC}#B{=debug} to\n"
554
"                  install debug hooks.\n"
555
"#E{PYTHONMALLOCSTATS}: print memory allocator statistics\n"
556
"#E{PYTHONPATH}      : '#D'-separated list of directories prefixed to the\n"
557
"                  default module search path.  The result is sys.path.\n"
558
"#E{PYTHONPLATLIBDIR}: override sys.platlibdir\n"
559
"#E{PYTHONSTARTUP}   : file executed on interactive startup (no default)\n"
560
"#E{PYTHONUSERBASE}  : defines the user base directory (site.USER_BASE)\n"
561
"\n"
562
"#h{These variables have equivalent command-line options (see }#e{--help} for details):\n"
563
"#E{PYTHON_CONTEXT_AWARE_WARNINGS}: if true (#B{1}), enable thread-safe warnings\n"
564
"                  module behaviour (#S{-X} #e{context_aware_warnings})\n"
565
"#E{PYTHON_CPU_COUNT}: override the return value of os.cpu_count() (#S{-X} #e{cpu_count})\n"
566
"#E{PYTHONDEBUG}     : enable parser debug mode (#S{-d})\n"
567
"#E{PYTHONDEVMODE}   : enable Python Development Mode (#S{-X} #e{dev})\n"
568
"#E{PYTHONDONTWRITEBYTECODE}: don't write .pyc files (#S{-B})\n"
569
"#E{PYTHONFAULTHANDLER}: dump the Python traceback on fatal errors (#S{-X} #e{faulthandler})\n"
570
"#E{PYTHON_FROZEN_MODULES}: whether to use frozen modules; the default is \"#B{on}\"\n"
571
"                  for installed Python and \"#B{off}\" for a local build\n"
572
"                  (#S{-X} #e{frozen_modules})\n"
573
#ifdef Py_GIL_DISABLED
574
"#E{PYTHON_GIL}      : when set to #B{0}, disables the GIL (#S{-X} #e{gil})\n"
575
#endif
576
"#E{PYTHONINSPECT}   : inspect interactively after running script (#S{-i})\n"
577
"#E{PYTHONINTMAXSTRDIGITS}: limit the size of int<->str conversions;\n"
578
"                  0 disables the limit (#S{-X} #e{int_max_str_digits}#B{=N})\n"
579
"#E{PYTHON_LAZY_IMPORTS}: control global lazy imports (#S{-X} #e{lazy_imports})\n"
580
"#E{PYTHONNODEBUGRANGES}: don't include extra location information in code objects\n"
581
"                  (#S{-X} #e{no_debug_ranges})\n"
582
"#E{PYTHONNOUSERSITE}: disable user site directory (#S{-s})\n"
583
"#E{PYTHONOPTIMIZE}  : enable level 1 optimizations (#S{-O})\n"
584
"#E{PYTHON_PERF_JIT_SUPPORT}: enable Linux \"perf\" profiler support with JIT\n"
585
"                  (#S{-X} #e{perf_jit})\n"
586
"#E{PYTHONPERFSUPPORT}: support the Linux \"perf\" profiler (#S{-X} #e{perf})\n"
587
#ifdef Py_DEBUG
588
"#E{PYTHON_PRESITE}: import this module before site (#S{-X} #e{presite})\n"
589
#endif
590
"#E{PYTHONPROFILEIMPORTTIME}: show how long each import takes (#S{-X} #e{importtime})\n"
591
"#E{PYTHONPYCACHEPREFIX}: root directory for bytecode cache (pyc) files\n"
592
"                  (#S{-X} #e{pycache_prefix})\n"
593
"#E{PYTHONSAFEPATH}  : don't prepend a potentially unsafe path to sys.path.\n"
594
#ifdef Py_STATS
595
"#E{PYTHONSTATS}     : turns on statistics gathering (#S{-X} #e{pystats})\n"
596
#endif
597
"#E{PYTHON_THREAD_INHERIT_CONTEXT}: if true (#B{1}), threads inherit context vars\n"
598
"                  (#S{-X} #e{thread_inherit_context})\n"
599
#ifdef Py_GIL_DISABLED
600
"#E{PYTHON_TLBC}     : when set to #B{0}, disables thread-local bytecode (#S{-X} #e{tlbc})\n"
601
#endif
602
"#E{PYTHONTRACEMALLOC}: trace Python memory allocations (#S{-X} #e{tracemalloc})\n"
603
"#E{PYTHONUNBUFFERED}: disable stdout/stderr buffering (#S{-u})\n"
604
"#E{PYTHONUTF8}      : control the UTF-8 mode (#S{-X} #e{utf8})\n"
605
"#E{PYTHONVERBOSE}   : trace import statements (#S{-v})\n"
606
"#E{PYTHONWARNDEFAULTENCODING}: enable opt-in EncodingWarning for 'encoding=None'\n"
607
"                  (#S{-X} #e{warn_default_encoding})\n"
608
"#E{PYTHONWARNINGS}  : warning control (#S{-W})\n"
609
;
610
611
612
/* --- Global configuration variables ----------------------------- */
613
614
/* UTF-8 mode (PEP 540): if equal to 1, use the UTF-8 encoding, and change
615
   stdin and stdout error handler to "surrogateescape". */
616
int Py_UTF8Mode = 0;
617
int Py_DebugFlag = 0; /* Needed by parser.c */
618
int Py_VerboseFlag = 0; /* Needed by import.c */
619
int Py_QuietFlag = 0; /* Needed by sysmodule.c */
620
int Py_InteractiveFlag = 0; /* Previously, was used by Py_FdIsInteractive() */
621
int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */
622
int Py_OptimizeFlag = 0; /* Needed by compile.c */
623
int Py_NoSiteFlag = 0; /* Suppress 'import site' */
624
int Py_BytesWarningFlag = 0; /* Warn on str(bytes) and str(buffer) */
625
int Py_FrozenFlag = 0; /* Needed by getpath.c */
626
int Py_IgnoreEnvironmentFlag = 0; /* e.g. PYTHONPATH, PYTHONHOME */
627
int Py_DontWriteBytecodeFlag = 0; /* Suppress writing bytecode files (*.pyc) */
628
int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
629
int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */
630
int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */
631
int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */
632
#ifdef MS_WINDOWS
633
int Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */
634
int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */
635
#endif
636
637
638
static PyObject *
639
_Py_GetGlobalVariablesAsDict(void)
640
0
{
641
0
_Py_COMP_DIAG_PUSH
642
0
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
643
0
    PyObject *dict, *obj;
644
645
0
    dict = PyDict_New();
646
0
    if (dict == NULL) {
647
0
        return NULL;
648
0
    }
649
650
0
#define SET_ITEM(KEY, EXPR) \
651
0
        do { \
652
0
            obj = (EXPR); \
653
0
            if (obj == NULL) { \
654
0
                goto fail; \
655
0
            } \
656
0
            int res = PyDict_SetItemString(dict, (KEY), obj); \
657
0
            Py_DECREF(obj); \
658
0
            if (res < 0) { \
659
0
                goto fail; \
660
0
            } \
661
0
        } while (0)
662
0
#define SET_ITEM_INT(VAR) \
663
0
    SET_ITEM(#VAR, PyLong_FromLong(VAR))
664
0
#define FROM_STRING(STR) \
665
0
    ((STR != NULL) ? \
666
0
        PyUnicode_FromString(STR) \
667
0
        : Py_NewRef(Py_None))
668
0
#define SET_ITEM_STR(VAR) \
669
0
    SET_ITEM(#VAR, FROM_STRING(VAR))
670
671
0
    SET_ITEM_STR(Py_FileSystemDefaultEncoding);
672
0
    SET_ITEM_INT(Py_HasFileSystemDefaultEncoding);
673
0
    SET_ITEM_STR(Py_FileSystemDefaultEncodeErrors);
674
0
    SET_ITEM_INT(_Py_HasFileSystemDefaultEncodeErrors);
675
676
0
    SET_ITEM_INT(Py_UTF8Mode);
677
0
    SET_ITEM_INT(Py_DebugFlag);
678
0
    SET_ITEM_INT(Py_VerboseFlag);
679
0
    SET_ITEM_INT(Py_QuietFlag);
680
0
    SET_ITEM_INT(Py_InteractiveFlag);
681
0
    SET_ITEM_INT(Py_InspectFlag);
682
683
0
    SET_ITEM_INT(Py_OptimizeFlag);
684
0
    SET_ITEM_INT(Py_NoSiteFlag);
685
0
    SET_ITEM_INT(Py_BytesWarningFlag);
686
0
    SET_ITEM_INT(Py_FrozenFlag);
687
0
    SET_ITEM_INT(Py_IgnoreEnvironmentFlag);
688
0
    SET_ITEM_INT(Py_DontWriteBytecodeFlag);
689
0
    SET_ITEM_INT(Py_NoUserSiteDirectory);
690
0
    SET_ITEM_INT(Py_UnbufferedStdioFlag);
691
0
    SET_ITEM_INT(Py_HashRandomizationFlag);
692
0
    SET_ITEM_INT(Py_IsolatedFlag);
693
694
#ifdef MS_WINDOWS
695
    SET_ITEM_INT(Py_LegacyWindowsFSEncodingFlag);
696
    SET_ITEM_INT(Py_LegacyWindowsStdioFlag);
697
#endif
698
699
0
    return dict;
700
701
0
fail:
702
0
    Py_DECREF(dict);
703
0
    return NULL;
704
705
0
#undef FROM_STRING
706
0
#undef SET_ITEM
707
0
#undef SET_ITEM_INT
708
0
#undef SET_ITEM_STR
709
0
_Py_COMP_DIAG_POP
710
0
}
711
712
char*
713
Py_GETENV(const char *name)
714
432
{
715
432
_Py_COMP_DIAG_PUSH
716
432
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
717
432
    if (Py_IgnoreEnvironmentFlag) {
718
0
        return NULL;
719
0
    }
720
432
    return getenv(name);
721
432
_Py_COMP_DIAG_POP
722
432
}
723
724
/* --- PyStatus ----------------------------------------------- */
725
726
PyStatus PyStatus_Ok(void)
727
108
{ return _PyStatus_OK(); }
728
729
PyStatus PyStatus_Error(const char *err_msg)
730
0
{
731
0
    assert(err_msg != NULL);
732
0
    return (PyStatus){._type = _PyStatus_TYPE_ERROR,
733
0
                      .err_msg = err_msg};
734
0
}
735
736
PyStatus PyStatus_NoMemory(void)
737
0
{ return PyStatus_Error("memory allocation failed"); }
738
739
PyStatus PyStatus_Exit(int exitcode)
740
0
{ return _PyStatus_EXIT(exitcode); }
741
742
743
int PyStatus_IsError(PyStatus status)
744
0
{ return _PyStatus_IS_ERROR(status); }
745
746
int PyStatus_IsExit(PyStatus status)
747
0
{ return _PyStatus_IS_EXIT(status); }
748
749
int PyStatus_Exception(PyStatus status)
750
0
{ return _PyStatus_EXCEPTION(status); }
751
752
void
753
_PyErr_SetFromPyStatus(PyStatus status)
754
0
{
755
0
    if (!_PyStatus_IS_ERROR(status)) {
756
0
        PyErr_Format(PyExc_SystemError,
757
0
                     "_PyErr_SetFromPyStatus() status is not an error");
758
0
        return;
759
0
    }
760
761
0
    const char *err_msg = status.err_msg;
762
0
    if (err_msg == NULL || strlen(err_msg) == 0) {
763
0
        PyErr_Format(PyExc_SystemError,
764
0
                     "_PyErr_SetFromPyStatus() status has no error message");
765
0
        return;
766
0
    }
767
768
0
    if (strcmp(err_msg, _PyStatus_NO_MEMORY_ERRMSG) == 0) {
769
0
        PyErr_NoMemory();
770
0
        return;
771
0
    }
772
773
0
    const char *func = status.func;
774
0
    if (func) {
775
0
        PyErr_Format(PyExc_RuntimeError, "%s: %s", func, err_msg);
776
0
    }
777
0
    else {
778
0
        PyErr_Format(PyExc_RuntimeError, "%s", err_msg);
779
0
    }
780
0
}
781
782
783
/* --- PyWideStringList ------------------------------------------------ */
784
785
#ifndef NDEBUG
786
int
787
_PyWideStringList_CheckConsistency(const PyWideStringList *list)
788
{
789
    assert(list->length >= 0);
790
    if (list->length != 0) {
791
        assert(list->items != NULL);
792
    }
793
    for (Py_ssize_t i = 0; i < list->length; i++) {
794
        assert(list->items[i] != NULL);
795
    }
796
    return 1;
797
}
798
#endif   /* Py_DEBUG */
799
800
801
static void
802
_PyWideStringList_ClearEx(PyWideStringList *list,
803
                          bool use_default_allocator)
804
1.80k
{
805
1.80k
    assert(_PyWideStringList_CheckConsistency(list));
806
2.01k
    for (Py_ssize_t i=0; i < list->length; i++) {
807
216
        if (use_default_allocator) {
808
0
            _PyMem_DefaultRawFree(list->items[i]);
809
0
        }
810
216
        else {
811
216
            PyMem_RawFree(list->items[i]);
812
216
        }
813
216
    }
814
1.80k
    if (use_default_allocator) {
815
36
        _PyMem_DefaultRawFree(list->items);
816
36
    }
817
1.76k
    else {
818
1.76k
        PyMem_RawFree(list->items);
819
1.76k
    }
820
1.80k
    list->length = 0;
821
1.80k
    list->items = NULL;
822
1.80k
}
823
824
void
825
_PyWideStringList_Clear(PyWideStringList *list)
826
1.18k
{
827
1.18k
    _PyWideStringList_ClearEx(list, false);
828
1.18k
}
829
830
static int
831
_PyWideStringList_CopyEx(PyWideStringList *list,
832
                         const PyWideStringList *list2,
833
                         bool use_default_allocator)
834
612
{
835
612
    assert(_PyWideStringList_CheckConsistency(list));
836
612
    assert(_PyWideStringList_CheckConsistency(list2));
837
838
612
    if (list2->length == 0) {
839
504
        _PyWideStringList_ClearEx(list, use_default_allocator);
840
504
        return 0;
841
504
    }
842
843
108
    PyWideStringList copy = _PyWideStringList_INIT;
844
845
108
    size_t size = list2->length * sizeof(list2->items[0]);
846
108
    if (use_default_allocator) {
847
0
        copy.items = _PyMem_DefaultRawMalloc(size);
848
0
    }
849
108
    else {
850
108
        copy.items = PyMem_RawMalloc(size);
851
108
    }
852
108
    if (copy.items == NULL) {
853
0
        return -1;
854
0
    }
855
856
288
    for (Py_ssize_t i=0; i < list2->length; i++) {
857
180
        wchar_t *item;
858
180
        if (use_default_allocator) {
859
0
            item = _PyMem_DefaultRawWcsdup(list2->items[i]);
860
0
        }
861
180
        else {
862
180
            item = _PyMem_RawWcsdup(list2->items[i]);
863
180
        }
864
180
        if (item == NULL) {
865
0
            _PyWideStringList_ClearEx(&copy, use_default_allocator);
866
0
            return -1;
867
0
        }
868
180
        copy.items[i] = item;
869
180
        copy.length = i + 1;
870
180
    }
871
872
108
    _PyWideStringList_ClearEx(list, use_default_allocator);
873
108
    *list = copy;
874
108
    return 0;
875
108
}
876
877
int
878
_PyWideStringList_Copy(PyWideStringList *list, const PyWideStringList *list2)
879
576
{
880
576
    return _PyWideStringList_CopyEx(list, list2, false);
881
576
}
882
883
PyStatus
884
PyWideStringList_Insert(PyWideStringList *list,
885
                        Py_ssize_t index, const wchar_t *item)
886
180
{
887
180
    Py_ssize_t len = list->length;
888
180
    if (len == PY_SSIZE_T_MAX) {
889
        /* length+1 would overflow */
890
0
        return _PyStatus_NO_MEMORY();
891
0
    }
892
180
    if (index < 0) {
893
0
        return _PyStatus_ERR("PyWideStringList_Insert index must be >= 0");
894
0
    }
895
180
    if (index > len) {
896
0
        index = len;
897
0
    }
898
899
180
    wchar_t *item2 = _PyMem_RawWcsdup(item);
900
180
    if (item2 == NULL) {
901
0
        return _PyStatus_NO_MEMORY();
902
0
    }
903
904
180
    size_t size = (len + 1) * sizeof(list->items[0]);
905
180
    wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size);
906
180
    if (items2 == NULL) {
907
0
        PyMem_RawFree(item2);
908
0
        return _PyStatus_NO_MEMORY();
909
0
    }
910
911
180
    if (index < len) {
912
0
        memmove(&items2[index + 1],
913
0
                &items2[index],
914
0
                (len - index) * sizeof(items2[0]));
915
0
    }
916
917
180
    items2[index] = item2;
918
180
    list->items = items2;
919
180
    list->length++;
920
180
    return _PyStatus_OK();
921
180
}
922
923
924
PyStatus
925
PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
926
180
{
927
180
    return PyWideStringList_Insert(list, list->length, item);
928
180
}
929
930
931
PyStatus
932
_PyWideStringList_Extend(PyWideStringList *list, const PyWideStringList *list2)
933
72
{
934
72
    for (Py_ssize_t i = 0; i < list2->length; i++) {
935
0
        PyStatus status = PyWideStringList_Append(list, list2->items[i]);
936
0
        if (_PyStatus_EXCEPTION(status)) {
937
0
            return status;
938
0
        }
939
0
    }
940
72
    return _PyStatus_OK();
941
72
}
942
943
944
static int
945
_PyWideStringList_Find(PyWideStringList *list, const wchar_t *item)
946
0
{
947
0
    for (Py_ssize_t i = 0; i < list->length; i++) {
948
0
        if (wcscmp(list->items[i], item) == 0) {
949
0
            return 1;
950
0
        }
951
0
    }
952
0
    return 0;
953
0
}
954
955
956
PyObject*
957
_PyWideStringList_AsList(const PyWideStringList *list)
958
144
{
959
144
    assert(_PyWideStringList_CheckConsistency(list));
960
961
144
    PyObject *pylist = PyList_New(list->length);
962
144
    if (pylist == NULL) {
963
0
        return NULL;
964
0
    }
965
966
288
    for (Py_ssize_t i = 0; i < list->length; i++) {
967
144
        PyObject *item = PyUnicode_FromWideChar(list->items[i], -1);
968
144
        if (item == NULL) {
969
0
            Py_DECREF(pylist);
970
0
            return NULL;
971
0
        }
972
144
        PyList_SET_ITEM(pylist, i, item);
973
144
    }
974
144
    return pylist;
975
144
}
976
977
978
static PyObject*
979
_PyWideStringList_AsTuple(const PyWideStringList *list)
980
144
{
981
144
    assert(_PyWideStringList_CheckConsistency(list));
982
983
144
    PyObject *tuple = PyTuple_New(list->length);
984
144
    if (tuple == NULL) {
985
0
        return NULL;
986
0
    }
987
988
180
    for (Py_ssize_t i = 0; i < list->length; i++) {
989
36
        PyObject *item = PyUnicode_FromWideChar(list->items[i], -1);
990
36
        if (item == NULL) {
991
0
            Py_DECREF(tuple);
992
0
            return NULL;
993
0
        }
994
36
        PyTuple_SET_ITEM(tuple, i, item);
995
36
    }
996
144
    return tuple;
997
144
}
998
999
1000
/* --- Py_GetArgcArgv() ------------------------------------------- */
1001
1002
void
1003
_Py_ClearArgcArgv(void)
1004
0
{
1005
0
    _PyWideStringList_ClearEx(&_PyRuntime.orig_argv, true);
1006
0
}
1007
1008
1009
static int
1010
_Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv)
1011
36
{
1012
36
    const PyWideStringList argv_list = {.length = argc, .items = (wchar_t **)argv};
1013
1014
    // XXX _PyRuntime.orig_argv only gets cleared by Py_Main(),
1015
    // so it currently leaks for embedders.
1016
36
    return _PyWideStringList_CopyEx(&_PyRuntime.orig_argv, &argv_list, true);
1017
36
}
1018
1019
1020
// _PyConfig_Write() calls _Py_SetArgcArgv() with PyConfig.orig_argv.
1021
void
1022
Py_GetArgcArgv(int *argc, wchar_t ***argv)
1023
0
{
1024
0
    *argc = (int)_PyRuntime.orig_argv.length;
1025
0
    *argv = _PyRuntime.orig_argv.items;
1026
0
}
1027
1028
1029
/* --- PyConfig ---------------------------------------------- */
1030
1031
36
#define MAX_HASH_SEED 4294967295UL
1032
1033
1034
#ifndef NDEBUG
1035
static int
1036
config_check_consistency(const PyConfig *config)
1037
{
1038
    /* Check config consistency */
1039
    assert(config->isolated >= 0);
1040
    assert(config->use_environment >= 0);
1041
    assert(config->dev_mode >= 0);
1042
    assert(config->install_signal_handlers >= 0);
1043
    assert(config->use_hash_seed >= 0);
1044
    assert(config->hash_seed <= MAX_HASH_SEED);
1045
    assert(config->faulthandler >= 0);
1046
    assert(config->tracemalloc >= 0);
1047
    assert(config->import_time >= 0);
1048
    assert(config->code_debug_ranges >= 0);
1049
    assert(config->show_ref_count >= 0);
1050
    assert(config->dump_refs >= 0);
1051
    assert(config->malloc_stats >= 0);
1052
    assert(config->pymalloc_hugepages >= 0);
1053
    assert(config->site_import >= 0);
1054
    assert(config->bytes_warning >= 0);
1055
    assert(config->warn_default_encoding >= 0);
1056
    assert(config->inspect >= 0);
1057
    assert(config->interactive >= 0);
1058
    assert(config->optimization_level >= 0);
1059
    assert(config->parser_debug >= 0);
1060
    assert(config->write_bytecode >= 0);
1061
    assert(config->verbose >= 0);
1062
    assert(config->quiet >= 0);
1063
    assert(config->user_site_directory >= 0);
1064
    assert(config->parse_argv >= 0);
1065
    assert(config->configure_c_stdio >= 0);
1066
    assert(config->buffered_stdio >= 0);
1067
    assert(_PyWideStringList_CheckConsistency(&config->orig_argv));
1068
    assert(_PyWideStringList_CheckConsistency(&config->argv));
1069
    /* sys.argv must be non-empty: empty argv is replaced with [''] */
1070
    assert(config->argv.length >= 1);
1071
    assert(_PyWideStringList_CheckConsistency(&config->xoptions));
1072
    assert(_PyWideStringList_CheckConsistency(&config->warnoptions));
1073
    assert(_PyWideStringList_CheckConsistency(&config->module_search_paths));
1074
    assert(config->module_search_paths_set >= 0);
1075
    assert(config->filesystem_encoding != NULL);
1076
    assert(config->filesystem_errors != NULL);
1077
    assert(config->stdio_encoding != NULL);
1078
    assert(config->stdio_errors != NULL);
1079
#ifdef MS_WINDOWS
1080
    assert(config->legacy_windows_stdio >= 0);
1081
#endif
1082
    /* -c and -m options are exclusive */
1083
    assert(!(config->run_command != NULL && config->run_module != NULL));
1084
    assert(config->check_hash_pycs_mode != NULL);
1085
    assert(config->_install_importlib >= 0);
1086
    assert(config->pathconfig_warnings >= 0);
1087
    assert(config->_is_python_build >= 0);
1088
    assert(config->safe_path >= 0);
1089
    assert(config->int_max_str_digits >= 0);
1090
    // cpu_count can be -1 if the user doesn't override it.
1091
    assert(config->cpu_count != 0);
1092
    // lazy_imports can be -1 (default) or 1 (on). 0 is rejected later
1093
    // for embedders with an error message.
1094
    assert(config->lazy_imports >= -1 && config->lazy_imports <= 1);
1095
    // config->use_frozen_modules is initialized later
1096
    // by _PyConfig_InitImportConfig().
1097
    assert(config->thread_inherit_context >= 0);
1098
    assert(config->context_aware_warnings >= 0);
1099
#ifdef __APPLE__
1100
    assert(config->use_system_logger >= 0);
1101
#endif
1102
#ifdef Py_STATS
1103
    assert(config->_pystats >= 0);
1104
#endif
1105
    return 1;
1106
}
1107
#endif
1108
1109
1110
/* Free memory allocated in config, but don't clear all attributes */
1111
void
1112
PyConfig_Clear(PyConfig *config)
1113
144
{
1114
144
#define CLEAR(ATTR) \
1115
3.02k
    do { \
1116
3.02k
        PyMem_RawFree(ATTR); \
1117
3.02k
        ATTR = NULL; \
1118
3.02k
    } while (0)
1119
1120
144
    CLEAR(config->pycache_prefix);
1121
144
    CLEAR(config->pythonpath_env);
1122
144
    CLEAR(config->home);
1123
144
    CLEAR(config->program_name);
1124
1125
144
    _PyWideStringList_Clear(&config->argv);
1126
144
    _PyWideStringList_Clear(&config->warnoptions);
1127
144
    _PyWideStringList_Clear(&config->xoptions);
1128
144
    _PyWideStringList_Clear(&config->module_search_paths);
1129
144
    config->module_search_paths_set = 0;
1130
144
    CLEAR(config->stdlib_dir);
1131
1132
144
    CLEAR(config->executable);
1133
144
    CLEAR(config->base_executable);
1134
144
    CLEAR(config->prefix);
1135
144
    CLEAR(config->base_prefix);
1136
144
    CLEAR(config->exec_prefix);
1137
144
    CLEAR(config->base_exec_prefix);
1138
144
    CLEAR(config->platlibdir);
1139
144
    CLEAR(config->sys_path_0);
1140
1141
144
    CLEAR(config->filesystem_encoding);
1142
144
    CLEAR(config->filesystem_errors);
1143
144
    CLEAR(config->stdio_encoding);
1144
144
    CLEAR(config->stdio_errors);
1145
144
    CLEAR(config->run_command);
1146
144
    CLEAR(config->run_module);
1147
144
    CLEAR(config->run_filename);
1148
144
    CLEAR(config->check_hash_pycs_mode);
1149
#ifdef Py_DEBUG
1150
    CLEAR(config->run_presite);
1151
#endif
1152
1153
144
    _PyWideStringList_Clear(&config->orig_argv);
1154
144
#undef CLEAR
1155
144
}
1156
1157
1158
void
1159
_PyConfig_InitCompatConfig(PyConfig *config)
1160
108
{
1161
108
    memset(config, 0, sizeof(*config));
1162
1163
108
    config->_config_init = (int)_PyConfig_INIT_COMPAT;
1164
108
    config->import_time = -1;
1165
108
    config->isolated = -1;
1166
108
    config->use_environment = -1;
1167
108
    config->dev_mode = -1;
1168
108
    config->install_signal_handlers = 1;
1169
108
    config->use_hash_seed = -1;
1170
108
    config->faulthandler = -1;
1171
108
    config->tracemalloc = -1;
1172
108
    config->perf_profiling = -1;
1173
108
    config->remote_debug = -1;
1174
108
    config->module_search_paths_set = 0;
1175
108
    config->parse_argv = 0;
1176
108
    config->site_import = -1;
1177
108
    config->bytes_warning = -1;
1178
108
    config->warn_default_encoding = 0;
1179
108
    config->inspect = -1;
1180
108
    config->interactive = -1;
1181
108
    config->optimization_level = -1;
1182
108
    config->parser_debug= -1;
1183
108
    config->write_bytecode = -1;
1184
108
    config->verbose = -1;
1185
108
    config->quiet = -1;
1186
108
    config->user_site_directory = -1;
1187
108
    config->configure_c_stdio = 0;
1188
108
    config->buffered_stdio = -1;
1189
108
    config->_install_importlib = 1;
1190
108
    config->check_hash_pycs_mode = NULL;
1191
108
    config->pathconfig_warnings = -1;
1192
108
    config->_init_main = 1;
1193
#ifdef MS_WINDOWS
1194
    config->legacy_windows_stdio = -1;
1195
#endif
1196
#ifdef Py_DEBUG
1197
    config->use_frozen_modules = 0;
1198
#else
1199
108
    config->use_frozen_modules = 1;
1200
108
#endif
1201
108
    config->safe_path = 0;
1202
108
    config->int_max_str_digits = -1;
1203
108
    config->_is_python_build = 0;
1204
108
    config->code_debug_ranges = 1;
1205
108
    config->cpu_count = -1;
1206
108
    config->lazy_imports = -1;
1207
#ifdef Py_GIL_DISABLED
1208
    config->thread_inherit_context = 1;
1209
    config->context_aware_warnings = 1;
1210
#else
1211
108
    config->thread_inherit_context = 0;
1212
108
    config->context_aware_warnings = 0;
1213
108
#endif
1214
#ifdef __APPLE__
1215
    config->use_system_logger = USE_SYSTEM_LOGGER_DEFAULT;
1216
#endif
1217
#ifdef Py_GIL_DISABLED
1218
    config->enable_gil = _PyConfig_GIL_DEFAULT;
1219
    config->tlbc_enabled = 1;
1220
#endif
1221
108
}
1222
1223
1224
static void
1225
config_init_defaults(PyConfig *config)
1226
72
{
1227
72
    _PyConfig_InitCompatConfig(config);
1228
1229
72
    config->isolated = 0;
1230
72
    config->use_environment = 1;
1231
72
    config->site_import = 1;
1232
72
    config->bytes_warning = 0;
1233
72
    config->inspect = 0;
1234
72
    config->interactive = 0;
1235
72
    config->optimization_level = 0;
1236
72
    config->parser_debug= 0;
1237
72
    config->write_bytecode = 1;
1238
72
    config->verbose = 0;
1239
72
    config->quiet = 0;
1240
72
    config->user_site_directory = 1;
1241
72
    config->buffered_stdio = 1;
1242
72
    config->pathconfig_warnings = 1;
1243
#ifdef MS_WINDOWS
1244
    config->legacy_windows_stdio = 0;
1245
#endif
1246
#ifdef Py_GIL_DISABLED
1247
    config->thread_inherit_context = 1;
1248
    config->context_aware_warnings = 1;
1249
#else
1250
72
    config->thread_inherit_context = 0;
1251
72
    config->context_aware_warnings = 0;
1252
72
#endif
1253
#ifdef __APPLE__
1254
    config->use_system_logger = USE_SYSTEM_LOGGER_DEFAULT;
1255
#endif
1256
72
}
1257
1258
1259
void
1260
PyConfig_InitPythonConfig(PyConfig *config)
1261
72
{
1262
72
    config_init_defaults(config);
1263
1264
72
    config->_config_init = (int)_PyConfig_INIT_PYTHON;
1265
72
    config->configure_c_stdio = 1;
1266
72
    config->parse_argv = 1;
1267
72
}
1268
1269
1270
void
1271
PyConfig_InitIsolatedConfig(PyConfig *config)
1272
0
{
1273
0
    config_init_defaults(config);
1274
1275
0
    config->_config_init = (int)_PyConfig_INIT_ISOLATED;
1276
0
    config->isolated = 1;
1277
0
    config->use_environment = 0;
1278
0
    config->user_site_directory = 0;
1279
0
    config->dev_mode = 0;
1280
0
    config->install_signal_handlers = 0;
1281
0
    config->use_hash_seed = 0;
1282
0
    config->tracemalloc = 0;
1283
0
    config->perf_profiling = 0;
1284
0
    config->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;
1285
0
    config->safe_path = 1;
1286
0
    config->pathconfig_warnings = 0;
1287
#ifdef Py_GIL_DISABLED
1288
    config->thread_inherit_context = 1;
1289
#else
1290
0
    config->thread_inherit_context = 0;
1291
0
#endif
1292
#ifdef MS_WINDOWS
1293
    config->legacy_windows_stdio = 0;
1294
#endif
1295
#ifdef __APPLE__
1296
    config->use_system_logger = USE_SYSTEM_LOGGER_DEFAULT;
1297
#endif
1298
0
}
1299
1300
1301
/* Copy str into *config_str (duplicate the string) */
1302
PyStatus
1303
PyConfig_SetString(PyConfig *config, wchar_t **config_str, const wchar_t *str)
1304
2.55k
{
1305
2.55k
    PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
1306
2.55k
    if (_PyStatus_EXCEPTION(status)) {
1307
0
        return status;
1308
0
    }
1309
1310
2.55k
    wchar_t *str2;
1311
2.55k
    if (str != NULL) {
1312
900
        str2 = _PyMem_RawWcsdup(str);
1313
900
        if (str2 == NULL) {
1314
0
            return _PyStatus_NO_MEMORY();
1315
0
        }
1316
900
    }
1317
1.65k
    else {
1318
1.65k
        str2 = NULL;
1319
1.65k
    }
1320
2.55k
    PyMem_RawFree(*config_str);
1321
2.55k
    *config_str = str2;
1322
2.55k
    return _PyStatus_OK();
1323
2.55k
}
1324
1325
1326
static PyStatus
1327
config_set_bytes_string(PyConfig *config, wchar_t **config_str,
1328
                        const char *str, const char *decode_err_msg)
1329
0
{
1330
0
    PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
1331
0
    if (_PyStatus_EXCEPTION(status)) {
1332
0
        return status;
1333
0
    }
1334
1335
0
    wchar_t *str2;
1336
0
    if (str != NULL) {
1337
0
        size_t len;
1338
0
        str2 = Py_DecodeLocale(str, &len);
1339
0
        if (str2 == NULL) {
1340
0
            if (len == (size_t)-2) {
1341
0
                return _PyStatus_ERR(decode_err_msg);
1342
0
            }
1343
0
            else {
1344
0
                return  _PyStatus_NO_MEMORY();
1345
0
            }
1346
0
        }
1347
0
    }
1348
0
    else {
1349
0
        str2 = NULL;
1350
0
    }
1351
0
    PyMem_RawFree(*config_str);
1352
0
    *config_str = str2;
1353
0
    return _PyStatus_OK();
1354
0
}
1355
1356
1357
#define CONFIG_SET_BYTES_STR(config, config_str, str, NAME) \
1358
0
    config_set_bytes_string(config, config_str, str, "cannot decode " NAME)
1359
1360
1361
/* Decode str using Py_DecodeLocale() and set the result into *config_str.
1362
   Pre-initialize Python if needed to ensure that encodings are properly
1363
   configured. */
1364
PyStatus
1365
PyConfig_SetBytesString(PyConfig *config, wchar_t **config_str,
1366
                        const char *str)
1367
0
{
1368
0
    return CONFIG_SET_BYTES_STR(config, config_str, str, "string");
1369
0
}
1370
1371
1372
static inline void*
1373
config_get_spec_member(const PyConfig *config, const PyConfigSpec *spec)
1374
13.7k
{
1375
13.7k
    return (char *)config + spec->offset;
1376
13.7k
}
1377
1378
1379
static inline void*
1380
preconfig_get_spec_member(const PyPreConfig *preconfig, const PyConfigSpec *spec)
1381
0
{
1382
0
    return (char *)preconfig + spec->offset;
1383
0
}
1384
1385
1386
PyStatus
1387
_PyConfig_Copy(PyConfig *config, const PyConfig *config2)
1388
72
{
1389
72
    PyConfig_Clear(config);
1390
1391
72
    PyStatus status;
1392
72
    const PyConfigSpec *spec = PYCONFIG_SPEC;
1393
5.18k
    for (; spec->name != NULL; spec++) {
1394
5.11k
        void *member = config_get_spec_member(config, spec);
1395
5.11k
        const void *member2 = config_get_spec_member((PyConfig*)config2, spec);
1396
5.11k
        switch (spec->type) {
1397
288
        case PyConfig_MEMBER_INT:
1398
864
        case PyConfig_MEMBER_UINT:
1399
3.09k
        case PyConfig_MEMBER_BOOL:
1400
3.09k
        {
1401
3.09k
            *(int*)member = *(int*)member2;
1402
3.09k
            break;
1403
864
        }
1404
72
        case PyConfig_MEMBER_ULONG:
1405
72
        {
1406
72
            *(unsigned long*)member = *(unsigned long*)member2;
1407
72
            break;
1408
864
        }
1409
504
        case PyConfig_MEMBER_WSTR:
1410
1.58k
        case PyConfig_MEMBER_WSTR_OPT:
1411
1.58k
        {
1412
1.58k
            const wchar_t *str = *(const wchar_t**)member2;
1413
1.58k
            status = PyConfig_SetString(config, (wchar_t**)member, str);
1414
1.58k
            if (_PyStatus_EXCEPTION(status)) {
1415
0
                return status;
1416
0
            }
1417
1.58k
            break;
1418
1.58k
        }
1419
1.58k
        case PyConfig_MEMBER_WSTR_LIST:
1420
360
        {
1421
360
            if (_PyWideStringList_Copy((PyWideStringList*)member,
1422
360
                                       (const PyWideStringList*)member2) < 0) {
1423
0
                return _PyStatus_NO_MEMORY();
1424
0
            }
1425
360
            break;
1426
360
        }
1427
360
        default:
1428
0
            Py_UNREACHABLE();
1429
5.11k
        }
1430
5.11k
    }
1431
72
    return _PyStatus_OK();
1432
72
}
1433
1434
1435
PyObject *
1436
_PyConfig_AsDict(const PyConfig *config)
1437
36
{
1438
36
    PyObject *dict = PyDict_New();
1439
36
    if (dict == NULL) {
1440
0
        return NULL;
1441
0
    }
1442
1443
36
    const PyConfigSpec *spec = PYCONFIG_SPEC;
1444
2.59k
    for (; spec->name != NULL; spec++) {
1445
2.55k
        PyObject *obj = config_get(config, spec, 0);
1446
2.55k
        if (obj == NULL) {
1447
0
            Py_DECREF(dict);
1448
0
            return NULL;
1449
0
        }
1450
1451
2.55k
        int res = PyDict_SetItemString(dict, spec->name, obj);
1452
2.55k
        Py_DECREF(obj);
1453
2.55k
        if (res < 0) {
1454
0
            Py_DECREF(dict);
1455
0
            return NULL;
1456
0
        }
1457
2.55k
    }
1458
36
    return dict;
1459
36
}
1460
1461
1462
static void
1463
config_dict_invalid_value(const char *name)
1464
0
{
1465
0
    PyErr_Format(PyExc_ValueError, "invalid config value: %s", name);
1466
0
}
1467
1468
1469
static int
1470
config_dict_get_int(PyObject *dict, const char *name, int *result)
1471
1.54k
{
1472
1.54k
    PyObject *item = config_dict_get(dict, name);
1473
1.54k
    if (item == NULL) {
1474
0
        return -1;
1475
0
    }
1476
1.54k
    int value = PyLong_AsInt(item);
1477
1.54k
    Py_DECREF(item);
1478
1.54k
    if (value == -1 && PyErr_Occurred()) {
1479
0
        if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1480
0
            config_dict_invalid_type(name);
1481
0
        }
1482
0
        else if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
1483
0
            config_dict_invalid_value(name);
1484
0
        }
1485
0
        return -1;
1486
0
    }
1487
1.54k
    *result = value;
1488
1.54k
    return 0;
1489
1.54k
}
1490
1491
1492
static int
1493
config_dict_get_ulong(PyObject *dict, const char *name, unsigned long *result)
1494
36
{
1495
36
    PyObject *item = config_dict_get(dict, name);
1496
36
    if (item == NULL) {
1497
0
        return -1;
1498
0
    }
1499
36
    unsigned long value = PyLong_AsUnsignedLong(item);
1500
36
    Py_DECREF(item);
1501
36
    if (value == (unsigned long)-1 && PyErr_Occurred()) {
1502
0
        if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1503
0
            config_dict_invalid_type(name);
1504
0
        }
1505
0
        else if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
1506
0
            config_dict_invalid_value(name);
1507
0
        }
1508
0
        return -1;
1509
0
    }
1510
36
    *result = value;
1511
36
    return 0;
1512
36
}
1513
1514
1515
static int
1516
config_dict_get_wstr(PyObject *dict, const char *name, PyConfig *config,
1517
                     wchar_t **result)
1518
792
{
1519
792
    PyObject *item = config_dict_get(dict, name);
1520
792
    if (item == NULL) {
1521
0
        return -1;
1522
0
    }
1523
1524
792
    PyStatus status;
1525
792
    if (item == Py_None) {
1526
252
        status = PyConfig_SetString(config, result, NULL);
1527
252
    }
1528
540
    else if (!PyUnicode_Check(item)) {
1529
0
        config_dict_invalid_type(name);
1530
0
        goto error;
1531
0
    }
1532
540
    else {
1533
540
        wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);
1534
540
        if (wstr == NULL) {
1535
0
            goto error;
1536
0
        }
1537
540
        status = PyConfig_SetString(config, result, wstr);
1538
540
        PyMem_Free(wstr);
1539
540
    }
1540
792
    if (_PyStatus_EXCEPTION(status)) {
1541
0
        PyErr_NoMemory();
1542
0
        goto error;
1543
0
    }
1544
792
    Py_DECREF(item);
1545
792
    return 0;
1546
1547
0
error:
1548
0
    Py_DECREF(item);
1549
0
    return -1;
1550
792
}
1551
1552
1553
static int
1554
config_dict_get_wstrlist(PyObject *dict, const char *name, PyConfig *config,
1555
                         PyWideStringList *result)
1556
144
{
1557
144
    PyObject *list = config_dict_get(dict, name);
1558
144
    if (list == NULL) {
1559
0
        return -1;
1560
0
    }
1561
1562
144
    int is_list = PyList_CheckExact(list);
1563
144
    if (!is_list && !PyTuple_CheckExact(list)) {
1564
0
        Py_DECREF(list);
1565
0
        config_dict_invalid_type(name);
1566
0
        return -1;
1567
0
    }
1568
1569
144
    PyWideStringList wstrlist = _PyWideStringList_INIT;
1570
144
    Py_ssize_t len = is_list ? PyList_GET_SIZE(list) : PyTuple_GET_SIZE(list);
1571
288
    for (Py_ssize_t i=0; i < len; i++) {
1572
144
        PyObject *item = is_list ? PyList_GET_ITEM(list, i) : PyTuple_GET_ITEM(list, i);
1573
1574
144
        if (item == Py_None) {
1575
0
            config_dict_invalid_value(name);
1576
0
            goto error;
1577
0
        }
1578
144
        else if (!PyUnicode_Check(item)) {
1579
0
            config_dict_invalid_type(name);
1580
0
            goto error;
1581
0
        }
1582
144
        wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);
1583
144
        if (wstr == NULL) {
1584
0
            goto error;
1585
0
        }
1586
144
        PyStatus status = PyWideStringList_Append(&wstrlist, wstr);
1587
144
        PyMem_Free(wstr);
1588
144
        if (_PyStatus_EXCEPTION(status)) {
1589
0
            PyErr_NoMemory();
1590
0
            goto error;
1591
0
        }
1592
144
    }
1593
1594
144
    if (_PyWideStringList_Copy(result, &wstrlist) < 0) {
1595
0
        PyErr_NoMemory();
1596
0
        goto error;
1597
0
    }
1598
144
    _PyWideStringList_Clear(&wstrlist);
1599
144
    Py_DECREF(list);
1600
144
    return 0;
1601
1602
0
error:
1603
0
    _PyWideStringList_Clear(&wstrlist);
1604
0
    Py_DECREF(list);
1605
0
    return -1;
1606
144
}
1607
1608
1609
static int
1610
config_dict_get_xoptions(PyObject *dict, const char *name, PyConfig *config,
1611
                         PyWideStringList *result)
1612
36
{
1613
36
    PyObject *xoptions = config_dict_get(dict, name);
1614
36
    if (xoptions == NULL) {
1615
0
        return -1;
1616
0
    }
1617
1618
36
    if (!PyDict_CheckExact(xoptions)) {
1619
0
        Py_DECREF(xoptions);
1620
0
        config_dict_invalid_type(name);
1621
0
        return -1;
1622
0
    }
1623
1624
36
    Py_ssize_t pos = 0;
1625
36
    PyObject *key, *value;
1626
36
    PyWideStringList wstrlist = _PyWideStringList_INIT;
1627
36
    while (PyDict_Next(xoptions, &pos, &key, &value)) {
1628
0
        PyObject *item;
1629
1630
0
        if (value != Py_True) {
1631
0
            item = PyUnicode_FromFormat("%S=%S", key, value);
1632
0
            if (item == NULL) {
1633
0
                goto error;
1634
0
            }
1635
0
        }
1636
0
        else {
1637
0
            item = Py_NewRef(key);
1638
0
        }
1639
1640
0
        wchar_t *wstr = PyUnicode_AsWideCharString(item, NULL);
1641
0
        Py_DECREF(item);
1642
0
        if (wstr == NULL) {
1643
0
            goto error;
1644
0
        }
1645
1646
0
        PyStatus status = PyWideStringList_Append(&wstrlist, wstr);
1647
0
        PyMem_Free(wstr);
1648
0
        if (_PyStatus_EXCEPTION(status)) {
1649
0
            PyErr_NoMemory();
1650
0
            goto error;
1651
0
        }
1652
0
    }
1653
1654
36
    if (_PyWideStringList_Copy(result, &wstrlist) < 0) {
1655
0
        PyErr_NoMemory();
1656
0
        goto error;
1657
0
    }
1658
36
    _PyWideStringList_Clear(&wstrlist);
1659
36
    Py_DECREF(xoptions);
1660
36
    return 0;
1661
1662
0
error:
1663
0
    _PyWideStringList_Clear(&wstrlist);
1664
0
    Py_DECREF(xoptions);
1665
0
    return -1;
1666
36
}
1667
1668
1669
int
1670
_PyConfig_FromDict(PyConfig *config, PyObject *dict)
1671
36
{
1672
36
    if (!PyDict_Check(dict)) {
1673
0
        PyErr_SetString(PyExc_TypeError, "dict expected");
1674
0
        return -1;
1675
0
    }
1676
1677
36
    const PyConfigSpec *spec = PYCONFIG_SPEC;
1678
2.59k
    for (; spec->name != NULL; spec++) {
1679
2.55k
        char *member = (char *)config + spec->offset;
1680
2.55k
        switch (spec->type) {
1681
144
        case PyConfig_MEMBER_INT:
1682
432
        case PyConfig_MEMBER_UINT:
1683
1.54k
        case PyConfig_MEMBER_BOOL:
1684
1.54k
        {
1685
1.54k
            int value;
1686
1.54k
            if (config_dict_get_int(dict, spec->name, &value) < 0) {
1687
0
                return -1;
1688
0
            }
1689
1.54k
            if (spec->type == PyConfig_MEMBER_BOOL
1690
432
                || spec->type == PyConfig_MEMBER_UINT)
1691
1.40k
            {
1692
1.40k
                if (value < 0) {
1693
0
                    config_dict_invalid_value(spec->name);
1694
0
                    return -1;
1695
0
                }
1696
1.40k
            }
1697
1.54k
            *(int*)member = value;
1698
1.54k
            break;
1699
1.54k
        }
1700
36
        case PyConfig_MEMBER_ULONG:
1701
36
        {
1702
36
            if (config_dict_get_ulong(dict, spec->name,
1703
36
                                      (unsigned long*)member) < 0) {
1704
0
                return -1;
1705
0
            }
1706
36
            break;
1707
36
        }
1708
252
        case PyConfig_MEMBER_WSTR:
1709
252
        {
1710
252
            wchar_t **wstr = (wchar_t**)member;
1711
252
            if (config_dict_get_wstr(dict, spec->name, config, wstr) < 0) {
1712
0
                return -1;
1713
0
            }
1714
252
            if (*wstr == NULL) {
1715
0
                config_dict_invalid_value(spec->name);
1716
0
                return -1;
1717
0
            }
1718
252
            break;
1719
252
        }
1720
540
        case PyConfig_MEMBER_WSTR_OPT:
1721
540
        {
1722
540
            wchar_t **wstr = (wchar_t**)member;
1723
540
            if (config_dict_get_wstr(dict, spec->name, config, wstr) < 0) {
1724
0
                return -1;
1725
0
            }
1726
540
            break;
1727
540
        }
1728
540
        case PyConfig_MEMBER_WSTR_LIST:
1729
180
        {
1730
180
            if (strcmp(spec->name, "xoptions") == 0) {
1731
36
                if (config_dict_get_xoptions(dict, spec->name, config,
1732
36
                                             (PyWideStringList*)member) < 0) {
1733
0
                    return -1;
1734
0
                }
1735
36
            }
1736
144
            else {
1737
144
                if (config_dict_get_wstrlist(dict, spec->name, config,
1738
144
                                             (PyWideStringList*)member) < 0) {
1739
0
                    return -1;
1740
0
                }
1741
144
            }
1742
180
            break;
1743
180
        }
1744
180
        default:
1745
0
            Py_UNREACHABLE();
1746
2.55k
        }
1747
2.55k
    }
1748
1749
36
    if (!(config->_config_init == _PyConfig_INIT_COMPAT
1750
0
          || config->_config_init == _PyConfig_INIT_PYTHON
1751
0
          || config->_config_init == _PyConfig_INIT_ISOLATED))
1752
0
    {
1753
0
        config_dict_invalid_value("_config_init");
1754
0
        return -1;
1755
0
    }
1756
1757
36
    if (config->hash_seed > MAX_HASH_SEED) {
1758
0
        config_dict_invalid_value("hash_seed");
1759
0
        return -1;
1760
0
    }
1761
36
    return 0;
1762
36
}
1763
1764
1765
static const char*
1766
config_get_env(const PyConfig *config, const char *name)
1767
720
{
1768
720
    return _Py_GetEnv(config->use_environment, name);
1769
720
}
1770
1771
1772
/* Get a copy of the environment variable as wchar_t*.
1773
   Return 0 on success, but *dest can be NULL.
1774
   Return -1 on memory allocation failure. Return -2 on decoding error. */
1775
static PyStatus
1776
config_get_env_dup(PyConfig *config,
1777
                   wchar_t **dest,
1778
                   wchar_t *wname, char *name,
1779
                   const char *decode_err_msg)
1780
180
{
1781
180
    assert(*dest == NULL);
1782
180
    assert(config->use_environment >= 0);
1783
1784
180
    if (!config->use_environment) {
1785
0
        *dest = NULL;
1786
0
        return _PyStatus_OK();
1787
0
    }
1788
1789
#ifdef MS_WINDOWS
1790
    const wchar_t *var = _wgetenv(wname);
1791
    if (!var || var[0] == '\0') {
1792
        *dest = NULL;
1793
        return _PyStatus_OK();
1794
    }
1795
1796
    return PyConfig_SetString(config, dest, var);
1797
#else
1798
180
    const char *var = getenv(name);
1799
180
    if (!var || var[0] == '\0') {
1800
180
        *dest = NULL;
1801
180
        return _PyStatus_OK();
1802
180
    }
1803
1804
0
    return config_set_bytes_string(config, dest, var, decode_err_msg);
1805
180
#endif
1806
180
}
1807
1808
1809
#define CONFIG_GET_ENV_DUP(CONFIG, DEST, WNAME, NAME) \
1810
180
    config_get_env_dup(CONFIG, DEST, WNAME, NAME, "cannot decode " NAME)
1811
1812
1813
static void
1814
config_get_global_vars(PyConfig *config)
1815
36
{
1816
36
    if (config->_config_init != _PyConfig_INIT_COMPAT) {
1817
        /* Python and Isolated configuration ignore global variables */
1818
0
        return;
1819
0
    }
1820
1821
36
    const PyConfigSpec *spec = PYCONFIG_SPEC;
1822
2.59k
    for (; spec->name != NULL; spec++) {
1823
2.55k
        if (spec->global_var.ptr == NULL) {
1824
2.05k
            continue;
1825
2.05k
        }
1826
2.55k
        assert(spec->type == PyConfig_MEMBER_INT
1827
504
               || spec->type == PyConfig_MEMBER_UINT
1828
504
               || spec->type == PyConfig_MEMBER_BOOL);
1829
504
        int *member = config_get_spec_member(config, spec);
1830
504
        if (*member != -1) {
1831
0
            continue;
1832
0
        }
1833
504
        int value = *spec->global_var.ptr;
1834
504
        if (spec->global_var.not) {
1835
216
            value = !value;
1836
216
        }
1837
504
        *member = value;
1838
504
    }
1839
36
}
1840
1841
1842
/* Set Py_xxx global configuration variables from 'config' configuration. */
1843
static void
1844
config_set_global_vars(const PyConfig *config)
1845
36
{
1846
36
    const PyConfigSpec *spec = PYCONFIG_SPEC;
1847
2.59k
    for (; spec->name != NULL; spec++) {
1848
2.55k
        if (spec->global_var.ptr == NULL) {
1849
2.05k
            continue;
1850
2.05k
        }
1851
2.55k
        assert(spec->type == PyConfig_MEMBER_INT
1852
504
               || spec->type == PyConfig_MEMBER_UINT
1853
504
               || spec->type == PyConfig_MEMBER_BOOL);
1854
504
        int *member = config_get_spec_member(config, spec);
1855
504
        int value = *member;
1856
504
        if (value == -1) {
1857
0
            continue;
1858
0
        }
1859
504
        if (spec->global_var.not) {
1860
216
            value = !value;
1861
216
        }
1862
504
        *spec->global_var.ptr = value;
1863
504
    }
1864
1865
36
_Py_COMP_DIAG_PUSH
1866
36
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
1867
    /* Random or non-zero hash seed */
1868
36
    Py_HashRandomizationFlag = (config->use_hash_seed == 0 ||
1869
0
                                config->hash_seed != 0);
1870
36
_Py_COMP_DIAG_POP
1871
36
}
1872
1873
1874
static const wchar_t*
1875
config_get_xoption(const PyConfig *config, wchar_t *name)
1876
648
{
1877
648
    return _Py_get_xoption(&config->xoptions, name);
1878
648
}
1879
1880
static const wchar_t*
1881
config_get_xoption_value(const PyConfig *config, wchar_t *name)
1882
180
{
1883
180
    const wchar_t *xoption = config_get_xoption(config, name);
1884
180
    if (xoption == NULL) {
1885
180
        return NULL;
1886
180
    }
1887
0
    const wchar_t *sep = wcschr(xoption, L'=');
1888
0
    return sep ? sep + 1 : L"";
1889
180
}
1890
1891
1892
static PyStatus
1893
config_init_hash_seed(PyConfig *config)
1894
36
{
1895
36
    static_assert(sizeof(_Py_HashSecret_t) == sizeof(_Py_HashSecret.uc),
1896
36
                  "_Py_HashSecret_t has wrong size");
1897
1898
36
    const char *seed_text = config_get_env(config, "PYTHONHASHSEED");
1899
1900
    /* Convert a text seed to a numeric one */
1901
36
    if (seed_text && strcmp(seed_text, "random") != 0) {
1902
0
        const char *endptr = seed_text;
1903
0
        unsigned long seed;
1904
0
        errno = 0;
1905
0
        seed = strtoul(seed_text, (char **)&endptr, 10);
1906
0
        if (*endptr != '\0'
1907
0
            || seed > MAX_HASH_SEED
1908
0
            || (errno == ERANGE && seed == ULONG_MAX))
1909
0
        {
1910
0
            return _PyStatus_ERR("PYTHONHASHSEED must be \"random\" "
1911
0
                                "or an integer in range [0; 4294967295]");
1912
0
        }
1913
        /* Use a specific hash */
1914
0
        config->use_hash_seed = 1;
1915
0
        config->hash_seed = seed;
1916
0
    }
1917
36
    else {
1918
        /* Use a random hash */
1919
36
        config->use_hash_seed = 0;
1920
36
        config->hash_seed = 0;
1921
36
    }
1922
36
    return _PyStatus_OK();
1923
36
}
1924
1925
1926
static int
1927
config_wstr_to_int(const wchar_t *wstr, int *result)
1928
0
{
1929
0
    const wchar_t *endptr = wstr;
1930
0
    errno = 0;
1931
0
    long value = wcstol(wstr, (wchar_t **)&endptr, 10);
1932
0
    if (*endptr != '\0' || errno == ERANGE) {
1933
0
        return -1;
1934
0
    }
1935
0
    if (value < INT_MIN || value > INT_MAX) {
1936
0
        return -1;
1937
0
    }
1938
1939
0
    *result = (int)value;
1940
0
    return 0;
1941
0
}
1942
1943
static PyStatus
1944
config_read_gil(PyConfig *config, size_t len, wchar_t first_char)
1945
0
{
1946
0
    if (len == 1 && first_char == L'0') {
1947
#ifdef Py_GIL_DISABLED
1948
        config->enable_gil = _PyConfig_GIL_DISABLE;
1949
#else
1950
0
        return _PyStatus_ERR("Disabling the GIL is not supported by this build");
1951
0
#endif
1952
0
    }
1953
0
    else if (len == 1 && first_char == L'1') {
1954
#ifdef Py_GIL_DISABLED
1955
        config->enable_gil = _PyConfig_GIL_ENABLE;
1956
#else
1957
0
        return _PyStatus_OK();
1958
0
#endif
1959
0
    }
1960
0
    else {
1961
0
        return _PyStatus_ERR("PYTHON_GIL / -X gil must be \"0\" or \"1\"");
1962
0
    }
1963
0
    return _PyStatus_OK();
1964
0
}
1965
1966
static PyStatus
1967
config_read_env_vars(PyConfig *config)
1968
36
{
1969
36
    PyStatus status;
1970
36
    int use_env = config->use_environment;
1971
1972
    /* Get environment variables */
1973
36
    _Py_get_env_flag(use_env, &config->parser_debug, "PYTHONDEBUG");
1974
36
    _Py_get_env_flag(use_env, &config->verbose, "PYTHONVERBOSE");
1975
36
    _Py_get_env_flag(use_env, &config->optimization_level, "PYTHONOPTIMIZE");
1976
36
    if (!config->inspect && _Py_GetEnv(use_env, "PYTHONINSPECT")) {
1977
0
        config->inspect = 1;
1978
0
    }
1979
1980
36
    int dont_write_bytecode = 0;
1981
36
    _Py_get_env_flag(use_env, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE");
1982
36
    if (dont_write_bytecode) {
1983
0
        config->write_bytecode = 0;
1984
0
    }
1985
1986
36
    int no_user_site_directory = 0;
1987
36
    _Py_get_env_flag(use_env, &no_user_site_directory, "PYTHONNOUSERSITE");
1988
36
    if (no_user_site_directory) {
1989
0
        config->user_site_directory = 0;
1990
0
    }
1991
1992
36
    int unbuffered_stdio = 0;
1993
36
    _Py_get_env_flag(use_env, &unbuffered_stdio, "PYTHONUNBUFFERED");
1994
36
    if (unbuffered_stdio) {
1995
0
        config->buffered_stdio = 0;
1996
0
    }
1997
1998
#ifdef MS_WINDOWS
1999
    _Py_get_env_flag(use_env, &config->legacy_windows_stdio,
2000
                     "PYTHONLEGACYWINDOWSSTDIO");
2001
#endif
2002
2003
36
    if (config_get_env(config, "PYTHONDUMPREFS")) {
2004
0
        config->dump_refs = 1;
2005
0
    }
2006
36
    if (config_get_env(config, "PYTHONMALLOCSTATS")) {
2007
0
        config->malloc_stats = 1;
2008
0
    }
2009
36
    {
2010
36
        const char *env = _Py_GetEnv(use_env, "PYTHON_PYMALLOC_HUGEPAGES");
2011
36
        if (env) {
2012
0
            int value;
2013
0
            if (_Py_str_to_int(env, &value) < 0 || value < 0) {
2014
                /* PYTHON_PYMALLOC_HUGEPAGES=text or negative
2015
                   behaves as PYTHON_PYMALLOC_HUGEPAGES=1 */
2016
0
                value = 1;
2017
0
            }
2018
0
            config->pymalloc_hugepages = (value > 0);
2019
0
        }
2020
36
    }
2021
2022
36
    if (config->dump_refs_file == NULL) {
2023
36
        status = CONFIG_GET_ENV_DUP(config, &config->dump_refs_file,
2024
36
                                    L"PYTHONDUMPREFSFILE", "PYTHONDUMPREFSFILE");
2025
36
        if (_PyStatus_EXCEPTION(status)) {
2026
0
            return status;
2027
0
        }
2028
36
    }
2029
2030
36
    if (config->pythonpath_env == NULL) {
2031
36
        status = CONFIG_GET_ENV_DUP(config, &config->pythonpath_env,
2032
36
                                    L"PYTHONPATH", "PYTHONPATH");
2033
36
        if (_PyStatus_EXCEPTION(status)) {
2034
0
            return status;
2035
0
        }
2036
36
    }
2037
2038
36
    if(config->platlibdir == NULL) {
2039
36
        status = CONFIG_GET_ENV_DUP(config, &config->platlibdir,
2040
36
                                    L"PYTHONPLATLIBDIR", "PYTHONPLATLIBDIR");
2041
36
        if (_PyStatus_EXCEPTION(status)) {
2042
0
            return status;
2043
0
        }
2044
36
    }
2045
2046
36
    if (config->use_hash_seed < 0) {
2047
36
        status = config_init_hash_seed(config);
2048
36
        if (_PyStatus_EXCEPTION(status)) {
2049
0
            return status;
2050
0
        }
2051
36
    }
2052
2053
36
    if (config_get_env(config, "PYTHONSAFEPATH")) {
2054
0
        config->safe_path = 1;
2055
0
    }
2056
2057
36
    const char *gil = config_get_env(config, "PYTHON_GIL");
2058
36
    if (gil != NULL) {
2059
0
        size_t len = strlen(gil);
2060
0
        status = config_read_gil(config, len, gil[0]);
2061
0
        if (_PyStatus_EXCEPTION(status)) {
2062
0
            return status;
2063
0
        }
2064
0
    }
2065
2066
36
    return _PyStatus_OK();
2067
36
}
2068
2069
static PyStatus
2070
config_init_cpu_count(PyConfig *config)
2071
36
{
2072
36
    const char *env = config_get_env(config, "PYTHON_CPU_COUNT");
2073
36
    if (env) {
2074
0
        int cpu_count = -1;
2075
0
        if (strcmp(env, "default") == 0) {
2076
0
            cpu_count = -1;
2077
0
        }
2078
0
        else if (_Py_str_to_int(env, &cpu_count) < 0 || cpu_count < 1) {
2079
0
            goto error;
2080
0
        }
2081
0
        config->cpu_count = cpu_count;
2082
0
    }
2083
2084
36
    const wchar_t *xoption = config_get_xoption(config, L"cpu_count");
2085
36
    if (xoption) {
2086
0
        int cpu_count = -1;
2087
0
        const wchar_t *sep = wcschr(xoption, L'=');
2088
0
        if (sep) {
2089
0
            if (wcscmp(sep + 1, L"default") == 0) {
2090
0
                cpu_count = -1;
2091
0
            }
2092
0
            else if (config_wstr_to_int(sep + 1, &cpu_count) < 0 || cpu_count < 1) {
2093
0
                goto error;
2094
0
            }
2095
0
        }
2096
0
        else {
2097
0
            goto error;
2098
0
        }
2099
0
        config->cpu_count = cpu_count;
2100
0
    }
2101
36
    return _PyStatus_OK();
2102
2103
0
error:
2104
0
    return _PyStatus_ERR("-X cpu_count=n option: n is missing or an invalid number, "
2105
36
                         "n must be greater than 0");
2106
36
}
2107
2108
static PyStatus
2109
config_init_thread_inherit_context(PyConfig *config)
2110
36
{
2111
36
    const char *env = config_get_env(config, "PYTHON_THREAD_INHERIT_CONTEXT");
2112
36
    if (env) {
2113
0
        int enabled;
2114
0
        if (_Py_str_to_int(env, &enabled) < 0 || (enabled < 0) || (enabled > 1)) {
2115
0
            return _PyStatus_ERR(
2116
0
                "PYTHON_THREAD_INHERIT_CONTEXT=N: N is missing or invalid");
2117
0
        }
2118
0
        config->thread_inherit_context = enabled;
2119
0
    }
2120
2121
36
    const wchar_t *xoption = config_get_xoption(config, L"thread_inherit_context");
2122
36
    if (xoption) {
2123
0
        int enabled;
2124
0
        const wchar_t *sep = wcschr(xoption, L'=');
2125
0
        if (!sep || (config_wstr_to_int(sep + 1, &enabled) < 0) || (enabled < 0) || (enabled > 1)) {
2126
0
            return _PyStatus_ERR(
2127
0
                "-X thread_inherit_context=n: n is missing or invalid");
2128
0
        }
2129
0
        config->thread_inherit_context = enabled;
2130
0
    }
2131
36
    return _PyStatus_OK();
2132
36
}
2133
2134
static PyStatus
2135
config_init_context_aware_warnings(PyConfig *config)
2136
36
{
2137
36
    const char *env = config_get_env(config, "PYTHON_CONTEXT_AWARE_WARNINGS");
2138
36
    if (env) {
2139
0
        int enabled;
2140
0
        if (_Py_str_to_int(env, &enabled) < 0 || (enabled < 0) || (enabled > 1)) {
2141
0
            return _PyStatus_ERR(
2142
0
                "PYTHON_CONTEXT_AWARE_WARNINGS=N: N is missing or invalid");
2143
0
        }
2144
0
        config->context_aware_warnings = enabled;
2145
0
    }
2146
2147
36
    const wchar_t *xoption = config_get_xoption(config, L"context_aware_warnings");
2148
36
    if (xoption) {
2149
0
        int enabled;
2150
0
        const wchar_t *sep = wcschr(xoption, L'=');
2151
0
        if (!sep || (config_wstr_to_int(sep + 1, &enabled) < 0) || (enabled < 0) || (enabled > 1)) {
2152
0
            return _PyStatus_ERR(
2153
0
                "-X context_aware_warnings=n: n is missing or invalid");
2154
0
        }
2155
0
        config->context_aware_warnings = enabled;
2156
0
    }
2157
36
    return _PyStatus_OK();
2158
36
}
2159
2160
static PyStatus
2161
config_init_tlbc(PyConfig *config)
2162
36
{
2163
#ifdef Py_GIL_DISABLED
2164
    const char *env = config_get_env(config, "PYTHON_TLBC");
2165
    if (env) {
2166
        int enabled;
2167
        if (_Py_str_to_int(env, &enabled) < 0 || (enabled < 0) || (enabled > 1)) {
2168
            return _PyStatus_ERR(
2169
                "PYTHON_TLBC=N: N is missing or invalid");
2170
        }
2171
        config->tlbc_enabled = enabled;
2172
    }
2173
2174
    const wchar_t *xoption = config_get_xoption(config, L"tlbc");
2175
    if (xoption) {
2176
        int enabled;
2177
        const wchar_t *sep = wcschr(xoption, L'=');
2178
        if (!sep || (config_wstr_to_int(sep + 1, &enabled) < 0) || (enabled < 0) || (enabled > 1)) {
2179
            return _PyStatus_ERR(
2180
                "-X tlbc=n: n is missing or invalid");
2181
        }
2182
        config->tlbc_enabled = enabled;
2183
    }
2184
    return _PyStatus_OK();
2185
#else
2186
36
    return _PyStatus_OK();
2187
36
#endif
2188
36
}
2189
2190
static PyStatus
2191
config_init_perf_profiling(PyConfig *config)
2192
36
{
2193
36
    int active = 0;
2194
36
    const char *env = config_get_env(config, "PYTHONPERFSUPPORT");
2195
36
    if (env) {
2196
0
        if (_Py_str_to_int(env, &active) != 0) {
2197
0
            active = 0;
2198
0
        }
2199
0
        if (active) {
2200
0
            config->perf_profiling = 1;
2201
0
        }
2202
0
    }
2203
36
    const wchar_t *xoption = config_get_xoption(config, L"perf");
2204
36
    if (xoption) {
2205
0
        config->perf_profiling = 1;
2206
0
    }
2207
36
    env = config_get_env(config, "PYTHON_PERF_JIT_SUPPORT");
2208
36
    if (env) {
2209
0
        if (_Py_str_to_int(env, &active) != 0) {
2210
0
            active = 0;
2211
0
        }
2212
0
        if (active) {
2213
0
            config->perf_profiling = 2;
2214
0
        }
2215
0
    }
2216
36
    xoption = config_get_xoption(config, L"perf_jit");
2217
36
    if (xoption) {
2218
0
        config->perf_profiling = 2;
2219
0
    }
2220
2221
36
    return _PyStatus_OK();
2222
2223
36
}
2224
2225
static PyStatus
2226
config_init_remote_debug(PyConfig *config)
2227
36
{
2228
#ifndef Py_REMOTE_DEBUG
2229
    config->remote_debug = 0;
2230
#else
2231
36
    int active = 1;
2232
36
    const char *env = Py_GETENV("PYTHON_DISABLE_REMOTE_DEBUG");
2233
36
    if (env) {
2234
0
        active = 0;
2235
0
    }
2236
36
    const wchar_t *xoption = config_get_xoption(config, L"disable-remote-debug");
2237
36
    if (xoption) {
2238
0
        active = 0;
2239
0
    }
2240
2241
36
    config->remote_debug = active;
2242
36
#endif
2243
36
    return _PyStatus_OK();
2244
2245
36
}
2246
2247
static PyStatus
2248
config_init_tracemalloc(PyConfig *config)
2249
36
{
2250
36
    int nframe;
2251
36
    int valid;
2252
2253
36
    const char *env = config_get_env(config, "PYTHONTRACEMALLOC");
2254
36
    if (env) {
2255
0
        if (!_Py_str_to_int(env, &nframe)) {
2256
0
            valid = (nframe >= 0);
2257
0
        }
2258
0
        else {
2259
0
            valid = 0;
2260
0
        }
2261
0
        if (!valid) {
2262
0
            return _PyStatus_ERR("PYTHONTRACEMALLOC: invalid number of frames");
2263
0
        }
2264
0
        config->tracemalloc = nframe;
2265
0
    }
2266
2267
36
    const wchar_t *xoption = config_get_xoption(config, L"tracemalloc");
2268
36
    if (xoption) {
2269
0
        const wchar_t *sep = wcschr(xoption, L'=');
2270
0
        if (sep) {
2271
0
            if (!config_wstr_to_int(sep + 1, &nframe)) {
2272
0
                valid = (nframe >= 0);
2273
0
            }
2274
0
            else {
2275
0
                valid = 0;
2276
0
            }
2277
0
            if (!valid) {
2278
0
                return _PyStatus_ERR("-X tracemalloc=NFRAME: "
2279
0
                                     "invalid number of frames");
2280
0
            }
2281
0
        }
2282
0
        else {
2283
            /* -X tracemalloc behaves as -X tracemalloc=1 */
2284
0
            nframe = 1;
2285
0
        }
2286
0
        config->tracemalloc = nframe;
2287
0
    }
2288
36
    return _PyStatus_OK();
2289
36
}
2290
2291
static PyStatus
2292
config_init_int_max_str_digits(PyConfig *config)
2293
36
{
2294
36
    int maxdigits;
2295
2296
36
    const char *env = config_get_env(config, "PYTHONINTMAXSTRDIGITS");
2297
36
    if (env) {
2298
0
        bool valid = 0;
2299
0
        if (!_Py_str_to_int(env, &maxdigits)) {
2300
0
            valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
2301
0
        }
2302
0
        if (!valid) {
2303
0
#define STRINGIFY(VAL) _STRINGIFY(VAL)
2304
0
#define _STRINGIFY(VAL) #VAL
2305
0
            return _PyStatus_ERR(
2306
0
                    "PYTHONINTMAXSTRDIGITS: invalid limit; must be >= "
2307
0
                    STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)
2308
0
                    " or 0 for unlimited.");
2309
0
        }
2310
0
        config->int_max_str_digits = maxdigits;
2311
0
    }
2312
2313
36
    const wchar_t *xoption = config_get_xoption(config, L"int_max_str_digits");
2314
36
    if (xoption) {
2315
0
        const wchar_t *sep = wcschr(xoption, L'=');
2316
0
        bool valid = 0;
2317
0
        if (sep) {
2318
0
            if (!config_wstr_to_int(sep + 1, &maxdigits)) {
2319
0
                valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
2320
0
            }
2321
0
        }
2322
0
        if (!valid) {
2323
0
            return _PyStatus_ERR(
2324
0
                    "-X int_max_str_digits: invalid limit; must be >= "
2325
0
                    STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)
2326
0
                    " or 0 for unlimited.");
2327
0
#undef _STRINGIFY
2328
0
#undef STRINGIFY
2329
0
        }
2330
0
        config->int_max_str_digits = maxdigits;
2331
0
    }
2332
36
    if (config->int_max_str_digits < 0) {
2333
36
        config->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;
2334
36
    }
2335
36
    return _PyStatus_OK();
2336
36
}
2337
2338
static PyStatus
2339
config_init_pycache_prefix(PyConfig *config)
2340
36
{
2341
36
    assert(config->pycache_prefix == NULL);
2342
2343
36
    const wchar_t *xoption = config_get_xoption(config, L"pycache_prefix");
2344
36
    if (xoption) {
2345
0
        const wchar_t *sep = wcschr(xoption, L'=');
2346
0
        if (sep && wcslen(sep) > 1) {
2347
0
            config->pycache_prefix = _PyMem_RawWcsdup(sep + 1);
2348
0
            if (config->pycache_prefix == NULL) {
2349
0
                return _PyStatus_NO_MEMORY();
2350
0
            }
2351
0
        }
2352
0
        else {
2353
            // PYTHONPYCACHEPREFIX env var ignored
2354
            // if "-X pycache_prefix=" option is used
2355
0
            config->pycache_prefix = NULL;
2356
0
        }
2357
0
        return _PyStatus_OK();
2358
0
    }
2359
2360
36
    return CONFIG_GET_ENV_DUP(config, &config->pycache_prefix,
2361
36
                              L"PYTHONPYCACHEPREFIX",
2362
36
                              "PYTHONPYCACHEPREFIX");
2363
36
}
2364
2365
2366
#ifdef Py_DEBUG
2367
static PyStatus
2368
config_init_run_presite(PyConfig *config)
2369
{
2370
    assert(config->run_presite == NULL);
2371
2372
    const wchar_t *xoption = config_get_xoption(config, L"presite");
2373
    if (xoption) {
2374
        const wchar_t *sep = wcschr(xoption, L'=');
2375
        if (sep && wcslen(sep) > 1) {
2376
            config->run_presite = _PyMem_RawWcsdup(sep + 1);
2377
            if (config->run_presite == NULL) {
2378
                return _PyStatus_NO_MEMORY();
2379
            }
2380
        }
2381
        else {
2382
            // PYTHON_PRESITE env var ignored
2383
            // if "-X presite=" option is used
2384
            config->run_presite = NULL;
2385
        }
2386
        return _PyStatus_OK();
2387
    }
2388
2389
    return CONFIG_GET_ENV_DUP(config, &config->run_presite,
2390
                              L"PYTHON_PRESITE",
2391
                              "PYTHON_PRESITE");
2392
}
2393
#endif
2394
2395
static PyStatus
2396
config_init_import_time(PyConfig *config)
2397
36
{
2398
36
    int importtime = 0;
2399
2400
36
    const char *env = config_get_env(config, "PYTHONPROFILEIMPORTTIME");
2401
36
    if (env) {
2402
0
        if (_Py_str_to_int(env, &importtime) != 0) {
2403
0
            importtime = 1;
2404
0
        }
2405
0
        if (importtime < 0 || importtime > 2) {
2406
0
            return _PyStatus_ERR(
2407
0
                "PYTHONPROFILEIMPORTTIME: numeric values other than 1 and 2 "
2408
0
                "are reserved for future use.");
2409
0
        }
2410
0
    }
2411
2412
36
    const wchar_t *x_value = config_get_xoption_value(config, L"importtime");
2413
36
    if (x_value) {
2414
0
        if (*x_value == 0 || config_wstr_to_int(x_value, &importtime) != 0) {
2415
0
            importtime = 1;
2416
0
        }
2417
0
        if (importtime < 0 || importtime > 2) {
2418
0
            return _PyStatus_ERR(
2419
0
                "-X importtime: values other than 1 and 2 "
2420
0
                "are reserved for future use.");
2421
0
        }
2422
0
    }
2423
2424
36
    config->import_time = importtime;
2425
36
    return _PyStatus_OK();
2426
36
}
2427
2428
static PyStatus
2429
config_init_lazy_imports(PyConfig *config)
2430
36
{
2431
36
    int lazy_imports = -1;
2432
2433
36
    const char *env = config_get_env(config, "PYTHON_LAZY_IMPORTS");
2434
36
    if (env) {
2435
0
        if (strcmp(env, "all") == 0) {
2436
0
            lazy_imports = 1;
2437
0
        }
2438
0
        else if (strcmp(env, "normal") == 0) {
2439
0
            lazy_imports = -1;
2440
0
        }
2441
0
        else {
2442
0
            return _PyStatus_ERR("PYTHON_LAZY_IMPORTS: invalid value; "
2443
0
                                 "expected 'all' or 'normal'");
2444
0
        }
2445
0
        config->lazy_imports = lazy_imports;
2446
0
    }
2447
2448
36
    const wchar_t *x_value = config_get_xoption_value(config, L"lazy_imports");
2449
36
    if (x_value) {
2450
0
        if (wcscmp(x_value, L"all") == 0) {
2451
0
            lazy_imports = 1;
2452
0
        }
2453
0
        else if (wcscmp(x_value, L"normal") == 0) {
2454
0
            lazy_imports = -1;
2455
0
        }
2456
0
        else {
2457
0
            return _PyStatus_ERR("-X lazy_imports: invalid value; "
2458
0
                                 "expected 'all' or 'normal'");
2459
0
        }
2460
0
        config->lazy_imports = lazy_imports;
2461
0
    }
2462
36
    return _PyStatus_OK();
2463
36
}
2464
2465
static PyStatus
2466
config_init_pathconfig_warnings(PyConfig *config)
2467
36
{
2468
36
    const char *env = config_get_env(config, "PYTHON_PATHCONFIG_WARNINGS");
2469
36
    if (env) {
2470
0
        int enabled;
2471
0
        if (_Py_str_to_int(env, &enabled) < 0 || (enabled < 0) || (enabled > 1)) {
2472
0
            return _PyStatus_ERR(
2473
0
                "PYTHON_PATHCONFIG_WARNINGS=N: N is missing or invalid");
2474
0
        }
2475
0
        config->pathconfig_warnings = enabled;
2476
0
    }
2477
2478
36
    const wchar_t *xoption = config_get_xoption(config, L"pathconfig_warnings");
2479
36
    if (xoption) {
2480
0
        int enabled;
2481
0
        const wchar_t *sep = wcschr(xoption, L'=');
2482
0
        if (!sep || (config_wstr_to_int(sep + 1, &enabled) < 0) || (enabled < 0) || (enabled > 1)) {
2483
0
            return _PyStatus_ERR(
2484
0
                "-X pathconfig_warnings=n: n is missing or invalid");
2485
0
        }
2486
0
        config->pathconfig_warnings = enabled;
2487
0
    }
2488
36
    return _PyStatus_OK();
2489
36
}
2490
2491
static PyStatus
2492
config_read_complex_options(PyConfig *config)
2493
36
{
2494
    /* More complex options configured by env var and -X option */
2495
36
    if (config->faulthandler < 0) {
2496
36
        if (config_get_env(config, "PYTHONFAULTHANDLER")
2497
36
           || config_get_xoption(config, L"faulthandler")) {
2498
0
            config->faulthandler = 1;
2499
0
        }
2500
36
    }
2501
36
    if (config_get_env(config, "PYTHONNODEBUGRANGES")
2502
36
       || config_get_xoption(config, L"no_debug_ranges")) {
2503
0
        config->code_debug_ranges = 0;
2504
0
    }
2505
2506
36
    PyStatus status;
2507
36
    if (config->import_time < 0) {
2508
36
        status = config_init_import_time(config);
2509
36
        if (_PyStatus_EXCEPTION(status)) {
2510
0
            return status;
2511
0
        }
2512
36
    }
2513
2514
36
    if (config->lazy_imports < 0) {
2515
36
        status = config_init_lazy_imports(config);
2516
36
        if (_PyStatus_EXCEPTION(status)) {
2517
0
            return status;
2518
0
        }
2519
36
    }
2520
2521
36
    if (config->tracemalloc < 0) {
2522
36
        status = config_init_tracemalloc(config);
2523
36
        if (_PyStatus_EXCEPTION(status)) {
2524
0
            return status;
2525
0
        }
2526
36
    }
2527
2528
36
    if (config->perf_profiling < 0) {
2529
36
        status = config_init_perf_profiling(config);
2530
36
        if (_PyStatus_EXCEPTION(status)) {
2531
0
            return status;
2532
0
        }
2533
36
    }
2534
2535
36
    if (config->remote_debug < 0) {
2536
36
        status = config_init_remote_debug(config);
2537
36
        if (_PyStatus_EXCEPTION(status)) {
2538
0
            return status;
2539
0
        }
2540
36
    }
2541
2542
36
    if (config->int_max_str_digits < 0) {
2543
36
        status = config_init_int_max_str_digits(config);
2544
36
        if (_PyStatus_EXCEPTION(status)) {
2545
0
            return status;
2546
0
        }
2547
36
    }
2548
2549
36
    if (config->cpu_count < 0) {
2550
36
        status = config_init_cpu_count(config);
2551
36
        if (_PyStatus_EXCEPTION(status)) {
2552
0
            return status;
2553
0
        }
2554
36
    }
2555
2556
36
    if (config->pycache_prefix == NULL) {
2557
36
        status = config_init_pycache_prefix(config);
2558
36
        if (_PyStatus_EXCEPTION(status)) {
2559
0
            return status;
2560
0
        }
2561
36
    }
2562
2563
#ifdef Py_DEBUG
2564
    if (config->run_presite == NULL) {
2565
        status = config_init_run_presite(config);
2566
        if (_PyStatus_EXCEPTION(status)) {
2567
            return status;
2568
        }
2569
    }
2570
#endif
2571
2572
36
    status = config_init_thread_inherit_context(config);
2573
36
    if (_PyStatus_EXCEPTION(status)) {
2574
0
        return status;
2575
0
    }
2576
2577
36
    status = config_init_context_aware_warnings(config);
2578
36
    if (_PyStatus_EXCEPTION(status)) {
2579
0
        return status;
2580
0
    }
2581
2582
36
    status = config_init_tlbc(config);
2583
36
    if (_PyStatus_EXCEPTION(status)) {
2584
0
        return status;
2585
0
    }
2586
2587
36
    status = config_init_pathconfig_warnings(config);
2588
36
    if (_PyStatus_EXCEPTION(status)) {
2589
0
        return status;
2590
0
    }
2591
2592
36
    return _PyStatus_OK();
2593
36
}
2594
2595
2596
static const wchar_t *
2597
config_get_stdio_errors(const PyPreConfig *preconfig)
2598
36
{
2599
36
    if (preconfig->utf8_mode) {
2600
        /* UTF-8 Mode uses UTF-8/surrogateescape */
2601
36
        return L"surrogateescape";
2602
36
    }
2603
2604
0
#ifndef MS_WINDOWS
2605
0
    const char *loc = setlocale(LC_CTYPE, NULL);
2606
0
    if (loc != NULL) {
2607
        /* surrogateescape is the default in the legacy C and POSIX locales */
2608
0
        if (strcmp(loc, "C") == 0 || strcmp(loc, "POSIX") == 0) {
2609
0
            return L"surrogateescape";
2610
0
        }
2611
2612
0
#ifdef PY_COERCE_C_LOCALE
2613
        /* surrogateescape is the default in locale coercion target locales */
2614
0
        if (_Py_IsLocaleCoercionTarget(loc)) {
2615
0
            return L"surrogateescape";
2616
0
        }
2617
0
#endif
2618
0
    }
2619
2620
0
    return L"strict";
2621
#else
2622
    /* On Windows, always use surrogateescape by default */
2623
    return L"surrogateescape";
2624
#endif
2625
0
}
2626
2627
2628
// See also config_get_fs_encoding()
2629
static PyStatus
2630
config_get_locale_encoding(PyConfig *config, const PyPreConfig *preconfig,
2631
                           wchar_t **locale_encoding)
2632
36
{
2633
36
    wchar_t *encoding;
2634
36
    if (preconfig->utf8_mode) {
2635
36
        encoding = _PyMem_RawWcsdup(L"utf-8");
2636
36
    }
2637
0
    else {
2638
0
        encoding = _Py_GetLocaleEncoding();
2639
0
    }
2640
36
    if (encoding == NULL) {
2641
0
        return _PyStatus_NO_MEMORY();
2642
0
    }
2643
36
    PyStatus status = PyConfig_SetString(config, locale_encoding, encoding);
2644
36
    PyMem_RawFree(encoding);
2645
36
    return status;
2646
36
}
2647
2648
2649
static PyStatus
2650
config_init_stdio_encoding(PyConfig *config,
2651
                           const PyPreConfig *preconfig)
2652
36
{
2653
36
    PyStatus status;
2654
2655
    // Exit if encoding and errors are defined
2656
36
    if (config->stdio_encoding != NULL && config->stdio_errors != NULL) {
2657
0
        return _PyStatus_OK();
2658
0
    }
2659
2660
    /* PYTHONIOENCODING environment variable */
2661
36
    const char *opt = config_get_env(config, "PYTHONIOENCODING");
2662
36
    if (opt) {
2663
0
        char *pythonioencoding = _PyMem_RawStrdup(opt);
2664
0
        if (pythonioencoding == NULL) {
2665
0
            return _PyStatus_NO_MEMORY();
2666
0
        }
2667
2668
0
        char *errors = strchr(pythonioencoding, ':');
2669
0
        if (errors) {
2670
0
            *errors = '\0';
2671
0
            errors++;
2672
0
            if (!errors[0]) {
2673
0
                errors = NULL;
2674
0
            }
2675
0
        }
2676
2677
        /* Does PYTHONIOENCODING contain an encoding? */
2678
0
        if (pythonioencoding[0]) {
2679
0
            if (config->stdio_encoding == NULL) {
2680
0
                status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding,
2681
0
                                              pythonioencoding,
2682
0
                                              "PYTHONIOENCODING environment variable");
2683
0
                if (_PyStatus_EXCEPTION(status)) {
2684
0
                    PyMem_RawFree(pythonioencoding);
2685
0
                    return status;
2686
0
                }
2687
0
            }
2688
2689
            /* If the encoding is set but not the error handler,
2690
               use "strict" error handler by default.
2691
               PYTHONIOENCODING=latin1 behaves as
2692
               PYTHONIOENCODING=latin1:strict. */
2693
0
            if (!errors) {
2694
0
                errors = "strict";
2695
0
            }
2696
0
        }
2697
2698
0
        if (config->stdio_errors == NULL && errors != NULL) {
2699
0
            status = CONFIG_SET_BYTES_STR(config, &config->stdio_errors,
2700
0
                                          errors,
2701
0
                                          "PYTHONIOENCODING environment variable");
2702
0
            if (_PyStatus_EXCEPTION(status)) {
2703
0
                PyMem_RawFree(pythonioencoding);
2704
0
                return status;
2705
0
            }
2706
0
        }
2707
2708
0
        PyMem_RawFree(pythonioencoding);
2709
0
    }
2710
2711
    /* Choose the default error handler based on the current locale. */
2712
36
    if (config->stdio_encoding == NULL) {
2713
36
        status = config_get_locale_encoding(config, preconfig,
2714
36
                                            &config->stdio_encoding);
2715
36
        if (_PyStatus_EXCEPTION(status)) {
2716
0
            return status;
2717
0
        }
2718
36
    }
2719
36
    if (config->stdio_errors == NULL) {
2720
36
        const wchar_t *errors = config_get_stdio_errors(preconfig);
2721
36
        assert(errors != NULL);
2722
2723
36
        status = PyConfig_SetString(config, &config->stdio_errors, errors);
2724
36
        if (_PyStatus_EXCEPTION(status)) {
2725
0
            return status;
2726
0
        }
2727
36
    }
2728
2729
36
    return _PyStatus_OK();
2730
36
}
2731
2732
2733
// See also config_get_locale_encoding()
2734
static PyStatus
2735
config_get_fs_encoding(PyConfig *config, const PyPreConfig *preconfig,
2736
                       wchar_t **fs_encoding)
2737
36
{
2738
#ifdef _Py_FORCE_UTF8_FS_ENCODING
2739
    return PyConfig_SetString(config, fs_encoding, L"utf-8");
2740
#elif defined(MS_WINDOWS)
2741
    const wchar_t *encoding;
2742
    if (preconfig->legacy_windows_fs_encoding) {
2743
        // Legacy Windows filesystem encoding: mbcs/replace
2744
        encoding = L"mbcs";
2745
    }
2746
    else {
2747
        // Windows defaults to utf-8/surrogatepass (PEP 529)
2748
        encoding = L"utf-8";
2749
    }
2750
     return PyConfig_SetString(config, fs_encoding, encoding);
2751
#else  // !MS_WINDOWS
2752
36
    if (preconfig->utf8_mode) {
2753
36
        return PyConfig_SetString(config, fs_encoding, L"utf-8");
2754
36
    }
2755
2756
0
    if (_Py_GetForceASCII()) {
2757
0
        return PyConfig_SetString(config, fs_encoding, L"ascii");
2758
0
    }
2759
2760
0
    return config_get_locale_encoding(config, preconfig, fs_encoding);
2761
0
#endif  // !MS_WINDOWS
2762
0
}
2763
2764
2765
static PyStatus
2766
config_init_fs_encoding(PyConfig *config, const PyPreConfig *preconfig)
2767
36
{
2768
36
    PyStatus status;
2769
2770
36
    if (config->filesystem_encoding == NULL) {
2771
36
        status = config_get_fs_encoding(config, preconfig,
2772
36
                                        &config->filesystem_encoding);
2773
36
        if (_PyStatus_EXCEPTION(status)) {
2774
0
            return status;
2775
0
        }
2776
36
    }
2777
2778
36
    if (config->filesystem_errors == NULL) {
2779
36
        const wchar_t *errors;
2780
#ifdef MS_WINDOWS
2781
        if (preconfig->legacy_windows_fs_encoding) {
2782
            errors = L"replace";
2783
        }
2784
        else {
2785
            errors = L"surrogatepass";
2786
        }
2787
#else
2788
36
        errors = L"surrogateescape";
2789
36
#endif
2790
36
        status = PyConfig_SetString(config, &config->filesystem_errors, errors);
2791
36
        if (_PyStatus_EXCEPTION(status)) {
2792
0
            return status;
2793
0
        }
2794
36
    }
2795
36
    return _PyStatus_OK();
2796
36
}
2797
2798
2799
static PyStatus
2800
config_init_import(PyConfig *config, int compute_path_config)
2801
72
{
2802
72
    PyStatus status;
2803
2804
72
    status = _PyConfig_InitPathConfig(config, compute_path_config);
2805
72
    if (_PyStatus_EXCEPTION(status)) {
2806
0
        return status;
2807
0
    }
2808
2809
72
    const char *env = config_get_env(config, "PYTHON_FROZEN_MODULES");
2810
72
    if (env == NULL) {
2811
72
    }
2812
0
    else if (strcmp(env, "on") == 0) {
2813
0
        config->use_frozen_modules = 1;
2814
0
    }
2815
0
    else if (strcmp(env, "off") == 0) {
2816
0
        config->use_frozen_modules = 0;
2817
0
    } else {
2818
0
        return PyStatus_Error("bad value for PYTHON_FROZEN_MODULES "
2819
0
                              "(expected \"on\" or \"off\")");
2820
0
    }
2821
2822
    /* -X frozen_modules=[on|off] */
2823
72
    const wchar_t *value = config_get_xoption_value(config, L"frozen_modules");
2824
72
    if (value == NULL) {
2825
72
    }
2826
0
    else if (wcscmp(value, L"on") == 0) {
2827
0
        config->use_frozen_modules = 1;
2828
0
    }
2829
0
    else if (wcscmp(value, L"off") == 0) {
2830
0
        config->use_frozen_modules = 0;
2831
0
    }
2832
0
    else if (wcslen(value) == 0) {
2833
        // "-X frozen_modules" and "-X frozen_modules=" both imply "on".
2834
0
        config->use_frozen_modules = 1;
2835
0
    }
2836
0
    else {
2837
0
        return PyStatus_Error("bad value for option -X frozen_modules "
2838
0
                              "(expected \"on\" or \"off\")");
2839
0
    }
2840
2841
72
    assert(config->use_frozen_modules >= 0);
2842
72
    return _PyStatus_OK();
2843
72
}
2844
2845
PyStatus
2846
_PyConfig_InitImportConfig(PyConfig *config)
2847
36
{
2848
36
    return config_init_import(config, 1);
2849
36
}
2850
2851
2852
static PyStatus
2853
config_read(PyConfig *config, int compute_path_config)
2854
36
{
2855
36
    PyStatus status;
2856
36
    const PyPreConfig *preconfig = &_PyRuntime.preconfig;
2857
2858
36
    if (config->use_environment) {
2859
36
        status = config_read_env_vars(config);
2860
36
        if (_PyStatus_EXCEPTION(status)) {
2861
0
            return status;
2862
0
        }
2863
36
    }
2864
2865
    /* -X options */
2866
36
    if (config_get_xoption(config, L"showrefcount")) {
2867
0
        config->show_ref_count = 1;
2868
0
    }
2869
2870
36
    const wchar_t *x_gil = config_get_xoption_value(config, L"gil");
2871
36
    if (x_gil != NULL) {
2872
0
        size_t len = wcslen(x_gil);
2873
0
        status = config_read_gil(config, len, x_gil[0]);
2874
0
        if (_PyStatus_EXCEPTION(status)) {
2875
0
            return status;
2876
0
        }
2877
0
    }
2878
2879
#ifdef Py_STATS
2880
    if (config_get_xoption(config, L"pystats")) {
2881
        config->_pystats = 1;
2882
    }
2883
    else if (config_get_env(config, "PYTHONSTATS")) {
2884
        config->_pystats = 1;
2885
    }
2886
    if (config->_pystats < 0) {
2887
        config->_pystats = 0;
2888
    }
2889
#endif
2890
2891
36
    status = config_read_complex_options(config);
2892
36
    if (_PyStatus_EXCEPTION(status)) {
2893
0
        return status;
2894
0
    }
2895
2896
36
    if (config->_install_importlib) {
2897
36
        status = config_init_import(config, compute_path_config);
2898
36
        if (_PyStatus_EXCEPTION(status)) {
2899
0
            return status;
2900
0
        }
2901
36
    }
2902
2903
    /* default values */
2904
36
    if (config->dev_mode) {
2905
0
        if (config->faulthandler < 0) {
2906
0
            config->faulthandler = 1;
2907
0
        }
2908
0
    }
2909
36
    if (config->faulthandler < 0) {
2910
36
        config->faulthandler = 0;
2911
36
    }
2912
36
    if (config->tracemalloc < 0) {
2913
36
        config->tracemalloc = 0;
2914
36
    }
2915
36
    if (config->lazy_imports < 0) {
2916
36
        config->lazy_imports = -1;  // Default is auto/unset
2917
36
    }
2918
36
    if (config->perf_profiling < 0) {
2919
36
        config->perf_profiling = 0;
2920
36
    }
2921
36
    if (config->remote_debug < 0) {
2922
0
        config->remote_debug = -1;
2923
0
    }
2924
36
    if (config->use_hash_seed < 0) {
2925
0
        config->use_hash_seed = 0;
2926
0
        config->hash_seed = 0;
2927
0
    }
2928
2929
36
    if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) {
2930
36
        status = config_init_fs_encoding(config, preconfig);
2931
36
        if (_PyStatus_EXCEPTION(status)) {
2932
0
            return status;
2933
0
        }
2934
36
    }
2935
2936
36
    status = config_init_stdio_encoding(config, preconfig);
2937
36
    if (_PyStatus_EXCEPTION(status)) {
2938
0
        return status;
2939
0
    }
2940
2941
36
    if (config->argv.length < 1) {
2942
        /* Ensure at least one (empty) argument is seen */
2943
36
        status = PyWideStringList_Append(&config->argv, L"");
2944
36
        if (_PyStatus_EXCEPTION(status)) {
2945
0
            return status;
2946
0
        }
2947
36
    }
2948
2949
36
    if (config->check_hash_pycs_mode == NULL) {
2950
36
        status = PyConfig_SetString(config, &config->check_hash_pycs_mode,
2951
36
                                    L"default");
2952
36
        if (_PyStatus_EXCEPTION(status)) {
2953
0
            return status;
2954
0
        }
2955
36
    }
2956
2957
36
    if (config->configure_c_stdio < 0) {
2958
0
        config->configure_c_stdio = 1;
2959
0
    }
2960
2961
    // Only parse arguments once.
2962
36
    if (config->parse_argv == 1) {
2963
0
        config->parse_argv = 2;
2964
0
    }
2965
2966
36
    return _PyStatus_OK();
2967
36
}
2968
2969
2970
static void
2971
config_init_stdio(const PyConfig *config)
2972
0
{
2973
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
2974
    /* don't translate newlines (\r\n <=> \n) */
2975
    _setmode(fileno(stdin), O_BINARY);
2976
    _setmode(fileno(stdout), O_BINARY);
2977
    _setmode(fileno(stderr), O_BINARY);
2978
#endif
2979
2980
0
    if (!config->buffered_stdio) {
2981
0
#ifdef HAVE_SETVBUF
2982
0
        setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);
2983
0
        setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
2984
0
        setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
2985
#else /* !HAVE_SETVBUF */
2986
        setbuf(stdin,  (char *)NULL);
2987
        setbuf(stdout, (char *)NULL);
2988
        setbuf(stderr, (char *)NULL);
2989
#endif /* !HAVE_SETVBUF */
2990
0
    }
2991
0
    else if (config->interactive) {
2992
#ifdef MS_WINDOWS
2993
        /* Doesn't have to have line-buffered -- use unbuffered */
2994
        /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */
2995
        setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
2996
#else /* !MS_WINDOWS */
2997
0
#ifdef HAVE_SETVBUF
2998
0
        setvbuf(stdin,  (char *)NULL, _IOLBF, BUFSIZ);
2999
0
        setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
3000
0
#endif /* HAVE_SETVBUF */
3001
0
#endif /* !MS_WINDOWS */
3002
        /* Leave stderr alone - it should be unbuffered anyway. */
3003
0
    }
3004
0
}
3005
3006
3007
/* Write the configuration:
3008
3009
   - set Py_xxx global configuration variables
3010
   - initialize C standard streams (stdin, stdout, stderr) */
3011
PyStatus
3012
_PyConfig_Write(const PyConfig *config, _PyRuntimeState *runtime)
3013
36
{
3014
36
    config_set_global_vars(config);
3015
3016
36
    if (config->configure_c_stdio) {
3017
0
        config_init_stdio(config);
3018
0
    }
3019
3020
    /* Write the new pre-configuration into _PyRuntime */
3021
36
    PyPreConfig *preconfig = &runtime->preconfig;
3022
36
    preconfig->isolated = config->isolated;
3023
36
    preconfig->use_environment = config->use_environment;
3024
36
    preconfig->dev_mode = config->dev_mode;
3025
3026
36
    if (_Py_SetArgcArgv(config->orig_argv.length,
3027
36
                        config->orig_argv.items) < 0)
3028
0
    {
3029
0
        return _PyStatus_NO_MEMORY();
3030
0
    }
3031
3032
#ifdef PYMALLOC_USE_HUGEPAGES
3033
    runtime->allocators.use_hugepages = config->pymalloc_hugepages;
3034
#endif
3035
3036
36
    return _PyStatus_OK();
3037
36
}
3038
3039
3040
/* --- PyConfig command line parser -------------------------- */
3041
3042
static void
3043
config_usage(int error, const wchar_t* program)
3044
0
{
3045
0
    FILE *f = error ? stderr : stdout;
3046
0
    int colorize = _Py_can_colorize(f);
3047
3048
0
    fprint_help(f, usage_line, colorize, program);
3049
0
    if (error) {
3050
0
        fprintf(f, "Try `python -h' for more information.\n");
3051
0
    }
3052
0
    else {
3053
0
        fprint_help(f, usage_help, colorize, NULL);
3054
0
    }
3055
0
}
3056
3057
static void
3058
config_envvars_usage(void)
3059
0
{
3060
0
    int colorize = _Py_can_colorize(stdout);
3061
0
    fprint_help(stdout, usage_envvars, colorize, NULL);
3062
0
}
3063
3064
static void
3065
config_xoptions_usage(void)
3066
0
{
3067
0
    int colorize = _Py_can_colorize(stdout);
3068
0
    fprint_help(stdout, usage_xoptions, colorize, NULL);
3069
0
}
3070
3071
static void
3072
config_complete_usage(const wchar_t* program)
3073
0
{
3074
0
   config_usage(0, program);
3075
0
   putchar('\n');
3076
0
   config_envvars_usage();
3077
0
   putchar('\n');
3078
0
   config_xoptions_usage();
3079
0
}
3080
3081
3082
/* Parse the command line arguments */
3083
static PyStatus
3084
config_parse_cmdline(PyConfig *config, PyWideStringList *warnoptions,
3085
                     Py_ssize_t *opt_index)
3086
0
{
3087
0
    PyStatus status;
3088
0
    const PyWideStringList *argv = &config->argv;
3089
0
    int print_version = 0;
3090
0
    const wchar_t* program = config->program_name;
3091
0
    if (!program && argv->length >= 1) {
3092
0
        program = argv->items[0];
3093
0
    }
3094
3095
0
    _PyOS_ResetGetOpt();
3096
0
    do {
3097
0
        int longindex = -1;
3098
0
        int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
3099
0
        if (c == EOF) {
3100
0
            break;
3101
0
        }
3102
3103
0
        if (c == 'c') {
3104
0
            if (config->run_command == NULL) {
3105
                /* -c is the last option; following arguments
3106
                   that look like options are left for the
3107
                   command to interpret. */
3108
0
                size_t len = wcslen(_PyOS_optarg) + 1 + 1;
3109
0
                wchar_t *command = PyMem_RawMalloc(sizeof(wchar_t) * len);
3110
0
                if (command == NULL) {
3111
0
                    return _PyStatus_NO_MEMORY();
3112
0
                }
3113
0
                memcpy(command, _PyOS_optarg, (len - 2) * sizeof(wchar_t));
3114
0
                command[len - 2] = '\n';
3115
0
                command[len - 1] = 0;
3116
0
                config->run_command = command;
3117
0
            }
3118
0
            break;
3119
0
        }
3120
3121
0
        if (c == 'm') {
3122
            /* -m is the last option; following arguments
3123
               that look like options are left for the
3124
               module to interpret. */
3125
0
            if (config->run_module == NULL) {
3126
0
                config->run_module = _PyMem_RawWcsdup(_PyOS_optarg);
3127
0
                if (config->run_module == NULL) {
3128
0
                    return _PyStatus_NO_MEMORY();
3129
0
                }
3130
0
            }
3131
0
            break;
3132
0
        }
3133
3134
0
        switch (c) {
3135
        // Integers represent long options, see Python/getopt.c
3136
0
        case 0:
3137
            // check-hash-based-pycs
3138
0
            if (wcscmp(_PyOS_optarg, L"always") == 0
3139
0
                || wcscmp(_PyOS_optarg, L"never") == 0
3140
0
                || wcscmp(_PyOS_optarg, L"default") == 0)
3141
0
            {
3142
0
                status = PyConfig_SetString(config, &config->check_hash_pycs_mode,
3143
0
                                            _PyOS_optarg);
3144
0
                if (_PyStatus_EXCEPTION(status)) {
3145
0
                    return status;
3146
0
                }
3147
0
            } else {
3148
0
                fprintf(stderr, "--check-hash-based-pycs must be one of "
3149
0
                        "'default', 'always', or 'never'\n");
3150
0
                config_usage(1, program);
3151
0
                return _PyStatus_EXIT(2);
3152
0
            }
3153
0
            break;
3154
3155
0
        case 1:
3156
            // help-all
3157
0
            config_complete_usage(program);
3158
0
            return _PyStatus_EXIT(0);
3159
3160
0
        case 2:
3161
            // help-env
3162
0
            config_envvars_usage();
3163
0
            return _PyStatus_EXIT(0);
3164
3165
0
        case 3:
3166
            // help-xoptions
3167
0
            config_xoptions_usage();
3168
0
            return _PyStatus_EXIT(0);
3169
3170
0
        case 'b':
3171
0
            config->bytes_warning++;
3172
0
            break;
3173
3174
0
        case 'd':
3175
0
            config->parser_debug++;
3176
0
            break;
3177
3178
0
        case 'i':
3179
0
            config->inspect++;
3180
0
            config->interactive++;
3181
0
            break;
3182
3183
0
        case 'E':
3184
0
        case 'I':
3185
0
        case 'X':
3186
            /* option handled by _PyPreCmdline_Read() */
3187
0
            break;
3188
3189
0
        case 'O':
3190
0
            config->optimization_level++;
3191
0
            break;
3192
3193
0
        case 'P':
3194
0
            config->safe_path = 1;
3195
0
            break;
3196
3197
0
        case 'B':
3198
0
            config->write_bytecode = 0;
3199
0
            break;
3200
3201
0
        case 's':
3202
0
            config->user_site_directory = 0;
3203
0
            break;
3204
3205
0
        case 'S':
3206
0
            config->site_import = 0;
3207
0
            break;
3208
3209
0
        case 't':
3210
            /* ignored for backwards compatibility */
3211
0
            break;
3212
3213
0
        case 'u':
3214
0
            config->buffered_stdio = 0;
3215
0
            break;
3216
3217
0
        case 'v':
3218
0
            config->verbose++;
3219
0
            break;
3220
3221
0
        case 'x':
3222
0
            config->skip_source_first_line = 1;
3223
0
            break;
3224
3225
0
        case 'h':
3226
0
        case '?':
3227
0
            config_usage(0, program);
3228
0
            return _PyStatus_EXIT(0);
3229
3230
0
        case 'V':
3231
0
            print_version++;
3232
0
            break;
3233
3234
0
        case 'W':
3235
0
            status = PyWideStringList_Append(warnoptions, _PyOS_optarg);
3236
0
            if (_PyStatus_EXCEPTION(status)) {
3237
0
                return status;
3238
0
            }
3239
0
            break;
3240
3241
0
        case 'q':
3242
0
            config->quiet++;
3243
0
            break;
3244
3245
0
        case 'R':
3246
0
            config->use_hash_seed = 0;
3247
0
            break;
3248
3249
        /* This space reserved for other options */
3250
3251
0
        default:
3252
            /* unknown argument: parsing failed */
3253
0
            config_usage(1, program);
3254
0
            return _PyStatus_EXIT(2);
3255
0
        }
3256
0
    } while (1);
3257
3258
0
    if (print_version) {
3259
0
        printf("Python %s\n",
3260
0
                (print_version >= 2) ? Py_GetVersion() : PY_VERSION);
3261
0
        return _PyStatus_EXIT(0);
3262
0
    }
3263
3264
0
    if (config->run_command == NULL && config->run_module == NULL
3265
0
        && _PyOS_optind < argv->length
3266
0
        && wcscmp(argv->items[_PyOS_optind], L"-") != 0
3267
0
        && config->run_filename == NULL)
3268
0
    {
3269
0
        config->run_filename = _PyMem_RawWcsdup(argv->items[_PyOS_optind]);
3270
0
        if (config->run_filename == NULL) {
3271
0
            return _PyStatus_NO_MEMORY();
3272
0
        }
3273
0
    }
3274
3275
0
    if (config->run_command != NULL || config->run_module != NULL) {
3276
        /* Backup _PyOS_optind */
3277
0
        _PyOS_optind--;
3278
0
    }
3279
3280
0
    *opt_index = _PyOS_optind;
3281
3282
0
    return _PyStatus_OK();
3283
0
}
3284
3285
3286
#ifdef MS_WINDOWS
3287
#  define WCSTOK wcstok_s
3288
#else
3289
0
#  define WCSTOK wcstok
3290
#endif
3291
3292
/* Get warning options from PYTHONWARNINGS environment variable. */
3293
static PyStatus
3294
config_init_env_warnoptions(PyConfig *config, PyWideStringList *warnoptions)
3295
36
{
3296
36
    PyStatus status;
3297
    /* CONFIG_GET_ENV_DUP requires dest to be initialized to NULL */
3298
36
    wchar_t *env = NULL;
3299
36
    status = CONFIG_GET_ENV_DUP(config, &env,
3300
36
                             L"PYTHONWARNINGS", "PYTHONWARNINGS");
3301
36
    if (_PyStatus_EXCEPTION(status)) {
3302
0
        return status;
3303
0
    }
3304
3305
    /* env var is not set or is empty */
3306
36
    if (env == NULL) {
3307
36
        return _PyStatus_OK();
3308
36
    }
3309
3310
3311
0
    wchar_t *warning, *context = NULL;
3312
0
    for (warning = WCSTOK(env, L",", &context);
3313
0
         warning != NULL;
3314
0
         warning = WCSTOK(NULL, L",", &context))
3315
0
    {
3316
0
        status = PyWideStringList_Append(warnoptions, warning);
3317
0
        if (_PyStatus_EXCEPTION(status)) {
3318
0
            PyMem_RawFree(env);
3319
0
            return status;
3320
0
        }
3321
0
    }
3322
0
    PyMem_RawFree(env);
3323
0
    return _PyStatus_OK();
3324
0
}
3325
3326
3327
static PyStatus
3328
warnoptions_append(PyConfig *config, PyWideStringList *options,
3329
                   const wchar_t *option)
3330
0
{
3331
    /* config_init_warnoptions() add existing config warnoptions at the end:
3332
       ensure that the new option is not already present in this list to
3333
       prevent change the options order when config_init_warnoptions() is
3334
       called twice. */
3335
0
    if (_PyWideStringList_Find(&config->warnoptions, option)) {
3336
        /* Already present: do nothing */
3337
0
        return _PyStatus_OK();
3338
0
    }
3339
0
    if (_PyWideStringList_Find(options, option)) {
3340
        /* Already present: do nothing */
3341
0
        return _PyStatus_OK();
3342
0
    }
3343
0
    return PyWideStringList_Append(options, option);
3344
0
}
3345
3346
3347
static PyStatus
3348
warnoptions_extend(PyConfig *config, PyWideStringList *options,
3349
                   const PyWideStringList *options2)
3350
108
{
3351
108
    const Py_ssize_t len = options2->length;
3352
108
    wchar_t *const *items = options2->items;
3353
3354
108
    for (Py_ssize_t i = 0; i < len; i++) {
3355
0
        PyStatus status = warnoptions_append(config, options, items[i]);
3356
0
        if (_PyStatus_EXCEPTION(status)) {
3357
0
            return status;
3358
0
        }
3359
0
    }
3360
108
    return _PyStatus_OK();
3361
108
}
3362
3363
3364
static PyStatus
3365
config_init_warnoptions(PyConfig *config,
3366
                        const PyWideStringList *cmdline_warnoptions,
3367
                        const PyWideStringList *env_warnoptions,
3368
                        const PyWideStringList *sys_warnoptions)
3369
36
{
3370
36
    PyStatus status;
3371
36
    PyWideStringList options = _PyWideStringList_INIT;
3372
3373
    /* Priority of warnings options, lowest to highest:
3374
     *
3375
     * - any implicit filters added by _warnings.c/warnings.py
3376
     * - PyConfig.dev_mode: "default" filter
3377
     * - PYTHONWARNINGS environment variable
3378
     * - '-W' command line options
3379
     * - PyConfig.bytes_warning ('-b' and '-bb' command line options):
3380
     *   "default::BytesWarning" or "error::BytesWarning" filter
3381
     * - early PySys_AddWarnOption() calls
3382
     * - PyConfig.warnoptions
3383
     *
3384
     * PyConfig.warnoptions is copied to sys.warnoptions. Since the warnings
3385
     * module works on the basis of "the most recently added filter will be
3386
     * checked first", we add the lowest precedence entries first so that later
3387
     * entries override them.
3388
     */
3389
3390
36
    if (config->dev_mode) {
3391
0
        status = warnoptions_append(config, &options, L"default");
3392
0
        if (_PyStatus_EXCEPTION(status)) {
3393
0
            goto error;
3394
0
        }
3395
0
    }
3396
3397
36
    status = warnoptions_extend(config, &options, env_warnoptions);
3398
36
    if (_PyStatus_EXCEPTION(status)) {
3399
0
        goto error;
3400
0
    }
3401
3402
36
    status = warnoptions_extend(config, &options, cmdline_warnoptions);
3403
36
    if (_PyStatus_EXCEPTION(status)) {
3404
0
        goto error;
3405
0
    }
3406
3407
    /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c
3408
     * don't even try to emit a warning, so we skip setting the filter in that
3409
     * case.
3410
     */
3411
36
    if (config->bytes_warning) {
3412
0
        const wchar_t *filter;
3413
0
        if (config->bytes_warning> 1) {
3414
0
            filter = L"error::BytesWarning";
3415
0
        }
3416
0
        else {
3417
0
            filter = L"default::BytesWarning";
3418
0
        }
3419
0
        status = warnoptions_append(config, &options, filter);
3420
0
        if (_PyStatus_EXCEPTION(status)) {
3421
0
            goto error;
3422
0
        }
3423
0
    }
3424
3425
36
    status = warnoptions_extend(config, &options, sys_warnoptions);
3426
36
    if (_PyStatus_EXCEPTION(status)) {
3427
0
        goto error;
3428
0
    }
3429
3430
    /* Always add all PyConfig.warnoptions options */
3431
36
    status = _PyWideStringList_Extend(&options, &config->warnoptions);
3432
36
    if (_PyStatus_EXCEPTION(status)) {
3433
0
        goto error;
3434
0
    }
3435
3436
36
    _PyWideStringList_Clear(&config->warnoptions);
3437
36
    config->warnoptions = options;
3438
36
    return _PyStatus_OK();
3439
3440
0
error:
3441
0
    _PyWideStringList_Clear(&options);
3442
0
    return status;
3443
36
}
3444
3445
3446
static PyStatus
3447
config_update_argv(PyConfig *config, Py_ssize_t opt_index)
3448
0
{
3449
0
    const PyWideStringList *cmdline_argv = &config->argv;
3450
0
    PyWideStringList config_argv = _PyWideStringList_INIT;
3451
3452
    /* Copy argv to be able to modify it (to force -c/-m) */
3453
0
    if (cmdline_argv->length <= opt_index) {
3454
        /* Ensure at least one (empty) argument is seen */
3455
0
        PyStatus status = PyWideStringList_Append(&config_argv, L"");
3456
0
        if (_PyStatus_EXCEPTION(status)) {
3457
0
            return status;
3458
0
        }
3459
0
    }
3460
0
    else {
3461
0
        PyWideStringList slice;
3462
0
        slice.length = cmdline_argv->length - opt_index;
3463
0
        slice.items = &cmdline_argv->items[opt_index];
3464
0
        if (_PyWideStringList_Copy(&config_argv, &slice) < 0) {
3465
0
            return _PyStatus_NO_MEMORY();
3466
0
        }
3467
0
    }
3468
0
    assert(config_argv.length >= 1);
3469
3470
0
    wchar_t *arg0 = NULL;
3471
0
    if (config->run_command != NULL) {
3472
        /* Force sys.argv[0] = '-c' */
3473
0
        arg0 = L"-c";
3474
0
    }
3475
0
    else if (config->run_module != NULL) {
3476
        /* Force sys.argv[0] = '-m'*/
3477
0
        arg0 = L"-m";
3478
0
    }
3479
3480
0
    if (arg0 != NULL) {
3481
0
        arg0 = _PyMem_RawWcsdup(arg0);
3482
0
        if (arg0 == NULL) {
3483
0
            _PyWideStringList_Clear(&config_argv);
3484
0
            return _PyStatus_NO_MEMORY();
3485
0
        }
3486
3487
0
        PyMem_RawFree(config_argv.items[0]);
3488
0
        config_argv.items[0] = arg0;
3489
0
    }
3490
3491
0
    _PyWideStringList_Clear(&config->argv);
3492
0
    config->argv = config_argv;
3493
0
    return _PyStatus_OK();
3494
0
}
3495
3496
3497
static PyStatus
3498
core_read_precmdline(PyConfig *config, _PyPreCmdline *precmdline)
3499
36
{
3500
36
    PyStatus status;
3501
3502
36
    if (config->parse_argv == 1) {
3503
0
        if (_PyWideStringList_Copy(&precmdline->argv, &config->argv) < 0) {
3504
0
            return _PyStatus_NO_MEMORY();
3505
0
        }
3506
0
    }
3507
3508
36
    PyPreConfig preconfig;
3509
3510
36
    status = _PyPreConfig_InitFromPreConfig(&preconfig, &_PyRuntime.preconfig);
3511
36
    if (_PyStatus_EXCEPTION(status)) {
3512
0
        return status;
3513
0
    }
3514
3515
36
    _PyPreConfig_GetConfig(&preconfig, config);
3516
3517
36
    status = _PyPreCmdline_Read(precmdline, &preconfig);
3518
36
    if (_PyStatus_EXCEPTION(status)) {
3519
0
        return status;
3520
0
    }
3521
3522
36
    status = _PyPreCmdline_SetConfig(precmdline, config);
3523
36
    if (_PyStatus_EXCEPTION(status)) {
3524
0
        return status;
3525
0
    }
3526
36
    return _PyStatus_OK();
3527
36
}
3528
3529
3530
/* Get run_filename absolute path */
3531
static PyStatus
3532
config_run_filename_abspath(PyConfig *config)
3533
36
{
3534
36
    if (!config->run_filename) {
3535
36
        return _PyStatus_OK();
3536
36
    }
3537
3538
0
#ifndef MS_WINDOWS
3539
0
    if (_Py_isabs(config->run_filename)) {
3540
        /* path is already absolute */
3541
0
        return _PyStatus_OK();
3542
0
    }
3543
0
#endif
3544
3545
0
    wchar_t *abs_filename;
3546
0
    if (_Py_abspath(config->run_filename, &abs_filename) < 0) {
3547
        /* failed to get the absolute path of the command line filename:
3548
           ignore the error, keep the relative path */
3549
0
        return _PyStatus_OK();
3550
0
    }
3551
0
    if (abs_filename == NULL) {
3552
0
        return _PyStatus_NO_MEMORY();
3553
0
    }
3554
3555
0
    PyMem_RawFree(config->run_filename);
3556
0
    config->run_filename = abs_filename;
3557
0
    return _PyStatus_OK();
3558
0
}
3559
3560
3561
static PyStatus
3562
config_read_cmdline(PyConfig *config)
3563
36
{
3564
36
    PyStatus status;
3565
36
    PyWideStringList cmdline_warnoptions = _PyWideStringList_INIT;
3566
36
    PyWideStringList env_warnoptions = _PyWideStringList_INIT;
3567
36
    PyWideStringList sys_warnoptions = _PyWideStringList_INIT;
3568
3569
36
    if (config->parse_argv < 0) {
3570
0
        config->parse_argv = 1;
3571
0
    }
3572
3573
36
    if (config->parse_argv == 1) {
3574
0
        Py_ssize_t opt_index;
3575
0
        status = config_parse_cmdline(config, &cmdline_warnoptions, &opt_index);
3576
0
        if (_PyStatus_EXCEPTION(status)) {
3577
0
            goto done;
3578
0
        }
3579
3580
0
        status = config_run_filename_abspath(config);
3581
0
        if (_PyStatus_EXCEPTION(status)) {
3582
0
            goto done;
3583
0
        }
3584
3585
0
        status = config_update_argv(config, opt_index);
3586
0
        if (_PyStatus_EXCEPTION(status)) {
3587
0
            goto done;
3588
0
        }
3589
0
    }
3590
36
    else {
3591
36
        status = config_run_filename_abspath(config);
3592
36
        if (_PyStatus_EXCEPTION(status)) {
3593
0
            goto done;
3594
0
        }
3595
36
    }
3596
3597
36
    if (config->use_environment) {
3598
36
        status = config_init_env_warnoptions(config, &env_warnoptions);
3599
36
        if (_PyStatus_EXCEPTION(status)) {
3600
0
            goto done;
3601
0
        }
3602
36
    }
3603
3604
    /* Handle early PySys_AddWarnOption() calls */
3605
36
    status = _PySys_ReadPreinitWarnOptions(&sys_warnoptions);
3606
36
    if (_PyStatus_EXCEPTION(status)) {
3607
0
        goto done;
3608
0
    }
3609
3610
36
    status = config_init_warnoptions(config,
3611
36
                                     &cmdline_warnoptions,
3612
36
                                     &env_warnoptions,
3613
36
                                     &sys_warnoptions);
3614
36
    if (_PyStatus_EXCEPTION(status)) {
3615
0
        goto done;
3616
0
    }
3617
3618
36
    status = _PyStatus_OK();
3619
3620
36
done:
3621
36
    _PyWideStringList_Clear(&cmdline_warnoptions);
3622
36
    _PyWideStringList_Clear(&env_warnoptions);
3623
36
    _PyWideStringList_Clear(&sys_warnoptions);
3624
36
    return status;
3625
36
}
3626
3627
3628
PyStatus
3629
_PyConfig_SetPyArgv(PyConfig *config, const _PyArgv *args)
3630
0
{
3631
0
    PyStatus status = _Py_PreInitializeFromConfig(config, args);
3632
0
    if (_PyStatus_EXCEPTION(status)) {
3633
0
        return status;
3634
0
    }
3635
3636
0
    return _PyArgv_AsWstrList(args, &config->argv);
3637
0
}
3638
3639
3640
/* Set config.argv: decode argv using Py_DecodeLocale(). Pre-initialize Python
3641
   if needed to ensure that encodings are properly configured. */
3642
PyStatus
3643
PyConfig_SetBytesArgv(PyConfig *config, Py_ssize_t argc, char * const *argv)
3644
0
{
3645
0
    _PyArgv args = {
3646
0
        .argc = argc,
3647
0
        .use_bytes_argv = 1,
3648
0
        .bytes_argv = argv,
3649
0
        .wchar_argv = NULL};
3650
0
    return _PyConfig_SetPyArgv(config, &args);
3651
0
}
3652
3653
3654
PyStatus
3655
PyConfig_SetArgv(PyConfig *config, Py_ssize_t argc, wchar_t * const *argv)
3656
0
{
3657
0
    _PyArgv args = {
3658
0
        .argc = argc,
3659
0
        .use_bytes_argv = 0,
3660
0
        .bytes_argv = NULL,
3661
0
        .wchar_argv = argv};
3662
0
    return _PyConfig_SetPyArgv(config, &args);
3663
0
}
3664
3665
3666
PyStatus
3667
PyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list,
3668
                           Py_ssize_t length, wchar_t **items)
3669
0
{
3670
0
    PyStatus status = _Py_PreInitializeFromConfig(config, NULL);
3671
0
    if (_PyStatus_EXCEPTION(status)) {
3672
0
        return status;
3673
0
    }
3674
3675
0
    PyWideStringList list2 = {.length = length, .items = items};
3676
0
    if (_PyWideStringList_Copy(list, &list2) < 0) {
3677
0
        return _PyStatus_NO_MEMORY();
3678
0
    }
3679
0
    return _PyStatus_OK();
3680
0
}
3681
3682
3683
#ifdef __CYGWIN__
3684
// Cygwin strips ".exe" suffix from argv[0].
3685
// Add again the ".exe" suffix.
3686
static PyStatus
3687
config_argv0_add_exe(PyConfig *config)
3688
{
3689
    if (config->argv.length < 1) {
3690
        return _PyStatus_OK();
3691
    }
3692
    const wchar_t *argv0 = config->argv.items[0];
3693
    size_t len = wcslen(argv0);
3694
    if (len >= 5 && wcscmp(argv0 + len - 4, L".exe") == 0) {
3695
        return _PyStatus_OK();
3696
    }
3697
3698
    wchar_t *exe = PyMem_RawMalloc((len + 4 + 1) * sizeof(wchar_t));
3699
    if (exe == NULL) {
3700
        return _PyStatus_NO_MEMORY();
3701
    }
3702
    wcscpy(exe, argv0);
3703
    wcscat(exe, L".exe");
3704
3705
    FILE *fp = _Py_wfopen(exe, L"rb");
3706
    if (fp != NULL) {
3707
        fclose(fp);
3708
3709
        PyMem_RawFree(config->argv.items[0]);
3710
        config->argv.items[0] = exe;
3711
    }
3712
    else {
3713
        PyMem_RawFree(exe);
3714
    }
3715
3716
    return _PyStatus_OK();
3717
}
3718
#endif
3719
3720
3721
/* Read the configuration into PyConfig from:
3722
3723
   * Command line arguments
3724
   * Environment variables
3725
   * Py_xxx global configuration variables
3726
3727
   The only side effects are to modify config and to call _Py_SetArgcArgv(). */
3728
PyStatus
3729
_PyConfig_Read(PyConfig *config, int compute_path_config)
3730
36
{
3731
36
    PyStatus status;
3732
3733
36
    status = _Py_PreInitializeFromConfig(config, NULL);
3734
36
    if (_PyStatus_EXCEPTION(status)) {
3735
0
        return status;
3736
0
    }
3737
3738
36
    config_get_global_vars(config);
3739
3740
#ifdef __CYGWIN__
3741
    status = config_argv0_add_exe(config);
3742
    if (_PyStatus_EXCEPTION(status)) {
3743
        return status;
3744
    }
3745
#endif
3746
3747
36
    if (config->orig_argv.length == 0
3748
36
        && !(config->argv.length == 1
3749
0
             && wcscmp(config->argv.items[0], L"") == 0))
3750
36
    {
3751
36
        if (_PyWideStringList_Copy(&config->orig_argv, &config->argv) < 0) {
3752
0
            return _PyStatus_NO_MEMORY();
3753
0
        }
3754
36
    }
3755
3756
36
    _PyPreCmdline precmdline = _PyPreCmdline_INIT;
3757
36
    status = core_read_precmdline(config, &precmdline);
3758
36
    if (_PyStatus_EXCEPTION(status)) {
3759
0
        goto done;
3760
0
    }
3761
3762
36
    assert(config->isolated >= 0);
3763
36
    if (config->isolated) {
3764
0
        config->safe_path = 1;
3765
0
        config->use_environment = 0;
3766
0
        config->user_site_directory = 0;
3767
0
    }
3768
3769
36
    status = config_read_cmdline(config);
3770
36
    if (_PyStatus_EXCEPTION(status)) {
3771
0
        goto done;
3772
0
    }
3773
3774
    /* Handle early PySys_AddXOption() calls */
3775
36
    status = _PySys_ReadPreinitXOptions(config);
3776
36
    if (_PyStatus_EXCEPTION(status)) {
3777
0
        goto done;
3778
0
    }
3779
3780
36
    status = config_read(config, compute_path_config);
3781
36
    if (_PyStatus_EXCEPTION(status)) {
3782
0
        goto done;
3783
0
    }
3784
3785
36
    assert(config_check_consistency(config));
3786
3787
36
    status = _PyStatus_OK();
3788
3789
36
done:
3790
36
    _PyPreCmdline_Clear(&precmdline);
3791
36
    return status;
3792
36
}
3793
3794
3795
PyStatus
3796
PyConfig_Read(PyConfig *config)
3797
0
{
3798
0
    return _PyConfig_Read(config, 0);
3799
0
}
3800
3801
3802
PyObject*
3803
_Py_GetConfigsAsDict(void)
3804
0
{
3805
0
    PyObject *result = NULL;
3806
0
    PyObject *dict = NULL;
3807
3808
0
    result = PyDict_New();
3809
0
    if (result == NULL) {
3810
0
        goto error;
3811
0
    }
3812
3813
    /* global result */
3814
0
    dict = _Py_GetGlobalVariablesAsDict();
3815
0
    if (dict == NULL) {
3816
0
        goto error;
3817
0
    }
3818
0
    if (PyDict_SetItemString(result, "global_config", dict) < 0) {
3819
0
        goto error;
3820
0
    }
3821
0
    Py_CLEAR(dict);
3822
3823
    /* pre config */
3824
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
3825
0
    const PyPreConfig *pre_config = &interp->runtime->preconfig;
3826
0
    dict = _PyPreConfig_AsDict(pre_config);
3827
0
    if (dict == NULL) {
3828
0
        goto error;
3829
0
    }
3830
0
    if (PyDict_SetItemString(result, "pre_config", dict) < 0) {
3831
0
        goto error;
3832
0
    }
3833
0
    Py_CLEAR(dict);
3834
3835
    /* core config */
3836
0
    const PyConfig *config = _PyInterpreterState_GetConfig(interp);
3837
0
    dict = _PyConfig_AsDict(config);
3838
0
    if (dict == NULL) {
3839
0
        goto error;
3840
0
    }
3841
0
    if (PyDict_SetItemString(result, "config", dict) < 0) {
3842
0
        goto error;
3843
0
    }
3844
0
    Py_CLEAR(dict);
3845
3846
0
    return result;
3847
3848
0
error:
3849
0
    Py_XDECREF(result);
3850
0
    Py_XDECREF(dict);
3851
0
    return NULL;
3852
0
}
3853
3854
3855
static void
3856
init_dump_ascii_wstr(const wchar_t *str)
3857
0
{
3858
0
    if (str == NULL) {
3859
0
        PySys_WriteStderr("(not set)");
3860
0
        return;
3861
0
    }
3862
3863
0
    PySys_WriteStderr("'");
3864
0
    for (; *str != L'\0'; str++) {
3865
0
        unsigned int ch = (unsigned int)*str;
3866
0
        if (ch == L'\'') {
3867
0
            PySys_WriteStderr("\\'");
3868
0
        } else if (0x20 <= ch && ch < 0x7f) {
3869
0
            PySys_WriteStderr("%c", ch);
3870
0
        }
3871
0
        else if (ch <= 0xff) {
3872
0
            PySys_WriteStderr("\\x%02x", ch);
3873
0
        }
3874
0
#if SIZEOF_WCHAR_T > 2
3875
0
        else if (ch > 0xffff) {
3876
0
            PySys_WriteStderr("\\U%08x", ch);
3877
0
        }
3878
0
#endif
3879
0
        else {
3880
0
            PySys_WriteStderr("\\u%04x", ch);
3881
0
        }
3882
0
    }
3883
0
    PySys_WriteStderr("'");
3884
0
}
3885
3886
3887
/* Dump the Python path configuration into sys.stderr */
3888
void
3889
_Py_DumpPathConfig(PyThreadState *tstate)
3890
0
{
3891
0
    PyObject *exc = _PyErr_GetRaisedException(tstate);
3892
3893
0
    PySys_WriteStderr("Python path configuration:\n");
3894
3895
0
#define DUMP_CONFIG(NAME, FIELD) \
3896
0
        do { \
3897
0
            PySys_WriteStderr("  " NAME " = "); \
3898
0
            init_dump_ascii_wstr(config->FIELD); \
3899
0
            PySys_WriteStderr("\n"); \
3900
0
        } while (0)
3901
3902
0
    const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
3903
0
    DUMP_CONFIG("PYTHONHOME", home);
3904
0
    DUMP_CONFIG("PYTHONPATH", pythonpath_env);
3905
0
    DUMP_CONFIG("program name", program_name);
3906
0
    PySys_WriteStderr("  isolated = %i\n", config->isolated);
3907
0
    PySys_WriteStderr("  environment = %i\n", config->use_environment);
3908
0
    PySys_WriteStderr("  user site = %i\n", config->user_site_directory);
3909
0
    PySys_WriteStderr("  safe_path = %i\n", config->safe_path);
3910
0
    PySys_WriteStderr("  import site = %i\n", config->site_import);
3911
0
    PySys_WriteStderr("  is in build tree = %i\n", config->_is_python_build);
3912
0
    DUMP_CONFIG("stdlib dir", stdlib_dir);
3913
0
    DUMP_CONFIG("sys.path[0]", sys_path_0);
3914
0
#undef DUMP_CONFIG
3915
3916
0
#define DUMP_SYS(NAME) \
3917
0
        do { \
3918
0
            PySys_FormatStderr("  sys.%s = ", #NAME); \
3919
0
            if (PySys_GetOptionalAttrString(#NAME, &obj) < 0) { \
3920
0
                PyErr_Clear(); \
3921
0
            } \
3922
0
            if (obj != NULL) { \
3923
0
                PySys_FormatStderr("%A", obj); \
3924
0
                Py_DECREF(obj); \
3925
0
            } \
3926
0
            else { \
3927
0
                PySys_WriteStderr("(not set)"); \
3928
0
            } \
3929
0
            PySys_FormatStderr("\n"); \
3930
0
        } while (0)
3931
3932
0
    PyObject *obj;
3933
0
    DUMP_SYS(_base_executable);
3934
0
    DUMP_SYS(base_prefix);
3935
0
    DUMP_SYS(base_exec_prefix);
3936
0
    DUMP_SYS(platlibdir);
3937
0
    DUMP_SYS(executable);
3938
0
    DUMP_SYS(prefix);
3939
0
    DUMP_SYS(exec_prefix);
3940
0
#undef DUMP_SYS
3941
3942
0
    PyObject *sys_path;
3943
0
    (void) PySys_GetOptionalAttrString("path", &sys_path);
3944
0
    if (sys_path != NULL && PyList_Check(sys_path)) {
3945
0
        PySys_WriteStderr("  sys.path = [\n");
3946
0
        Py_ssize_t len = PyList_GET_SIZE(sys_path);
3947
0
        for (Py_ssize_t i=0; i < len; i++) {
3948
0
            PyObject *path = PyList_GET_ITEM(sys_path, i);
3949
0
            PySys_FormatStderr("    %A,\n", path);
3950
0
        }
3951
0
        PySys_WriteStderr("  ]\n");
3952
0
    }
3953
0
    Py_XDECREF(sys_path);
3954
3955
0
    _PyErr_SetRaisedException(tstate, exc);
3956
0
}
3957
3958
3959
// --- PyInitConfig API ---------------------------------------------------
3960
3961
struct PyInitConfig {
3962
    PyPreConfig preconfig;
3963
    PyConfig config;
3964
    struct _inittab *inittab;
3965
    Py_ssize_t inittab_size;
3966
    PyStatus status;
3967
    char *err_msg;
3968
};
3969
3970
static PyInitConfig*
3971
initconfig_alloc(void)
3972
0
{
3973
0
    return calloc(1, sizeof(PyInitConfig));
3974
0
}
3975
3976
3977
PyInitConfig*
3978
PyInitConfig_Create(void)
3979
0
{
3980
0
    PyInitConfig *config = initconfig_alloc();
3981
0
    if (config == NULL) {
3982
0
        return NULL;
3983
0
    }
3984
0
    PyPreConfig_InitIsolatedConfig(&config->preconfig);
3985
0
    PyConfig_InitIsolatedConfig(&config->config);
3986
0
    config->status = _PyStatus_OK();
3987
0
    return config;
3988
0
}
3989
3990
3991
void
3992
PyInitConfig_Free(PyInitConfig *config)
3993
0
{
3994
0
    if (config == NULL) {
3995
0
        return;
3996
0
    }
3997
3998
0
    initconfig_free_config(&config->config);
3999
0
    PyMem_RawFree(config->inittab);
4000
0
    free(config->err_msg);
4001
0
    free(config);
4002
0
}
4003
4004
4005
int
4006
PyInitConfig_GetError(PyInitConfig* config, const char **perr_msg)
4007
0
{
4008
0
    if (_PyStatus_IS_EXIT(config->status)) {
4009
0
        char buffer[22];  // len("exit code -2147483648\0")
4010
0
        PyOS_snprintf(buffer, sizeof(buffer),
4011
0
                      "exit code %i",
4012
0
                      config->status.exitcode);
4013
4014
0
        if (config->err_msg != NULL) {
4015
0
            free(config->err_msg);
4016
0
        }
4017
0
        config->err_msg = strdup(buffer);
4018
0
        if (config->err_msg != NULL) {
4019
0
            *perr_msg = config->err_msg;
4020
0
            return 1;
4021
0
        }
4022
0
        config->status = _PyStatus_NO_MEMORY();
4023
0
    }
4024
4025
0
    if (_PyStatus_IS_ERROR(config->status) && config->status.err_msg != NULL) {
4026
0
        *perr_msg = config->status.err_msg;
4027
0
        return 1;
4028
0
    }
4029
0
    else {
4030
0
        *perr_msg = NULL;
4031
0
        return 0;
4032
0
    }
4033
0
}
4034
4035
4036
int
4037
PyInitConfig_GetExitCode(PyInitConfig* config, int *exitcode)
4038
0
{
4039
0
    if (_PyStatus_IS_EXIT(config->status)) {
4040
0
        *exitcode = config->status.exitcode;
4041
0
        return 1;
4042
0
    }
4043
0
    else {
4044
0
        return 0;
4045
0
    }
4046
0
}
4047
4048
4049
static void
4050
initconfig_set_error(PyInitConfig *config, const char *err_msg)
4051
0
{
4052
0
    config->status = _PyStatus_ERR(err_msg);
4053
0
}
4054
4055
4056
static const PyConfigSpec*
4057
initconfig_find_spec(const PyConfigSpec *spec, const char *name)
4058
0
{
4059
0
    for (; spec->name != NULL; spec++) {
4060
0
        if (strcmp(name, spec->name) == 0) {
4061
0
            return spec;
4062
0
        }
4063
0
    }
4064
0
    return NULL;
4065
0
}
4066
4067
4068
int
4069
PyInitConfig_HasOption(PyInitConfig *config, const char *name)
4070
0
{
4071
0
    const PyConfigSpec *spec = initconfig_find_spec(PYCONFIG_SPEC, name);
4072
0
    if (spec == NULL) {
4073
0
        spec = initconfig_find_spec(PYPRECONFIG_SPEC, name);
4074
0
    }
4075
0
    return (spec != NULL);
4076
0
}
4077
4078
4079
static const PyConfigSpec*
4080
initconfig_prepare(PyInitConfig *config, const char *name, void **raw_member)
4081
0
{
4082
0
    const PyConfigSpec *spec = initconfig_find_spec(PYCONFIG_SPEC, name);
4083
0
    if (spec != NULL) {
4084
0
        *raw_member = config_get_spec_member(&config->config, spec);
4085
0
        return spec;
4086
0
    }
4087
4088
0
    spec = initconfig_find_spec(PYPRECONFIG_SPEC, name);
4089
0
    if (spec != NULL) {
4090
0
        *raw_member = preconfig_get_spec_member(&config->preconfig, spec);
4091
0
        return spec;
4092
0
    }
4093
4094
0
    initconfig_set_error(config, "unknown config option name");
4095
0
    return NULL;
4096
0
}
4097
4098
4099
int
4100
PyInitConfig_GetInt(PyInitConfig *config, const char *name, int64_t *value)
4101
0
{
4102
0
    void *raw_member;
4103
0
    const PyConfigSpec *spec = initconfig_prepare(config, name, &raw_member);
4104
0
    if (spec == NULL) {
4105
0
        return -1;
4106
0
    }
4107
4108
0
    switch (spec->type) {
4109
0
    case PyConfig_MEMBER_INT:
4110
0
    case PyConfig_MEMBER_UINT:
4111
0
    case PyConfig_MEMBER_BOOL:
4112
0
    {
4113
0
        int *member = raw_member;
4114
0
        *value = *member;
4115
0
        break;
4116
0
    }
4117
4118
0
    case PyConfig_MEMBER_ULONG:
4119
0
    {
4120
0
        unsigned long *member = raw_member;
4121
0
#if SIZEOF_LONG >= 8
4122
0
        if ((unsigned long)INT64_MAX < *member) {
4123
0
            initconfig_set_error(config,
4124
0
                "config option value doesn't fit into int64_t");
4125
0
            return -1;
4126
0
        }
4127
0
#endif
4128
0
        *value = *member;
4129
0
        break;
4130
0
    }
4131
4132
0
    default:
4133
0
        initconfig_set_error(config, "config option type is not int");
4134
0
        return -1;
4135
0
    }
4136
0
    return 0;
4137
0
}
4138
4139
4140
static char*
4141
wstr_to_utf8(PyInitConfig *config, wchar_t *wstr)
4142
0
{
4143
0
    char *utf8;
4144
0
    int res = _Py_EncodeUTF8Ex(wstr, &utf8, NULL, NULL, 1, _Py_ERROR_STRICT);
4145
0
    if (res == -2) {
4146
0
        initconfig_set_error(config, "encoding error");
4147
0
        return NULL;
4148
0
    }
4149
0
    if (res < 0) {
4150
0
        config->status = _PyStatus_NO_MEMORY();
4151
0
        return NULL;
4152
0
    }
4153
4154
    // Copy to use the malloc() memory allocator
4155
0
    size_t size = strlen(utf8) + 1;
4156
0
    char *str = malloc(size);
4157
0
    if (str == NULL) {
4158
0
        PyMem_RawFree(utf8);
4159
0
        config->status = _PyStatus_NO_MEMORY();
4160
0
        return NULL;
4161
0
    }
4162
4163
0
    memcpy(str, utf8, size);
4164
0
    PyMem_RawFree(utf8);
4165
0
    return str;
4166
0
}
4167
4168
4169
int
4170
PyInitConfig_GetStr(PyInitConfig *config, const char *name, char **value)
4171
0
{
4172
0
    void *raw_member;
4173
0
    const PyConfigSpec *spec = initconfig_prepare(config, name, &raw_member);
4174
0
    if (spec == NULL) {
4175
0
        return -1;
4176
0
    }
4177
4178
0
    if (spec->type != PyConfig_MEMBER_WSTR
4179
0
        && spec->type != PyConfig_MEMBER_WSTR_OPT)
4180
0
    {
4181
0
        initconfig_set_error(config, "config option type is not string");
4182
0
        return -1;
4183
0
    }
4184
4185
0
    wchar_t **member = raw_member;
4186
0
    if (*member == NULL) {
4187
0
        *value = NULL;
4188
0
        return 0;
4189
0
    }
4190
4191
0
    *value = wstr_to_utf8(config, *member);
4192
0
    if (*value == NULL) {
4193
0
        return -1;
4194
0
    }
4195
0
    return 0;
4196
0
}
4197
4198
4199
int
4200
PyInitConfig_GetStrList(PyInitConfig *config, const char *name, size_t *length, char ***items)
4201
0
{
4202
0
    void *raw_member;
4203
0
    const PyConfigSpec *spec = initconfig_prepare(config, name, &raw_member);
4204
0
    if (spec == NULL) {
4205
0
        return -1;
4206
0
    }
4207
4208
0
    if (spec->type != PyConfig_MEMBER_WSTR_LIST) {
4209
0
        initconfig_set_error(config, "config option type is not string list");
4210
0
        return -1;
4211
0
    }
4212
4213
0
    PyWideStringList *list = raw_member;
4214
0
    *length = list->length;
4215
4216
0
    *items = malloc(list->length * sizeof(char*));
4217
0
    if (*items == NULL) {
4218
0
        config->status = _PyStatus_NO_MEMORY();
4219
0
        return -1;
4220
0
    }
4221
4222
0
    for (Py_ssize_t i=0; i < list->length; i++) {
4223
0
        (*items)[i] = wstr_to_utf8(config, list->items[i]);
4224
0
        if ((*items)[i] == NULL) {
4225
0
            PyInitConfig_FreeStrList(i, *items);
4226
0
            return -1;
4227
0
        }
4228
0
    }
4229
0
    return 0;
4230
0
}
4231
4232
4233
void
4234
PyInitConfig_FreeStrList(size_t length, char **items)
4235
0
{
4236
0
    for (size_t i=0; i < length; i++) {
4237
0
        free(items[i]);
4238
0
    }
4239
0
    free(items);
4240
0
}
4241
4242
4243
int
4244
PyInitConfig_SetInt(PyInitConfig *config, const char *name, int64_t value)
4245
0
{
4246
0
    void *raw_member;
4247
0
    const PyConfigSpec *spec = initconfig_prepare(config, name, &raw_member);
4248
0
    if (spec == NULL) {
4249
0
        return -1;
4250
0
    }
4251
4252
0
    switch (spec->type) {
4253
0
    case PyConfig_MEMBER_INT:
4254
0
    {
4255
0
        if (value < (int64_t)INT_MIN || (int64_t)INT_MAX < value) {
4256
0
            initconfig_set_error(config,
4257
0
                "config option value is out of int range");
4258
0
            return -1;
4259
0
        }
4260
0
        int int_value = (int)value;
4261
4262
0
        int *member = raw_member;
4263
0
        *member = int_value;
4264
0
        break;
4265
0
    }
4266
4267
0
    case PyConfig_MEMBER_UINT:
4268
0
    case PyConfig_MEMBER_BOOL:
4269
0
    {
4270
0
        if (value < 0 || (uint64_t)UINT_MAX < (uint64_t)value) {
4271
0
            initconfig_set_error(config,
4272
0
                "config option value is out of unsigned int range");
4273
0
            return -1;
4274
0
        }
4275
0
        int int_value = (int)value;
4276
4277
0
        int *member = raw_member;
4278
0
        *member = int_value;
4279
0
        break;
4280
0
    }
4281
4282
0
    case PyConfig_MEMBER_ULONG:
4283
0
    {
4284
0
        if (value < 0 || (uint64_t)ULONG_MAX < (uint64_t)value) {
4285
0
            initconfig_set_error(config,
4286
0
                "config option value is out of unsigned long range");
4287
0
            return -1;
4288
0
        }
4289
0
        unsigned long ulong_value = (unsigned long)value;
4290
4291
0
        unsigned long *member = raw_member;
4292
0
        *member = ulong_value;
4293
0
        break;
4294
0
    }
4295
4296
0
    default:
4297
0
        initconfig_set_error(config, "config option type is not int");
4298
0
        return -1;
4299
0
    }
4300
4301
0
    if (strcmp(name, "hash_seed") == 0) {
4302
0
        config->config.use_hash_seed = 1;
4303
0
    }
4304
4305
0
    return 0;
4306
0
}
4307
4308
4309
static wchar_t*
4310
utf8_to_wstr(PyInitConfig *config, const char *str)
4311
0
{
4312
0
    wchar_t *wstr;
4313
0
    size_t wlen;
4314
0
    int res = _Py_DecodeUTF8Ex(str, strlen(str), &wstr, &wlen, NULL, _Py_ERROR_STRICT);
4315
0
    if (res == -2) {
4316
0
        initconfig_set_error(config, "decoding error");
4317
0
        return NULL;
4318
0
    }
4319
0
    if (res < 0) {
4320
0
        config->status = _PyStatus_NO_MEMORY();
4321
0
        return NULL;
4322
0
    }
4323
4324
    // Copy to use the malloc() memory allocator
4325
0
    size_t size = (wlen + 1) * sizeof(wchar_t);
4326
0
    wchar_t *wstr2 = malloc(size);
4327
0
    if (wstr2 == NULL) {
4328
0
        PyMem_RawFree(wstr);
4329
0
        config->status = _PyStatus_NO_MEMORY();
4330
0
        return NULL;
4331
0
    }
4332
4333
0
    memcpy(wstr2, wstr, size);
4334
0
    PyMem_RawFree(wstr);
4335
0
    return wstr2;
4336
0
}
4337
4338
4339
int
4340
PyInitConfig_SetStr(PyInitConfig *config, const char *name, const char* value)
4341
0
{
4342
0
    void *raw_member;
4343
0
    const PyConfigSpec *spec = initconfig_prepare(config, name, &raw_member);
4344
0
    if (spec == NULL) {
4345
0
        return -1;
4346
0
    }
4347
4348
0
    if (spec->type != PyConfig_MEMBER_WSTR
4349
0
            && spec->type != PyConfig_MEMBER_WSTR_OPT) {
4350
0
        initconfig_set_error(config, "config option type is not string");
4351
0
        return -1;
4352
0
    }
4353
4354
0
    if (value == NULL && spec->type != PyConfig_MEMBER_WSTR_OPT) {
4355
0
        initconfig_set_error(config, "config option string cannot be NULL");
4356
0
    }
4357
4358
0
    wchar_t **member = raw_member;
4359
4360
0
    *member = utf8_to_wstr(config, value);
4361
0
    if (*member == NULL) {
4362
0
        return -1;
4363
0
    }
4364
0
    return 0;
4365
0
}
4366
4367
4368
static void
4369
initconfig_free_wstr(wchar_t *member)
4370
0
{
4371
0
    if (member) {
4372
0
        free(member);
4373
0
    }
4374
0
}
4375
4376
4377
static void
4378
initconfig_free_wstr_list(PyWideStringList *list)
4379
0
{
4380
0
    for (Py_ssize_t i = 0; i < list->length; i++) {
4381
0
        free(list->items[i]);
4382
0
    }
4383
0
    free(list->items);
4384
0
}
4385
4386
4387
static void
4388
initconfig_free_config(const PyConfig *config)
4389
0
{
4390
0
    const PyConfigSpec *spec = PYCONFIG_SPEC;
4391
0
    for (; spec->name != NULL; spec++) {
4392
0
        void *member = config_get_spec_member(config, spec);
4393
0
        if (spec->type == PyConfig_MEMBER_WSTR
4394
0
            || spec->type == PyConfig_MEMBER_WSTR_OPT)
4395
0
        {
4396
0
            wchar_t *wstr = *(wchar_t **)member;
4397
0
            initconfig_free_wstr(wstr);
4398
0
        }
4399
0
        else if (spec->type == PyConfig_MEMBER_WSTR_LIST) {
4400
0
            initconfig_free_wstr_list(member);
4401
0
        }
4402
0
    }
4403
0
}
4404
4405
4406
static int
4407
initconfig_set_str_list(PyInitConfig *config, PyWideStringList *list,
4408
                        Py_ssize_t length, char * const *items)
4409
0
{
4410
0
    PyWideStringList wlist = _PyWideStringList_INIT;
4411
0
    size_t size = sizeof(wchar_t*) * length;
4412
0
    wlist.items = (wchar_t **)malloc(size);
4413
0
    if (wlist.items == NULL) {
4414
0
        config->status = _PyStatus_NO_MEMORY();
4415
0
        return -1;
4416
0
    }
4417
4418
0
    for (Py_ssize_t i = 0; i < length; i++) {
4419
0
        wchar_t *arg = utf8_to_wstr(config, items[i]);
4420
0
        if (arg == NULL) {
4421
0
            initconfig_free_wstr_list(&wlist);
4422
0
            return -1;
4423
0
        }
4424
0
        wlist.items[i] = arg;
4425
0
        wlist.length++;
4426
0
    }
4427
4428
0
    initconfig_free_wstr_list(list);
4429
0
    *list = wlist;
4430
0
    return 0;
4431
0
}
4432
4433
4434
int
4435
PyInitConfig_SetStrList(PyInitConfig *config, const char *name,
4436
                        size_t length, char * const *items)
4437
0
{
4438
0
    void *raw_member;
4439
0
    const PyConfigSpec *spec = initconfig_prepare(config, name, &raw_member);
4440
0
    if (spec == NULL) {
4441
0
        return -1;
4442
0
    }
4443
4444
0
    if (spec->type != PyConfig_MEMBER_WSTR_LIST) {
4445
0
        initconfig_set_error(config, "config option type is not strings list");
4446
0
        return -1;
4447
0
    }
4448
0
    PyWideStringList *list = raw_member;
4449
0
    if (initconfig_set_str_list(config, list, length, items) < 0) {
4450
0
        return -1;
4451
0
    }
4452
4453
0
    if (strcmp(name, "module_search_paths") == 0) {
4454
0
        config->config.module_search_paths_set = 1;
4455
0
    }
4456
0
    return 0;
4457
0
}
4458
4459
4460
int
4461
PyInitConfig_AddModule(PyInitConfig *config, const char *name,
4462
                       PyObject* (*initfunc)(void))
4463
0
{
4464
0
    size_t size = sizeof(struct _inittab) * (config->inittab_size + 2);
4465
0
    struct _inittab *new_inittab = PyMem_RawRealloc(config->inittab, size);
4466
0
    if (new_inittab == NULL) {
4467
0
        config->status = _PyStatus_NO_MEMORY();
4468
0
        return -1;
4469
0
    }
4470
0
    config->inittab = new_inittab;
4471
4472
0
    struct _inittab *entry = &config->inittab[config->inittab_size];
4473
0
    entry->name = name;
4474
0
    entry->initfunc = initfunc;
4475
4476
    // Terminator entry
4477
0
    entry = &config->inittab[config->inittab_size + 1];
4478
0
    entry->name = NULL;
4479
0
    entry->initfunc = NULL;
4480
4481
0
    config->inittab_size++;
4482
0
    return 0;
4483
0
}
4484
4485
4486
int
4487
Py_InitializeFromInitConfig(PyInitConfig *config)
4488
0
{
4489
0
    if (config->inittab_size >= 1) {
4490
0
        if (PyImport_ExtendInittab(config->inittab) < 0) {
4491
0
            config->status = _PyStatus_NO_MEMORY();
4492
0
            return -1;
4493
0
        }
4494
0
    }
4495
4496
0
    _PyPreConfig_GetConfig(&config->preconfig, &config->config);
4497
4498
0
    config->status = Py_PreInitializeFromArgs(
4499
0
        &config->preconfig,
4500
0
        config->config.argv.length,
4501
0
        config->config.argv.items);
4502
0
    if (_PyStatus_EXCEPTION(config->status)) {
4503
0
        return -1;
4504
0
    }
4505
4506
0
    config->status = Py_InitializeFromConfig(&config->config);
4507
0
    if (_PyStatus_EXCEPTION(config->status)) {
4508
0
        return -1;
4509
0
    }
4510
4511
0
    return 0;
4512
0
}
4513
4514
4515
// --- PyConfig_Get() -------------------------------------------------------
4516
4517
static const PyConfigSpec*
4518
config_generic_find_spec(const PyConfigSpec *spec, const char *name)
4519
0
{
4520
0
    for (; spec->name != NULL; spec++) {
4521
0
        if (spec->visibility == PyConfig_MEMBER_INIT_ONLY) {
4522
0
            continue;
4523
0
        }
4524
0
        if (strcmp(name, spec->name) == 0) {
4525
0
            return spec;
4526
0
        }
4527
0
    }
4528
0
    return NULL;
4529
0
}
4530
4531
4532
static const PyConfigSpec*
4533
config_find_spec(const char *name)
4534
0
{
4535
0
    return config_generic_find_spec(PYCONFIG_SPEC, name);
4536
0
}
4537
4538
4539
static const PyConfigSpec*
4540
preconfig_find_spec(const char *name)
4541
0
{
4542
0
    return config_generic_find_spec(PYPRECONFIG_SPEC, name);
4543
0
}
4544
4545
4546
static int
4547
config_add_xoption(PyObject *dict, const wchar_t *str)
4548
0
{
4549
0
    PyObject *name = NULL, *value = NULL;
4550
4551
0
    const wchar_t *name_end = wcschr(str, L'=');
4552
0
    if (!name_end) {
4553
0
        name = PyUnicode_FromWideChar(str, -1);
4554
0
        if (name == NULL) {
4555
0
            goto error;
4556
0
        }
4557
0
        value = Py_NewRef(Py_True);
4558
0
    }
4559
0
    else {
4560
0
        name = PyUnicode_FromWideChar(str, name_end - str);
4561
0
        if (name == NULL) {
4562
0
            goto error;
4563
0
        }
4564
0
        value = PyUnicode_FromWideChar(name_end + 1, -1);
4565
0
        if (value == NULL) {
4566
0
            goto error;
4567
0
        }
4568
0
    }
4569
0
    if (PyDict_SetItem(dict, name, value) < 0) {
4570
0
        goto error;
4571
0
    }
4572
0
    Py_DECREF(name);
4573
0
    Py_DECREF(value);
4574
0
    return 0;
4575
4576
0
error:
4577
0
    Py_XDECREF(name);
4578
0
    Py_XDECREF(value);
4579
0
    return -1;
4580
0
}
4581
4582
4583
PyObject*
4584
_PyConfig_CreateXOptionsDict(const PyConfig *config)
4585
72
{
4586
72
    PyObject *dict = PyDict_New();
4587
72
    if (dict == NULL) {
4588
0
        return NULL;
4589
0
    }
4590
4591
72
    Py_ssize_t nxoption = config->xoptions.length;
4592
72
    wchar_t **xoptions = config->xoptions.items;
4593
72
    for (Py_ssize_t i=0; i < nxoption; i++) {
4594
0
        const wchar_t *option = xoptions[i];
4595
0
        if (config_add_xoption(dict, option) < 0) {
4596
0
            Py_DECREF(dict);
4597
0
            return NULL;
4598
0
        }
4599
0
    }
4600
72
    return dict;
4601
72
}
4602
4603
4604
static int
4605
config_get_sys_write_bytecode(const PyConfig *config, int *value)
4606
0
{
4607
0
    PyObject *attr = PySys_GetAttrString("dont_write_bytecode");
4608
0
    if (attr == NULL) {
4609
0
        return -1;
4610
0
    }
4611
4612
0
    int is_true = PyObject_IsTrue(attr);
4613
0
    Py_DECREF(attr);
4614
0
    if (is_true < 0) {
4615
0
        return -1;
4616
0
    }
4617
0
    *value = (!is_true);
4618
0
    return 0;
4619
0
}
4620
4621
4622
static PyObject*
4623
config_get(const PyConfig *config, const PyConfigSpec *spec,
4624
           int use_sys)
4625
2.55k
{
4626
2.55k
    if (use_sys) {
4627
0
        if (spec->sys.attr != NULL) {
4628
0
            return PySys_GetAttrString(spec->sys.attr);
4629
0
        }
4630
4631
0
        if (strcmp(spec->name, "write_bytecode") == 0) {
4632
0
            int value;
4633
0
            if (config_get_sys_write_bytecode(config, &value) < 0) {
4634
0
                return NULL;
4635
0
            }
4636
0
            return PyBool_FromLong(value);
4637
0
        }
4638
4639
0
        if (strcmp(spec->name, "int_max_str_digits") == 0) {
4640
0
            PyInterpreterState *interp = _PyInterpreterState_GET();
4641
0
            int maxdigits = _Py_atomic_load_int(&interp->long_state.max_str_digits);
4642
0
            return PyLong_FromLong(maxdigits);
4643
0
        }
4644
0
    }
4645
4646
2.55k
    void *member = config_get_spec_member(config, spec);
4647
2.55k
    switch (spec->type) {
4648
144
    case PyConfig_MEMBER_INT:
4649
432
    case PyConfig_MEMBER_UINT:
4650
432
    {
4651
432
        int value = *(int *)member;
4652
432
        return PyLong_FromLong(value);
4653
144
    }
4654
4655
1.11k
    case PyConfig_MEMBER_BOOL:
4656
1.11k
    {
4657
1.11k
        int value = *(int *)member;
4658
1.11k
        return PyBool_FromLong(value != 0);
4659
144
    }
4660
4661
36
    case PyConfig_MEMBER_ULONG:
4662
36
    {
4663
36
        unsigned long value = *(unsigned long *)member;
4664
36
        return PyLong_FromUnsignedLong(value);
4665
144
    }
4666
4667
252
    case PyConfig_MEMBER_WSTR:
4668
792
    case PyConfig_MEMBER_WSTR_OPT:
4669
792
    {
4670
792
        wchar_t *wstr = *(wchar_t **)member;
4671
792
        if (wstr != NULL) {
4672
180
            return PyUnicode_FromWideChar(wstr, -1);
4673
180
        }
4674
612
        else {
4675
612
            return Py_NewRef(Py_None);
4676
612
        }
4677
792
    }
4678
4679
180
    case PyConfig_MEMBER_WSTR_LIST:
4680
180
    {
4681
180
        if (strcmp(spec->name, "xoptions") == 0) {
4682
36
            return _PyConfig_CreateXOptionsDict(config);
4683
36
        }
4684
144
        else {
4685
144
            const PyWideStringList *list = (const PyWideStringList *)member;
4686
144
            return _PyWideStringList_AsTuple(list);
4687
144
        }
4688
180
    }
4689
4690
0
    default:
4691
0
        Py_UNREACHABLE();
4692
2.55k
    }
4693
2.55k
}
4694
4695
4696
static PyObject*
4697
preconfig_get(const PyPreConfig *preconfig, const PyConfigSpec *spec)
4698
0
{
4699
    // The type of all PYPRECONFIG_SPEC members is INT or BOOL.
4700
0
    assert(spec->type == PyConfig_MEMBER_INT
4701
0
           || spec->type == PyConfig_MEMBER_BOOL);
4702
4703
0
    char *member = (char *)preconfig + spec->offset;
4704
0
    int value = *(int *)member;
4705
4706
0
    if (spec->type == PyConfig_MEMBER_BOOL) {
4707
0
        return PyBool_FromLong(value != 0);
4708
0
    }
4709
0
    else {
4710
0
        return PyLong_FromLong(value);
4711
0
    }
4712
0
}
4713
4714
4715
static void
4716
config_unknown_name_error(const char *name)
4717
0
{
4718
0
    PyErr_Format(PyExc_ValueError, "unknown config option name: %s", name);
4719
0
}
4720
4721
4722
PyObject*
4723
PyConfig_Get(const char *name)
4724
0
{
4725
0
    const PyConfigSpec *spec = config_find_spec(name);
4726
0
    if (spec != NULL) {
4727
0
        const PyConfig *config = _Py_GetConfig();
4728
0
        return config_get(config, spec, 1);
4729
0
    }
4730
4731
0
    spec = preconfig_find_spec(name);
4732
0
    if (spec != NULL) {
4733
0
        const PyPreConfig *preconfig = &_PyRuntime.preconfig;
4734
0
        return preconfig_get(preconfig, spec);
4735
0
    }
4736
4737
0
    config_unknown_name_error(name);
4738
0
    return NULL;
4739
0
}
4740
4741
4742
int
4743
PyConfig_GetInt(const char *name, int *value)
4744
0
{
4745
0
    assert(!PyErr_Occurred());
4746
4747
0
    PyObject *obj = PyConfig_Get(name);
4748
0
    if (obj == NULL) {
4749
0
        return -1;
4750
0
    }
4751
4752
0
    if (!PyLong_Check(obj)) {
4753
0
        Py_DECREF(obj);
4754
0
        PyErr_Format(PyExc_TypeError, "config option %s is not an int", name);
4755
0
        return -1;
4756
0
    }
4757
4758
0
    int as_int = PyLong_AsInt(obj);
4759
0
    Py_DECREF(obj);
4760
0
    if (as_int == -1 && PyErr_Occurred()) {
4761
0
        PyErr_Format(PyExc_OverflowError,
4762
0
                     "config option %s value does not fit into a C int", name);
4763
0
        return -1;
4764
0
    }
4765
4766
0
    *value = as_int;
4767
0
    return 0;
4768
0
}
4769
4770
4771
static int
4772
config_names_add(PyObject *names, const PyConfigSpec *spec)
4773
0
{
4774
0
    for (; spec->name != NULL; spec++) {
4775
0
        if (spec->visibility == PyConfig_MEMBER_INIT_ONLY) {
4776
0
            continue;
4777
0
        }
4778
0
        PyObject *name = PyUnicode_FromString(spec->name);
4779
0
        if (name == NULL) {
4780
0
            return -1;
4781
0
        }
4782
0
        int res = PyList_Append(names, name);
4783
0
        Py_DECREF(name);
4784
0
        if (res < 0) {
4785
0
            return -1;
4786
0
        }
4787
0
    }
4788
0
    return 0;
4789
0
}
4790
4791
4792
PyObject*
4793
PyConfig_Names(void)
4794
0
{
4795
0
    PyObject *names = PyList_New(0);
4796
0
    if (names == NULL) {
4797
0
        goto error;
4798
0
    }
4799
4800
0
    if (config_names_add(names, PYCONFIG_SPEC) < 0) {
4801
0
        goto error;
4802
0
    }
4803
0
    if (config_names_add(names, PYPRECONFIG_SPEC) < 0) {
4804
0
        goto error;
4805
0
    }
4806
4807
0
    PyObject *frozen = PyFrozenSet_New(names);
4808
0
    Py_DECREF(names);
4809
0
    return frozen;
4810
4811
0
error:
4812
0
    Py_XDECREF(names);
4813
0
    return NULL;
4814
0
}
4815
4816
4817
// --- PyConfig_Set() -------------------------------------------------------
4818
4819
static int
4820
config_set_sys_flag(const PyConfigSpec *spec, int int_value)
4821
0
{
4822
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
4823
0
    PyConfig *config = &interp->config;
4824
4825
0
    if (spec->type == PyConfig_MEMBER_BOOL) {
4826
0
        if (int_value != 0) {
4827
            // convert values < 0 and values > 1 to 1
4828
0
            int_value = 1;
4829
0
        }
4830
0
    }
4831
4832
0
    PyObject *value;
4833
0
    if (spec->sys.flag_setter) {
4834
0
        value = spec->sys.flag_setter(int_value);
4835
0
    }
4836
0
    else {
4837
0
        value = config_sys_flag_long(int_value);
4838
0
    }
4839
0
    if (value == NULL) {
4840
0
        return -1;
4841
0
    }
4842
4843
    // Set sys.flags.FLAG
4844
0
    Py_ssize_t pos = spec->sys.flag_index;
4845
0
    if (_PySys_SetFlagObj(pos, value) < 0) {
4846
0
        goto error;
4847
0
    }
4848
4849
    // Set PyConfig.ATTR
4850
0
    assert(spec->type == PyConfig_MEMBER_INT
4851
0
           || spec->type == PyConfig_MEMBER_UINT
4852
0
           || spec->type == PyConfig_MEMBER_BOOL);
4853
0
    int *member = config_get_spec_member(config, spec);
4854
0
    *member = int_value;
4855
4856
    // Set sys.dont_write_bytecode attribute
4857
0
    if (strcmp(spec->name, "write_bytecode") == 0) {
4858
0
        if (PySys_SetObject("dont_write_bytecode", value) < 0) {
4859
0
            goto error;
4860
0
        }
4861
0
    }
4862
4863
0
    Py_DECREF(value);
4864
0
    return 0;
4865
4866
0
error:
4867
0
    Py_DECREF(value);
4868
0
    return -1;
4869
0
}
4870
4871
4872
// Set PyConfig.ATTR integer member
4873
static int
4874
config_set_int_attr(const PyConfigSpec *spec, int value)
4875
0
{
4876
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
4877
0
    PyConfig *config = &interp->config;
4878
0
    int *member = config_get_spec_member(config, spec);
4879
0
    *member = value;
4880
0
    return 0;
4881
0
}
4882
4883
4884
int
4885
PyConfig_Set(const char *name, PyObject *value)
4886
0
{
4887
0
    if (PySys_Audit("cpython.PyConfig_Set", "sO", name, value) < 0) {
4888
0
        return -1;
4889
0
    }
4890
4891
0
    const PyConfigSpec *spec = config_find_spec(name);
4892
0
    if (spec == NULL) {
4893
0
        spec = preconfig_find_spec(name);
4894
0
        if (spec == NULL) {
4895
0
            config_unknown_name_error(name);
4896
0
            return -1;
4897
0
        }
4898
0
        assert(spec->visibility != PyConfig_MEMBER_PUBLIC);
4899
0
    }
4900
4901
0
    if (spec->visibility != PyConfig_MEMBER_PUBLIC) {
4902
0
        PyErr_Format(PyExc_ValueError, "cannot set read-only option %s",
4903
0
                     name);
4904
0
        return -1;
4905
0
    }
4906
4907
0
    int int_value = 0;
4908
0
    int has_int_value = 0;
4909
4910
0
    switch (spec->type) {
4911
0
    case PyConfig_MEMBER_INT:
4912
0
    case PyConfig_MEMBER_UINT:
4913
0
    case PyConfig_MEMBER_BOOL:
4914
0
        if (!PyLong_Check(value)) {
4915
0
            PyErr_Format(PyExc_TypeError, "expected int or bool, got %T", value);
4916
0
            return -1;
4917
0
        }
4918
0
        int_value = PyLong_AsInt(value);
4919
0
        if (int_value == -1 && PyErr_Occurred()) {
4920
0
            return -1;
4921
0
        }
4922
0
        if (int_value < 0 && spec->type != PyConfig_MEMBER_INT) {
4923
0
            PyErr_Format(PyExc_ValueError, "value must be >= 0");
4924
0
            return -1;
4925
0
        }
4926
0
        has_int_value = 1;
4927
0
        break;
4928
4929
0
    case PyConfig_MEMBER_ULONG:
4930
        // not implemented: only hash_seed uses this type, and it's read-only
4931
0
        goto cannot_set;
4932
4933
0
    case PyConfig_MEMBER_WSTR:
4934
0
        if (!PyUnicode_CheckExact(value)) {
4935
0
            PyErr_Format(PyExc_TypeError, "expected str, got %T", value);
4936
0
            return -1;
4937
0
        }
4938
0
        break;
4939
4940
0
    case PyConfig_MEMBER_WSTR_OPT:
4941
0
        if (value != Py_None && !PyUnicode_CheckExact(value)) {
4942
0
            PyErr_Format(PyExc_TypeError, "expected str or None, got %T", value);
4943
0
            return -1;
4944
0
        }
4945
0
        break;
4946
4947
0
    case PyConfig_MEMBER_WSTR_LIST:
4948
0
        if (strcmp(spec->name, "xoptions") != 0) {
4949
0
            if (!PyList_Check(value)) {
4950
0
                PyErr_Format(PyExc_TypeError, "expected list[str], got %T",
4951
0
                             value);
4952
0
                return -1;
4953
0
            }
4954
0
            for (Py_ssize_t i=0; i < PyList_GET_SIZE(value); i++) {
4955
0
                PyObject *item = PyList_GET_ITEM(value, i);
4956
0
                if (!PyUnicode_Check(item)) {
4957
0
                    PyErr_Format(PyExc_TypeError,
4958
0
                                 "expected str, list item %zd has type %T",
4959
0
                                 i, item);
4960
0
                    return -1;
4961
0
                }
4962
0
            }
4963
0
        }
4964
0
        else {
4965
            // xoptions type is dict[str, str]
4966
0
            if (!PyDict_Check(value)) {
4967
0
                PyErr_Format(PyExc_TypeError,
4968
0
                             "expected dict[str, str | bool], got %T",
4969
0
                             value);
4970
0
                return -1;
4971
0
            }
4972
4973
0
            Py_ssize_t pos = 0;
4974
0
            PyObject *key, *item;
4975
0
            while (PyDict_Next(value, &pos, &key, &item)) {
4976
0
                if (!PyUnicode_Check(key)) {
4977
0
                    PyErr_Format(PyExc_TypeError,
4978
0
                                 "expected str, "
4979
0
                                 "got dict key type %T", key);
4980
0
                    return -1;
4981
0
                }
4982
0
                if (!PyUnicode_Check(item) && !PyBool_Check(item)) {
4983
0
                    PyErr_Format(PyExc_TypeError,
4984
0
                                 "expected str or bool, "
4985
0
                                 "got dict value type %T", key);
4986
0
                    return -1;
4987
0
                }
4988
0
            }
4989
0
        }
4990
0
        break;
4991
4992
0
    default:
4993
0
        Py_UNREACHABLE();
4994
0
    }
4995
4996
    // Set the global variable
4997
0
    if (spec->global_var.ptr != NULL) {
4998
0
        assert(has_int_value);
4999
0
        int value = int_value;
5000
0
        if (spec->global_var.not) {
5001
0
            value = !value;
5002
0
        }
5003
0
        *spec->global_var.ptr = value;
5004
0
    }
5005
5006
0
    if (spec->sys.attr != NULL) {
5007
        // Set the sys attribute, but don't set PyInterpreterState.config
5008
        // to keep the code simple.
5009
0
        return PySys_SetObject(spec->sys.attr, value);
5010
0
    }
5011
0
    else if (has_int_value) {
5012
0
        if (spec->sys.flag_index >= 0) {
5013
0
            return config_set_sys_flag(spec, int_value);
5014
0
        }
5015
0
        else if (strcmp(spec->name, "int_max_str_digits") == 0) {
5016
0
            return _PySys_SetIntMaxStrDigits(int_value);
5017
0
        }
5018
0
        else {
5019
0
            return config_set_int_attr(spec, int_value);
5020
0
        }
5021
0
    }
5022
5023
0
cannot_set:
5024
0
    PyErr_Format(PyExc_ValueError, "cannot set option %s", name);
5025
0
    return -1;
5026
0
}