Commit 13badcbc authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

bpo-32197: Try to fix a compiler error on OS X introduced in bpo-32030. (#4681)

* Revert "bpo-32030: _PyPathConfig_Init() sets home and program_name (#4673)"

This reverts commit af5a8950.

* Revert "bpo-32030: Fix config_get_program_name() on macOS (#4669)"

This reverts commit e23c06e2.

* Revert "bpo-32030: Add Python/pathconfig.c (#4668)"

This reverts commit 0ea395ae.

* Revert "bpo-32030: Don't call _PyPathConfig_Fini() in Py_FinalizeEx() (#4667)"

This reverts commit ebac19da.

* Revert "bpo-32030: Fix Py_GetPath(): init program_name (#4665)"

This reverts commit 9ac3d888.
parent af5a8950
...@@ -40,6 +40,7 @@ The following functions can be safely called before Python is initialized: ...@@ -40,6 +40,7 @@ The following functions can be safely called before Python is initialized:
* :c:func:`Py_GetCompiler` * :c:func:`Py_GetCompiler`
* :c:func:`Py_GetCopyright` * :c:func:`Py_GetCopyright`
* :c:func:`Py_GetPlatform` * :c:func:`Py_GetPlatform`
* :c:func:`Py_GetProgramName`
* :c:func:`Py_GetVersion` * :c:func:`Py_GetVersion`
* Utilities: * Utilities:
...@@ -58,8 +59,8 @@ The following functions can be safely called before Python is initialized: ...@@ -58,8 +59,8 @@ The following functions can be safely called before Python is initialized:
The following functions **should not be called** before The following functions **should not be called** before
:c:func:`Py_Initialize`: :c:func:`Py_EncodeLocale`, :c:func:`Py_GetPath`, :c:func:`Py_Initialize`: :c:func:`Py_EncodeLocale`, :c:func:`Py_GetPath`,
:c:func:`Py_GetPrefix`, :c:func:`Py_GetExecPrefix`, :c:func:`Py_GetPrefix`, :c:func:`Py_GetExecPrefix`,
:c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome`, :c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome` and
:c:func:`Py_GetProgramName` and :c:func:`PyEval_InitThreads`. :c:func:`PyEval_InitThreads`.
.. _global-conf-vars: .. _global-conf-vars:
......
...@@ -48,36 +48,9 @@ typedef struct { ...@@ -48,36 +48,9 @@ typedef struct {
#endif #endif
/* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */ /* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */
wchar_t *module_search_path; wchar_t *module_search_path;
/* Python program name */
wchar_t *program_name;
/* Set by Py_SetPythonHome() or PYTHONHOME environment variable */
wchar_t *home;
} _PyPathConfig; } _PyPathConfig;
#ifdef MS_WINDOWS #define _PyPathConfig_INIT {.module_search_path = NULL}
#define _PyPathConfig_INIT \
{.program_full_path = NULL, \
.prefix = NULL, \
.dll_path = NULL, \
.module_search_path = NULL, \
.program_name = NULL, \
.home = NULL}
#else
#define _PyPathConfig_INIT \
{.program_full_path = NULL, \
.prefix = NULL, \
.exec_prefix = NULL, \
.module_search_path = NULL, \
.program_name = NULL, \
.home = NULL}
#endif
PyAPI_DATA(_PyPathConfig) _Py_path_config;
PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate(
_PyPathConfig *config,
const _PyMainInterpreterConfig *main_config);
PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config);
/* Full Python runtime state */ /* Full Python runtime state */
......
...@@ -105,10 +105,11 @@ PyAPI_FUNC(wchar_t *) Py_GetPath(void); ...@@ -105,10 +105,11 @@ PyAPI_FUNC(wchar_t *) Py_GetPath(void);
#ifdef Py_BUILD_CORE #ifdef Py_BUILD_CORE
PyAPI_FUNC(_PyInitError) _PyPathConfig_Init( PyAPI_FUNC(_PyInitError) _PyPathConfig_Init(
const _PyMainInterpreterConfig *main_config); const _PyMainInterpreterConfig *main_config);
PyAPI_FUNC(void) _PyPathConfig_Fini(void);
#endif #endif
PyAPI_FUNC(void) Py_SetPath(const wchar_t *); PyAPI_FUNC(void) Py_SetPath(const wchar_t *);
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
int _Py_CheckPython3(void); int _Py_CheckPython3();
#endif #endif
/* In their own files */ /* In their own files */
......
...@@ -72,8 +72,7 @@ typedef struct { ...@@ -72,8 +72,7 @@ typedef struct {
(_PyMainInterpreterConfig){\ (_PyMainInterpreterConfig){\
.install_signal_handlers = -1, \ .install_signal_handlers = -1, \
.module_search_path_env = NULL, \ .module_search_path_env = NULL, \
.home = NULL, \ .home = NULL}
.program_name = NULL}
typedef struct _is { typedef struct _is {
......
...@@ -337,9 +337,8 @@ PYTHON_OBJS= \ ...@@ -337,9 +337,8 @@ PYTHON_OBJS= \
Python/importdl.o \ Python/importdl.o \
Python/marshal.o \ Python/marshal.o \
Python/modsupport.o \ Python/modsupport.o \
Python/mysnprintf.o \
Python/mystrtoul.o \ Python/mystrtoul.o \
Python/pathconfig.o \ Python/mysnprintf.o \
Python/peephole.o \ Python/peephole.o \
Python/pyarena.o \ Python/pyarena.o \
Python/pyctype.o \ Python/pyctype.o \
......
...@@ -117,7 +117,10 @@ extern "C" { ...@@ -117,7 +117,10 @@ extern "C" {
typedef struct { typedef struct {
wchar_t *path_env; /* PATH environment variable */ wchar_t *path_env; /* PATH environment variable */
wchar_t *home; /* PYTHONHOME environment variable */
wchar_t *module_search_path_env; /* PYTHONPATH environment variable */
wchar_t *program_name; /* Program name */
wchar_t *pythonpath; /* PYTHONPATH define */ wchar_t *pythonpath; /* PYTHONPATH define */
wchar_t *prefix; /* PREFIX define */ wchar_t *prefix; /* PREFIX define */
wchar_t *exec_prefix; /* EXEC_PREFIX define */ wchar_t *exec_prefix; /* EXEC_PREFIX define */
...@@ -132,6 +135,7 @@ typedef struct { ...@@ -132,6 +135,7 @@ typedef struct {
static const wchar_t delimiter[2] = {DELIM, '\0'}; static const wchar_t delimiter[2] = {DELIM, '\0'};
static const wchar_t separator[2] = {SEP, '\0'}; static const wchar_t separator[2] = {SEP, '\0'};
static _PyPathConfig _Py_path_config = _PyPathConfig_INIT;
/* Get file status. Encode the path to the locale encoding. */ /* Get file status. Encode the path to the locale encoding. */
...@@ -356,15 +360,14 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value) ...@@ -356,15 +360,14 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value)
bytes long. bytes long.
*/ */
static int static int
search_for_prefix(const _PyMainInterpreterConfig *main_config, search_for_prefix(PyCalculatePath *calculate, wchar_t *prefix)
PyCalculatePath *calculate, wchar_t *prefix)
{ {
size_t n; size_t n;
wchar_t *vpath; wchar_t *vpath;
/* If PYTHONHOME is set, we believe it unconditionally */ /* If PYTHONHOME is set, we believe it unconditionally */
if (main_config->home) { if (calculate->home) {
wcsncpy(prefix, main_config->home, MAXPATHLEN); wcsncpy(prefix, calculate->home, MAXPATHLEN);
prefix[MAXPATHLEN] = L'\0'; prefix[MAXPATHLEN] = L'\0';
wchar_t *delim = wcschr(prefix, DELIM); wchar_t *delim = wcschr(prefix, DELIM);
if (delim) { if (delim) {
...@@ -423,10 +426,9 @@ search_for_prefix(const _PyMainInterpreterConfig *main_config, ...@@ -423,10 +426,9 @@ search_for_prefix(const _PyMainInterpreterConfig *main_config,
static void static void
calculate_prefix(const _PyMainInterpreterConfig *main_config, calculate_prefix(PyCalculatePath *calculate, wchar_t *prefix)
PyCalculatePath *calculate, wchar_t *prefix)
{ {
calculate->prefix_found = search_for_prefix(main_config, calculate, prefix); calculate->prefix_found = search_for_prefix(calculate, prefix);
if (!calculate->prefix_found) { if (!calculate->prefix_found) {
if (!Py_FrozenFlag) { if (!Py_FrozenFlag) {
fprintf(stderr, fprintf(stderr,
...@@ -468,19 +470,18 @@ calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix) ...@@ -468,19 +470,18 @@ calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix)
MAXPATHLEN bytes long. MAXPATHLEN bytes long.
*/ */
static int static int
search_for_exec_prefix(const _PyMainInterpreterConfig *main_config, search_for_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)
PyCalculatePath *calculate, wchar_t *exec_prefix)
{ {
size_t n; size_t n;
/* If PYTHONHOME is set, we believe it unconditionally */ /* If PYTHONHOME is set, we believe it unconditionally */
if (main_config->home) { if (calculate->home) {
wchar_t *delim = wcschr(main_config->home, DELIM); wchar_t *delim = wcschr(calculate->home, DELIM);
if (delim) { if (delim) {
wcsncpy(exec_prefix, delim+1, MAXPATHLEN); wcsncpy(exec_prefix, delim+1, MAXPATHLEN);
} }
else { else {
wcsncpy(exec_prefix, main_config->home, MAXPATHLEN); wcsncpy(exec_prefix, calculate->home, MAXPATHLEN);
} }
exec_prefix[MAXPATHLEN] = L'\0'; exec_prefix[MAXPATHLEN] = L'\0';
joinpath(exec_prefix, calculate->lib_python); joinpath(exec_prefix, calculate->lib_python);
...@@ -551,12 +552,9 @@ search_for_exec_prefix(const _PyMainInterpreterConfig *main_config, ...@@ -551,12 +552,9 @@ search_for_exec_prefix(const _PyMainInterpreterConfig *main_config,
static void static void
calculate_exec_prefix(const _PyMainInterpreterConfig *main_config, calculate_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)
PyCalculatePath *calculate, wchar_t *exec_prefix)
{ {
calculate->exec_prefix_found = search_for_exec_prefix(main_config, calculate->exec_prefix_found = search_for_exec_prefix(calculate, exec_prefix);
calculate,
exec_prefix);
if (!calculate->exec_prefix_found) { if (!calculate->exec_prefix_found) {
if (!Py_FrozenFlag) { if (!Py_FrozenFlag) {
fprintf(stderr, fprintf(stderr,
...@@ -587,8 +585,7 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) ...@@ -587,8 +585,7 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix)
static _PyInitError static _PyInitError
calculate_program_full_path(const _PyMainInterpreterConfig *main_config, calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config)
PyCalculatePath *calculate, _PyPathConfig *config)
{ {
wchar_t program_full_path[MAXPATHLEN+1]; wchar_t program_full_path[MAXPATHLEN+1];
memset(program_full_path, 0, sizeof(program_full_path)); memset(program_full_path, 0, sizeof(program_full_path));
...@@ -607,8 +604,8 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config, ...@@ -607,8 +604,8 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config,
* other way to find a directory to start the search from. If * other way to find a directory to start the search from. If
* $PATH isn't exported, you lose. * $PATH isn't exported, you lose.
*/ */
if (wcschr(main_config->program_name, SEP)) { if (wcschr(calculate->program_name, SEP)) {
wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN);
} }
#ifdef __APPLE__ #ifdef __APPLE__
/* On Mac OS X, if a script uses an interpreter of the form /* On Mac OS X, if a script uses an interpreter of the form
...@@ -624,13 +621,11 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config, ...@@ -624,13 +621,11 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config,
else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) && else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) &&
execpath[0] == SEP) execpath[0] == SEP)
{ {
size_t len; size_t r = mbstowcs(program_full_path, execpath, MAXPATHLEN+1);
wchar_t *path = Py_DecodeLocale(execpath, &len); if (r == (size_t)-1 || r > MAXPATHLEN) {
if (path == NULL) { /* Could not convert execpath, or it's too long. */
return DECODE_LOCALE_ERR("executable path", len); program_full_path[0] = '\0';
} }
wcsncpy(program_full_path, path, MAXPATHLEN);
PyMem_RawFree(path);
} }
#endif /* __APPLE__ */ #endif /* __APPLE__ */
else if (calculate->path_env) { else if (calculate->path_env) {
...@@ -650,7 +645,7 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config, ...@@ -650,7 +645,7 @@ calculate_program_full_path(const _PyMainInterpreterConfig *main_config,
wcsncpy(program_full_path, path, MAXPATHLEN); wcsncpy(program_full_path, path, MAXPATHLEN);
} }
joinpath(program_full_path, main_config->program_name); joinpath(program_full_path, calculate->program_name);
if (isxfile(program_full_path)) { if (isxfile(program_full_path)) {
break; break;
} }
...@@ -815,15 +810,14 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) ...@@ -815,15 +810,14 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix)
static _PyInitError static _PyInitError
calculate_module_search_path(const _PyMainInterpreterConfig *main_config, calculate_module_search_path(PyCalculatePath *calculate,
PyCalculatePath *calculate,
const wchar_t *prefix, const wchar_t *exec_prefix, const wchar_t *prefix, const wchar_t *exec_prefix,
_PyPathConfig *config) _PyPathConfig *config)
{ {
/* Calculate size of return buffer */ /* Calculate size of return buffer */
size_t bufsz = 0; size_t bufsz = 0;
if (main_config->module_search_path_env != NULL) { if (calculate->module_search_path_env != NULL) {
bufsz += wcslen(main_config->module_search_path_env) + 1; bufsz += wcslen(calculate->module_search_path_env) + 1;
} }
wchar_t *defpath = calculate->pythonpath; wchar_t *defpath = calculate->pythonpath;
...@@ -857,8 +851,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, ...@@ -857,8 +851,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config,
buf[0] = '\0'; buf[0] = '\0';
/* Run-time value of $PYTHONPATH goes first */ /* Run-time value of $PYTHONPATH goes first */
if (main_config->module_search_path_env) { if (calculate->module_search_path_env) {
wcscpy(buf, main_config->module_search_path_env); wcscpy(buf, calculate->module_search_path_env);
wcscat(buf, delimiter); wcscat(buf, delimiter);
} }
...@@ -909,6 +903,10 @@ static _PyInitError ...@@ -909,6 +903,10 @@ static _PyInitError
calculate_init(PyCalculatePath *calculate, calculate_init(PyCalculatePath *calculate,
const _PyMainInterpreterConfig *main_config) const _PyMainInterpreterConfig *main_config)
{ {
calculate->home = main_config->home;
calculate->module_search_path_env = main_config->module_search_path_env;
calculate->program_name = main_config->program_name;
size_t len; size_t len;
char *path = getenv("PATH"); char *path = getenv("PATH");
if (path) { if (path) {
...@@ -950,12 +948,9 @@ calculate_free(PyCalculatePath *calculate) ...@@ -950,12 +948,9 @@ calculate_free(PyCalculatePath *calculate)
static _PyInitError static _PyInitError
calculate_path_impl(const _PyMainInterpreterConfig *main_config, calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config)
PyCalculatePath *calculate, _PyPathConfig *config)
{ {
_PyInitError err; _PyInitError err = calculate_program_full_path(calculate, config);
err = calculate_program_full_path(main_config, calculate, config);
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
return err; return err;
} }
...@@ -969,13 +964,13 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, ...@@ -969,13 +964,13 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config,
wchar_t prefix[MAXPATHLEN+1]; wchar_t prefix[MAXPATHLEN+1];
memset(prefix, 0, sizeof(prefix)); memset(prefix, 0, sizeof(prefix));
calculate_prefix(main_config, calculate, prefix); calculate_prefix(calculate, prefix);
calculate_zip_path(calculate, prefix); calculate_zip_path(calculate, prefix);
wchar_t exec_prefix[MAXPATHLEN+1]; wchar_t exec_prefix[MAXPATHLEN+1];
memset(exec_prefix, 0, sizeof(exec_prefix)); memset(exec_prefix, 0, sizeof(exec_prefix));
calculate_exec_prefix(main_config, calculate, exec_prefix); calculate_exec_prefix(calculate, exec_prefix);
if ((!calculate->prefix_found || !calculate->exec_prefix_found) && if ((!calculate->prefix_found || !calculate->exec_prefix_found) &&
!Py_FrozenFlag) !Py_FrozenFlag)
...@@ -984,8 +979,8 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, ...@@ -984,8 +979,8 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config,
"Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n"); "Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]\n");
} }
err = calculate_module_search_path(main_config, calculate, err = calculate_module_search_path(calculate, prefix, exec_prefix,
prefix, exec_prefix, config); config);
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
return err; return err;
} }
...@@ -1008,10 +1003,33 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, ...@@ -1008,10 +1003,33 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config,
} }
static void
pathconfig_clear(_PyPathConfig *config)
{
#define CLEAR(ATTR) \
do { \
PyMem_RawFree(ATTR); \
ATTR = NULL; \
} while (0)
CLEAR(config->prefix);
CLEAR(config->exec_prefix);
CLEAR(config->program_full_path);
CLEAR(config->module_search_path);
#undef CLEAR
}
/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix()
and Py_GetProgramFullPath() */
_PyInitError _PyInitError
_PyPathConfig_Calculate(_PyPathConfig *config, _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
const _PyMainInterpreterConfig *main_config)
{ {
if (_Py_path_config.module_search_path) {
/* Already initialized */
return _Py_INIT_OK();
}
PyCalculatePath calculate; PyCalculatePath calculate;
memset(&calculate, 0, sizeof(calculate)); memset(&calculate, 0, sizeof(calculate));
...@@ -1020,11 +1038,16 @@ _PyPathConfig_Calculate(_PyPathConfig *config, ...@@ -1020,11 +1038,16 @@ _PyPathConfig_Calculate(_PyPathConfig *config,
goto done; goto done;
} }
err = calculate_path_impl(main_config, &calculate, config); _PyPathConfig new_path_config;
memset(&new_path_config, 0, sizeof(new_path_config));
err = calculate_path_impl(&calculate, &new_path_config);
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
pathconfig_clear(&new_path_config);
goto done; goto done;
} }
_Py_path_config = new_path_config;
err = _Py_INIT_OK(); err = _Py_INIT_OK();
done: done:
...@@ -1032,6 +1055,88 @@ done: ...@@ -1032,6 +1055,88 @@ done:
return err; return err;
} }
static void
pathconfig_global_init(void)
{
if (_Py_path_config.module_search_path) {
/* Already initialized */
return;
}
_PyInitError err;
_PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT;
err = _PyMainInterpreterConfig_ReadEnv(&config);
if (!_Py_INIT_FAILED(err)) {
err = _PyPathConfig_Init(&config);
}
_PyMainInterpreterConfig_Clear(&config);
if (_Py_INIT_FAILED(err)) {
_Py_FatalInitError(err);
}
}
void
_PyPathConfig_Fini(void)
{
pathconfig_clear(&_Py_path_config);
}
/* External interface */
void
Py_SetPath(const wchar_t *path)
{
if (path == NULL) {
pathconfig_clear(&_Py_path_config);
return;
}
_PyPathConfig new_config;
new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
new_config.exec_prefix = _PyMem_RawWcsdup(L"");
new_config.prefix = _PyMem_RawWcsdup(L"");
new_config.module_search_path = _PyMem_RawWcsdup(path);
pathconfig_clear(&_Py_path_config);
_Py_path_config = new_config;
}
wchar_t *
Py_GetPath(void)
{
pathconfig_global_init();
return _Py_path_config.module_search_path;
}
wchar_t *
Py_GetPrefix(void)
{
pathconfig_global_init();
return _Py_path_config.prefix;
}
wchar_t *
Py_GetExecPrefix(void)
{
pathconfig_global_init();
return _Py_path_config.exec_prefix;
}
wchar_t *
Py_GetProgramFullPath(void)
{
pathconfig_global_init();
return _Py_path_config.program_full_path;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
...@@ -412,6 +412,7 @@ typedef struct { ...@@ -412,6 +412,7 @@ typedef struct {
/* non-zero if filename, command (-c) or module (-m) is set /* non-zero if filename, command (-c) or module (-m) is set
on the command line */ on the command line */
int run_code; int run_code;
wchar_t *program_name;
/* Error message if a function failed */ /* Error message if a function failed */
_PyInitError err; _PyInitError err;
/* PYTHONWARNINGS env var */ /* PYTHONWARNINGS env var */
...@@ -428,6 +429,7 @@ typedef struct { ...@@ -428,6 +429,7 @@ typedef struct {
.config = _PyMainInterpreterConfig_INIT, \ .config = _PyMainInterpreterConfig_INIT, \
.main_importer_path = NULL, \ .main_importer_path = NULL, \
.run_code = -1, \ .run_code = -1, \
.program_name = NULL, \
.err = _Py_INIT_OK(), \ .err = _Py_INIT_OK(), \
.env_warning_options = {0, NULL}} .env_warning_options = {0, NULL}}
...@@ -453,6 +455,7 @@ pymain_free_impl(_PyMain *pymain) ...@@ -453,6 +455,7 @@ pymain_free_impl(_PyMain *pymain)
pymain_optlist_clear(&pymain->env_warning_options); pymain_optlist_clear(&pymain->env_warning_options);
Py_CLEAR(pymain->main_importer_path); Py_CLEAR(pymain->main_importer_path);
PyMem_RawFree(pymain->program_name);
_PyMainInterpreterConfig_Clear(&pymain->config); _PyMainInterpreterConfig_Clear(&pymain->config);
...@@ -871,21 +874,14 @@ pymain_init_stdio(_PyMain *pymain) ...@@ -871,21 +874,14 @@ pymain_init_stdio(_PyMain *pymain)
/* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__ /* Get the program name: use PYTHONEXECUTABLE and __PYVENV_LAUNCHER__
environment variables on macOS if available. */ environment variables on macOS if available, use argv[0] by default.
static _PyInitError
config_get_program_name(_PyMainInterpreterConfig *config)
{
assert(config->program_name == NULL);
/* If Py_SetProgramName() was called, use its value */
wchar_t *program_name = _Py_path_config.program_name;
if (program_name != NULL) {
config->program_name = _PyMem_RawWcsdup(program_name);
if (config->program_name == NULL) {
return _Py_INIT_NO_MEMORY();
}
}
Return 0 on success.
Set pymain->err and return -1 on error. */
static int
pymain_get_program_name(_PyMain *pymain)
{
assert(pymain->program_name == NULL);
#ifdef __APPLE__ #ifdef __APPLE__
char *p; char *p;
/* On MacOS X, when the Python interpreter is embedded in an /* On MacOS X, when the Python interpreter is embedded in an
...@@ -898,13 +894,17 @@ config_get_program_name(_PyMainInterpreterConfig *config) ...@@ -898,13 +894,17 @@ config_get_program_name(_PyMainInterpreterConfig *config)
See Lib/plat-mac/bundlebuiler.py for details about the bootstrap See Lib/plat-mac/bundlebuiler.py for details about the bootstrap
script. */ script. */
if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0') { if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0') {
size_t len; wchar_t* buffer;
wchar_t* program_name = Py_DecodeLocale(p, &len); size_t len = strlen(p) + 1;
if (program_name == NULL) {
return SET_DECODE_ERROR("PYTHONEXECUTABLE environment " buffer = PyMem_RawMalloc(len * sizeof(wchar_t));
"variable", len); if (buffer == NULL) {
pymain->err = _Py_INIT_NO_MEMORY();
return -1;
} }
config->program_name = program_name;
mbstowcs(buffer, p, len);
pymain->program_name = buffer;
} }
#ifdef WITH_NEXT_FRAMEWORK #ifdef WITH_NEXT_FRAMEWORK
else { else {
...@@ -914,30 +914,21 @@ config_get_program_name(_PyMainInterpreterConfig *config) ...@@ -914,30 +914,21 @@ config_get_program_name(_PyMainInterpreterConfig *config)
* the argv0 of the stub executable * the argv0 of the stub executable
*/ */
size_t len; size_t len;
wchar_t* program_name = Py_DecodeLocale(pyvenv_launcher, &len); wchar_t* wbuf = Py_DecodeLocale(pyvenv_launcher, &len);
if (program_name == NULL) { if (wbuf == NULL) {
return SET_DECODE_ERROR("__PYVENV_LAUNCHER__ environment " SET_DECODE_ERROR("__PYVENV_LAUNCHER__", len);
"variable", len); return -1;
} }
config->program_name = program_name; pymain->program_name = wbuf;
} }
} }
#endif /* WITH_NEXT_FRAMEWORK */ #endif /* WITH_NEXT_FRAMEWORK */
#endif /* __APPLE__ */ #endif /* __APPLE__ */
return _Py_INIT_OK(); if (pymain->program_name == NULL) {
}
/* If config_get_program_name() found no program name: use argv[0] by default.
Return 0 on success. Set pymain->err and return -1 on error. */
static int
pymain_get_program_name(_PyMain *pymain)
{
if (pymain->config.program_name == NULL) {
/* Use argv[0] by default */ /* Use argv[0] by default */
pymain->config.program_name = pymain_wstrdup(pymain, pymain->argv[0]); pymain->program_name = pymain_wstrdup(pymain, pymain->argv[0]);
if (pymain->config.program_name == NULL) { if (pymain->program_name == NULL) {
return -1; return -1;
} }
} }
...@@ -959,6 +950,13 @@ pymain_init_main_interpreter(_PyMain *pymain) ...@@ -959,6 +950,13 @@ pymain_init_main_interpreter(_PyMain *pymain)
{ {
_PyInitError err; _PyInitError err;
/* TODO: Print any exceptions raised by these operations */
err = _PyMainInterpreterConfig_Read(&pymain->config);
if (_Py_INIT_FAILED(err)) {
pymain->err = err;
return -1;
}
err = _Py_InitializeMainInterpreter(&pymain->config); err = _Py_InitializeMainInterpreter(&pymain->config);
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
pymain->err = err; pymain->err = err;
...@@ -1416,13 +1414,14 @@ config_init_pythonpath(_PyMainInterpreterConfig *config) ...@@ -1416,13 +1414,14 @@ config_init_pythonpath(_PyMainInterpreterConfig *config)
static _PyInitError static _PyInitError
config_init_home(_PyMainInterpreterConfig *config) config_init_pythonhome(_PyMainInterpreterConfig *config)
{ {
wchar_t *home; wchar_t *home;
/* If Py_SetPythonHome() was called, use its value */ home = Py_GetPythonHome();
home = _Py_path_config.home;
if (home) { if (home) {
/* Py_SetPythonHome() has been called before Py_Main(),
use its value */
config->home = _PyMem_RawWcsdup(home); config->home = _PyMem_RawWcsdup(home);
if (config->home == NULL) { if (config->home == NULL) {
return _Py_INIT_NO_MEMORY(); return _Py_INIT_NO_MEMORY();
...@@ -1442,7 +1441,7 @@ config_init_home(_PyMainInterpreterConfig *config) ...@@ -1442,7 +1441,7 @@ config_init_home(_PyMainInterpreterConfig *config)
_PyInitError _PyInitError
_PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config) _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config)
{ {
_PyInitError err = config_init_home(config); _PyInitError err = config_init_pythonhome(config);
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
return err; return err;
} }
...@@ -1452,9 +1451,11 @@ _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config) ...@@ -1452,9 +1451,11 @@ _PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config)
return err; return err;
} }
err = config_get_program_name(config); /* FIXME: _PyMainInterpreterConfig_Read() has the same code. Remove it
if (_Py_INIT_FAILED(err)) { here? See also pymain_get_program_name() and pymain_parse_envvars(). */
return err; config->program_name = _PyMem_RawWcsdup(Py_GetProgramName());
if (config->program_name == NULL) {
return _Py_INIT_NO_MEMORY();
} }
return _Py_INIT_OK(); return _Py_INIT_OK();
...@@ -1480,17 +1481,25 @@ pymain_parse_envvars(_PyMain *pymain) ...@@ -1480,17 +1481,25 @@ pymain_parse_envvars(_PyMain *pymain)
if (pymain_warnings_envvar(pymain) < 0) { if (pymain_warnings_envvar(pymain) < 0) {
return -1; return -1;
} }
if (pymain_get_program_name(pymain) < 0) {
return -1;
}
core_config->allocator = Py_GETENV("PYTHONMALLOC");
/* FIXME: move pymain_get_program_name() code into
_PyMainInterpreterConfig_ReadEnv().
Problem: _PyMainInterpreterConfig_ReadEnv() doesn't have access
to argv[0]. */
Py_SetProgramName(pymain->program_name);
/* Don't free program_name here: the argument to Py_SetProgramName
must remain valid until Py_FinalizeEx is called. The string is freed
by pymain_free(). */
_PyInitError err = _PyMainInterpreterConfig_ReadEnv(&pymain->config); _PyInitError err = _PyMainInterpreterConfig_ReadEnv(&pymain->config);
if (_Py_INIT_FAILED(pymain->err)) { if (_Py_INIT_FAILED(pymain->err)) {
pymain->err = err; pymain->err = err;
return -1; return -1;
} }
if (pymain_get_program_name(pymain) < 0) {
return -1;
}
core_config->allocator = Py_GETENV("PYTHONMALLOC");
/* -X options */ /* -X options */
if (pymain_get_xoption(pymain, L"showrefcount")) { if (pymain_get_xoption(pymain, L"showrefcount")) {
...@@ -1546,12 +1555,6 @@ pymain_parse_cmdline_envvars_impl(_PyMain *pymain) ...@@ -1546,12 +1555,6 @@ pymain_parse_cmdline_envvars_impl(_PyMain *pymain)
return -1; return -1;
} }
_PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config);
if (_Py_INIT_FAILED(err)) {
pymain->err = err;
return -1;
}
return 0; return 0;
} }
...@@ -1668,14 +1671,6 @@ pymain_impl(_PyMain *pymain) ...@@ -1668,14 +1671,6 @@ pymain_impl(_PyMain *pymain)
other special meaning */ other special meaning */
pymain->status = 120; pymain->status = 120;
} }
/* _PyPathConfig_Clear() cannot be called in Py_FinalizeEx().
Py_Initialize() and Py_Finalize() can be called multiple times, but it
must not "forget" parameters set by Py_SetProgramName(), Py_SetPath() or
Py_SetPythonHome(), whereas _PyPathConfig_Clear() clear all these
parameters. */
_PyPathConfig_Clear(&_Py_path_config);
return 0; return 0;
} }
......
...@@ -118,6 +118,7 @@ ...@@ -118,6 +118,7 @@
#endif #endif
typedef struct { typedef struct {
wchar_t *module_search_path_env; /* PYTHONPATH environment variable */
wchar_t *path_env; /* PATH environment variable */ wchar_t *path_env; /* PATH environment variable */
wchar_t *home; /* PYTHONHOME environment variable */ wchar_t *home; /* PYTHONHOME environment variable */
...@@ -125,11 +126,15 @@ typedef struct { ...@@ -125,11 +126,15 @@ typedef struct {
wchar_t *machine_path; /* from HKEY_LOCAL_MACHINE */ wchar_t *machine_path; /* from HKEY_LOCAL_MACHINE */
wchar_t *user_path; /* from HKEY_CURRENT_USER */ wchar_t *user_path; /* from HKEY_CURRENT_USER */
wchar_t *program_name; /* Program name */
wchar_t argv0_path[MAXPATHLEN+1]; wchar_t argv0_path[MAXPATHLEN+1];
wchar_t zip_path[MAXPATHLEN+1]; wchar_t zip_path[MAXPATHLEN+1];
} PyCalculatePath; } PyCalculatePath;
static _PyPathConfig _Py_path_config = _PyPathConfig_INIT;
/* determine if "ch" is a separator character */ /* determine if "ch" is a separator character */
static int static int
is_sep(wchar_t ch) is_sep(wchar_t ch)
...@@ -498,8 +503,7 @@ get_dll_path(PyCalculatePath *calculate, _PyPathConfig *config) ...@@ -498,8 +503,7 @@ get_dll_path(PyCalculatePath *calculate, _PyPathConfig *config)
static _PyInitError static _PyInitError
get_program_full_path(const _PyMainInterpreterConfig *main_config, get_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config)
PyCalculatePath *calculate, _PyPathConfig *config)
{ {
wchar_t program_full_path[MAXPATHLEN+1]; wchar_t program_full_path[MAXPATHLEN+1];
memset(program_full_path, 0, sizeof(program_full_path)); memset(program_full_path, 0, sizeof(program_full_path));
...@@ -514,13 +518,12 @@ get_program_full_path(const _PyMainInterpreterConfig *main_config, ...@@ -514,13 +518,12 @@ get_program_full_path(const _PyMainInterpreterConfig *main_config,
* $PATH isn't exported, you lose. * $PATH isn't exported, you lose.
*/ */
#ifdef ALTSEP #ifdef ALTSEP
if (wcschr(main_config->program_name, SEP) || if (wcschr(calculate->program_name, SEP) || wcschr(calculate->program_name, ALTSEP))
wcschr(main_config->program_name, ALTSEP))
#else #else
if (wcschr(main_config->program_name, SEP)) if (wcschr(calculate->program_name, SEP))
#endif #endif
{ {
wcsncpy(program_full_path, main_config->program_name, MAXPATHLEN); wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN);
} }
else if (calculate->path_env) { else if (calculate->path_env) {
wchar_t *path = calculate->path_env; wchar_t *path = calculate->path_env;
...@@ -539,7 +542,7 @@ get_program_full_path(const _PyMainInterpreterConfig *main_config, ...@@ -539,7 +542,7 @@ get_program_full_path(const _PyMainInterpreterConfig *main_config,
} }
/* join() is safe for MAXPATHLEN+1 size buffer */ /* join() is safe for MAXPATHLEN+1 size buffer */
join(program_full_path, main_config->program_name); join(program_full_path, calculate->program_name);
if (exists(program_full_path)) { if (exists(program_full_path)) {
break; break;
} }
...@@ -710,6 +713,9 @@ calculate_init(PyCalculatePath *calculate, ...@@ -710,6 +713,9 @@ calculate_init(PyCalculatePath *calculate,
const _PyMainInterpreterConfig *main_config) const _PyMainInterpreterConfig *main_config)
{ {
calculate->home = main_config->home; calculate->home = main_config->home;
calculate->module_search_path_env = main_config->module_search_path_env;
calculate->program_name = main_config->program_name;
calculate->path_env = _wgetenv(L"PATH"); calculate->path_env = _wgetenv(L"PATH");
} }
...@@ -718,16 +724,12 @@ static int ...@@ -718,16 +724,12 @@ static int
get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config) get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config)
{ {
if (config->dll_path[0]) { if (config->dll_path[0]) {
if (!change_ext(spbuffer, config->dll_path, L"._pth") && if (!change_ext(spbuffer, config->dll_path, L"._pth") && exists(spbuffer)) {
exists(spbuffer))
{
return 1; return 1;
} }
} }
if (config->program_full_path[0]) { if (config->program_full_path[0]) {
if (!change_ext(spbuffer, config->program_full_path, L"._pth") && if (!change_ext(spbuffer, config->program_full_path, L"._pth") && exists(spbuffer)) {
exists(spbuffer))
{
return 1; return 1;
} }
} }
...@@ -813,9 +815,7 @@ calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix) ...@@ -813,9 +815,7 @@ calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix)
static _PyInitError static _PyInitError
calculate_module_search_path(const _PyMainInterpreterConfig *main_config, calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, wchar_t *prefix)
PyCalculatePath *calculate, _PyPathConfig *config,
wchar_t *prefix)
{ {
int skiphome = calculate->home==NULL ? 0 : 1; int skiphome = calculate->home==NULL ? 0 : 1;
#ifdef Py_ENABLE_SHARED #ifdef Py_ENABLE_SHARED
...@@ -824,10 +824,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, ...@@ -824,10 +824,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config,
#endif #endif
/* We only use the default relative PYTHONPATH if we haven't /* We only use the default relative PYTHONPATH if we haven't
anything better to use! */ anything better to use! */
int skipdefault = (main_config->module_search_path_env != NULL || int skipdefault = (calculate->module_search_path_env!=NULL || calculate->home!=NULL || \
calculate->home != NULL || calculate->machine_path!=NULL || calculate->user_path!=NULL);
calculate->machine_path != NULL ||
calculate->user_path != NULL);
/* We need to construct a path from the following parts. /* We need to construct a path from the following parts.
(1) the PYTHONPATH environment variable, if set; (1) the PYTHONPATH environment variable, if set;
...@@ -863,8 +861,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, ...@@ -863,8 +861,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config,
bufsz += wcslen(calculate->machine_path) + 1; bufsz += wcslen(calculate->machine_path) + 1;
} }
bufsz += wcslen(calculate->zip_path) + 1; bufsz += wcslen(calculate->zip_path) + 1;
if (main_config->module_search_path_env != NULL) { if (calculate->module_search_path_env != NULL) {
bufsz += wcslen(main_config->module_search_path_env) + 1; bufsz += wcslen(calculate->module_search_path_env) + 1;
} }
wchar_t *buf, *start_buf; wchar_t *buf, *start_buf;
...@@ -872,9 +870,9 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, ...@@ -872,9 +870,9 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config,
if (buf == NULL) { if (buf == NULL) {
/* We can't exit, so print a warning and limp along */ /* We can't exit, so print a warning and limp along */
fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n"); fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");
if (main_config->module_search_path_env) { if (calculate->module_search_path_env) {
fprintf(stderr, "Using environment $PYTHONPATH.\n"); fprintf(stderr, "Using environment $PYTHONPATH.\n");
config->module_search_path = main_config->module_search_path_env; config->module_search_path = calculate->module_search_path_env;
} }
else { else {
fprintf(stderr, "Using default static path.\n"); fprintf(stderr, "Using default static path.\n");
...@@ -884,9 +882,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, ...@@ -884,9 +882,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config,
} }
start_buf = buf; start_buf = buf;
if (main_config->module_search_path_env) { if (calculate->module_search_path_env) {
if (wcscpy_s(buf, bufsz - (buf - start_buf), if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->module_search_path_env)) {
main_config->module_search_path_env)) {
return INIT_ERR_BUFFER_OVERFLOW(); return INIT_ERR_BUFFER_OVERFLOW();
} }
buf = wcschr(buf, L'\0'); buf = wcschr(buf, L'\0');
...@@ -999,8 +996,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config, ...@@ -999,8 +996,8 @@ calculate_module_search_path(const _PyMainInterpreterConfig *main_config,
static _PyInitError static _PyInitError
calculate_path_impl(const _PyMainInterpreterConfig *main_config, calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config,
PyCalculatePath *calculate, _PyPathConfig *config) const _PyMainInterpreterConfig *main_config)
{ {
_PyInitError err; _PyInitError err;
...@@ -1009,7 +1006,7 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, ...@@ -1009,7 +1006,7 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config,
return err; return err;
} }
err = get_program_full_path(main_config, calculate, config); err = get_program_full_path(calculate, config);
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
return err; return err;
} }
...@@ -1035,7 +1032,7 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config, ...@@ -1035,7 +1032,7 @@ calculate_path_impl(const _PyMainInterpreterConfig *main_config,
calculate_home_prefix(calculate, prefix); calculate_home_prefix(calculate, prefix);
err = calculate_module_search_path(main_config, calculate, config, prefix); err = calculate_module_search_path(calculate, config, prefix);
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
return err; return err;
} }
...@@ -1058,28 +1055,145 @@ calculate_free(PyCalculatePath *calculate) ...@@ -1058,28 +1055,145 @@ calculate_free(PyCalculatePath *calculate)
} }
static void
pathconfig_clear(_PyPathConfig *config)
{
#define CLEAR(ATTR) \
do { \
PyMem_RawFree(ATTR); \
ATTR = NULL; \
} while (0)
CLEAR(config->prefix);
CLEAR(config->program_full_path);
CLEAR(config->dll_path);
CLEAR(config->module_search_path);
#undef CLEAR
}
/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix()
and Py_GetProgramFullPath() */
_PyInitError _PyInitError
_PyPathConfig_Calculate(_PyPathConfig *config, _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
const _PyMainInterpreterConfig *main_config)
{ {
if (_Py_path_config.module_search_path) {
/* Already initialized */
return _Py_INIT_OK();
}
_PyInitError err;
PyCalculatePath calculate; PyCalculatePath calculate;
memset(&calculate, 0, sizeof(calculate)); memset(&calculate, 0, sizeof(calculate));
calculate_init(&calculate, main_config); calculate_init(&calculate, main_config);
_PyInitError err = calculate_path_impl(main_config, &calculate, config); _PyPathConfig new_path_config;
memset(&new_path_config, 0, sizeof(new_path_config));
err = calculate_path_impl(&calculate, &new_path_config, main_config);
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
goto done; goto done;
} }
_Py_path_config = new_path_config;
err = _Py_INIT_OK(); err = _Py_INIT_OK();
done: done:
if (_Py_INIT_FAILED(err)) {
pathconfig_clear(&new_path_config);
}
calculate_free(&calculate); calculate_free(&calculate);
return err; return err;
} }
static void
pathconfig_global_init(void)
{
if (_Py_path_config.module_search_path) {
/* Already initialized */
return;
}
_PyInitError err;
_PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT;
err = _PyMainInterpreterConfig_ReadEnv(&config);
if (!_Py_INIT_FAILED(err)) {
err = _PyPathConfig_Init(&config);
}
_PyMainInterpreterConfig_Clear(&config);
if (_Py_INIT_FAILED(err)) {
_Py_FatalInitError(err);
}
}
void
_PyPathConfig_Fini(void)
{
pathconfig_clear(&_Py_path_config);
}
/* External interface */
void
Py_SetPath(const wchar_t *path)
{
if (_Py_path_config.module_search_path != NULL) {
pathconfig_clear(&_Py_path_config);
}
if (path == NULL) {
return;
}
_PyPathConfig new_config;
new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
new_config.prefix = _PyMem_RawWcsdup(L"");
new_config.dll_path = _PyMem_RawWcsdup(L"");
new_config.module_search_path = _PyMem_RawWcsdup(path);
pathconfig_clear(&_Py_path_config);
_Py_path_config = new_config;
}
wchar_t *
Py_GetPath(void)
{
pathconfig_global_init();
return _Py_path_config.module_search_path;
}
wchar_t *
Py_GetPrefix(void)
{
pathconfig_global_init();
return _Py_path_config.prefix;
}
wchar_t *
Py_GetExecPrefix(void)
{
return Py_GetPrefix();
}
wchar_t *
Py_GetProgramFullPath(void)
{
pathconfig_global_init();
return _Py_path_config.program_full_path;
}
/* Load python3.dll before loading any extension module that might refer /* Load python3.dll before loading any extension module that might refer
to it. That way, we can be sure that always the python3.dll corresponding to it. That way, we can be sure that always the python3.dll corresponding
to this python DLL is loaded, not a python3.dll that might be on the path to this python DLL is loaded, not a python3.dll that might be on the path
...@@ -1089,7 +1203,7 @@ done: ...@@ -1089,7 +1203,7 @@ done:
static int python3_checked = 0; static int python3_checked = 0;
static HANDLE hPython3; static HANDLE hPython3;
int int
_Py_CheckPython3(void) _Py_CheckPython3()
{ {
wchar_t py3path[MAXPATHLEN+1]; wchar_t py3path[MAXPATHLEN+1];
wchar_t *s; wchar_t *s;
......
...@@ -381,7 +381,6 @@ ...@@ -381,7 +381,6 @@
<ClCompile Include="..\Python\modsupport.c" /> <ClCompile Include="..\Python\modsupport.c" />
<ClCompile Include="..\Python\mysnprintf.c" /> <ClCompile Include="..\Python\mysnprintf.c" />
<ClCompile Include="..\Python\mystrtoul.c" /> <ClCompile Include="..\Python\mystrtoul.c" />
<ClCompile Include="..\Python\pathconfig.c" />
<ClCompile Include="..\Python\peephole.c" /> <ClCompile Include="..\Python\peephole.c" />
<ClCompile Include="..\Python\pyarena.c" /> <ClCompile Include="..\Python\pyarena.c" />
<ClCompile Include="..\Python\pyctype.c" /> <ClCompile Include="..\Python\pyctype.c" />
......
...@@ -896,9 +896,6 @@ ...@@ -896,9 +896,6 @@
<ClCompile Include="..\Python\mystrtoul.c"> <ClCompile Include="..\Python\mystrtoul.c">
<Filter>Python</Filter> <Filter>Python</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\Python\pathconfig.c">
<Filter>Python</Filter>
</ClCompile>
<ClCompile Include="..\Python\peephole.c"> <ClCompile Include="..\Python\peephole.c">
<Filter>Python</Filter> <Filter>Python</Filter>
</ClCompile> </ClCompile>
......
/* Path configuration like module_search_path (sys.path) */
#include "Python.h"
#include "osdefs.h"
#include "internal/pystate.h"
#ifdef __cplusplus
extern "C" {
#endif
_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
void
_PyPathConfig_Clear(_PyPathConfig *config)
{
/* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
called before Py_Initialize() which can changes the memory allocator. */
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
#define CLEAR(ATTR) \
do { \
PyMem_RawFree(ATTR); \
ATTR = NULL; \
} while (0)
CLEAR(config->prefix);
CLEAR(config->program_full_path);
#ifdef MS_WINDOWS
CLEAR(config->dll_path);
#else
CLEAR(config->exec_prefix);
#endif
CLEAR(config->module_search_path);
CLEAR(config->home);
CLEAR(config->program_name);
#undef CLEAR
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
}
/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix()
and Py_GetProgramFullPath() */
_PyInitError
_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config)
{
if (_Py_path_config.module_search_path) {
/* Already initialized */
return _Py_INIT_OK();
}
_PyInitError err;
_PyPathConfig new_config = _PyPathConfig_INIT;
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
/* Calculate program_full_path, prefix, exec_prefix (Unix)
or dll_path (Windows), and module_search_path */
err = _PyPathConfig_Calculate(&new_config, main_config);
if (_Py_INIT_FAILED(err)) {
_PyPathConfig_Clear(&new_config);
goto done;
}
/* Copy home and program_name from main_config */
if (main_config->home != NULL) {
new_config.home = _PyMem_RawWcsdup(main_config->home);
if (new_config.home == NULL) {
err = _Py_INIT_NO_MEMORY();
goto done;
}
}
else {
new_config.home = NULL;
}
new_config.program_name = _PyMem_RawWcsdup(main_config->program_name);
if (new_config.program_name == NULL) {
err = _Py_INIT_NO_MEMORY();
goto done;
}
_PyPathConfig_Clear(&_Py_path_config);
_Py_path_config = new_config;
err = _Py_INIT_OK();
done:
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
return err;
}
static void
pathconfig_global_init(void)
{
if (_Py_path_config.module_search_path) {
/* Already initialized */
return;
}
_PyInitError err;
_PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT;
err = _PyMainInterpreterConfig_ReadEnv(&config);
if (_Py_INIT_FAILED(err)) {
goto error;
}
err = _PyMainInterpreterConfig_Read(&config);
if (_Py_INIT_FAILED(err)) {
goto error;
}
err = _PyPathConfig_Init(&config);
if (_Py_INIT_FAILED(err)) {
goto error;
}
_PyMainInterpreterConfig_Clear(&config);
return;
error:
_PyMainInterpreterConfig_Clear(&config);
_Py_FatalInitError(err);
}
/* External interface */
void
Py_SetPath(const wchar_t *path)
{
if (path == NULL) {
_PyPathConfig_Clear(&_Py_path_config);
return;
}
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
_PyPathConfig new_config;
new_config.program_full_path = _PyMem_RawWcsdup(Py_GetProgramName());
new_config.prefix = _PyMem_RawWcsdup(L"");
#ifdef MS_WINDOWS
new_config.dll_path = _PyMem_RawWcsdup(L"");
#else
new_config.exec_prefix = _PyMem_RawWcsdup(L"");
#endif
new_config.module_search_path = _PyMem_RawWcsdup(path);
/* steal the home and program_name values (to leave them unchanged) */
new_config.home = _Py_path_config.home;
_Py_path_config.home = NULL;
new_config.program_name = _Py_path_config.program_name;
_Py_path_config.program_name = NULL;
_PyPathConfig_Clear(&_Py_path_config);
_Py_path_config = new_config;
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
}
void
Py_SetPythonHome(wchar_t *home)
{
if (home == NULL) {
return;
}
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
PyMem_RawFree(_Py_path_config.home);
_Py_path_config.home = _PyMem_RawWcsdup(home);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_Py_path_config.home == NULL) {
Py_FatalError("Py_SetPythonHome() failed: out of memory");
}
}
void
Py_SetProgramName(wchar_t *program_name)
{
if (program_name == NULL || program_name[0] == L'\0') {
return;
}
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
PyMem_RawFree(_Py_path_config.program_name);
_Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_Py_path_config.program_name == NULL) {
Py_FatalError("Py_SetProgramName() failed: out of memory");
}
}
wchar_t *
Py_GetPath(void)
{
pathconfig_global_init();
return _Py_path_config.module_search_path;
}
wchar_t *
Py_GetPrefix(void)
{
pathconfig_global_init();
return _Py_path_config.prefix;
}
wchar_t *
Py_GetExecPrefix(void)
{
#ifdef MS_WINDOWS
return Py_GetPrefix();
#else
pathconfig_global_init();
return _Py_path_config.exec_prefix;
#endif
}
wchar_t *
Py_GetProgramFullPath(void)
{
pathconfig_global_init();
return _Py_path_config.program_full_path;
}
wchar_t*
Py_GetPythonHome(void)
{
pathconfig_global_init();
return _Py_path_config.home;
}
wchar_t *
Py_GetProgramName(void)
{
pathconfig_global_init();
return _Py_path_config.program_name;
}
#ifdef __cplusplus
}
#endif
...@@ -804,12 +804,7 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config) ...@@ -804,12 +804,7 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config)
} }
if (config->program_name == NULL) { if (config->program_name == NULL) {
#ifdef MS_WINDOWS config->program_name = _PyMem_RawWcsdup(Py_GetProgramName());
const wchar_t *program_name = L"python";
#else
const wchar_t *program_name = L"python3";
#endif
config->program_name = _PyMem_RawWcsdup(program_name);
if (config->program_name == NULL) { if (config->program_name == NULL) {
return _Py_INIT_NO_MEMORY(); return _Py_INIT_NO_MEMORY();
} }
...@@ -1278,6 +1273,8 @@ Py_FinalizeEx(void) ...@@ -1278,6 +1273,8 @@ Py_FinalizeEx(void)
call_ll_exitfuncs(); call_ll_exitfuncs();
_PyPathConfig_Fini();
_PyRuntime_Finalize(); _PyRuntime_Finalize();
return status; return status;
} }
...@@ -1494,6 +1491,61 @@ Py_EndInterpreter(PyThreadState *tstate) ...@@ -1494,6 +1491,61 @@ Py_EndInterpreter(PyThreadState *tstate)
PyInterpreterState_Delete(interp); PyInterpreterState_Delete(interp);
} }
#ifdef MS_WINDOWS
static wchar_t *progname = L"python";
#else
static wchar_t *progname = L"python3";
#endif
void
Py_SetProgramName(wchar_t *pn)
{
if (pn && *pn)
progname = pn;
}
wchar_t *
Py_GetProgramName(void)
{
return progname;
}
static wchar_t *default_home = NULL;
void
Py_SetPythonHome(wchar_t *home)
{
default_home = home;
}
wchar_t*
Py_GetPythonHome(void)
{
/* Use a static buffer to avoid heap memory allocation failure.
Py_GetPythonHome() doesn't allow to report error, and the caller
doesn't release memory. */
static wchar_t buffer[MAXPATHLEN+1];
if (default_home) {
return default_home;
}
char *home = Py_GETENV("PYTHONHOME");
if (!home) {
return NULL;
}
size_t size = Py_ARRAY_LENGTH(buffer);
size_t r = mbstowcs(buffer, home, size);
if (r == (size_t)-1 || r >= size) {
/* conversion failed or the static buffer is too small */
return NULL;
}
return buffer;
}
/* Add the __main__ module */ /* Add the __main__ module */
static _PyInitError static _PyInitError
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment