943 lines
23 KiB
C
943 lines
23 KiB
C
/* Python interpreter main program */
|
|
|
|
#include "Python.h"
|
|
#include "pycore_coreconfig.h"
|
|
#include "pycore_pylifecycle.h"
|
|
#include "pycore_pymem.h"
|
|
#include "pycore_pystate.h"
|
|
|
|
#ifdef __FreeBSD__
|
|
# include <fenv.h> /* fedisableexcept() */
|
|
#endif
|
|
|
|
/* Includes for exit_sigint() */
|
|
#include <stdio.h> /* perror() */
|
|
#ifdef HAVE_SIGNAL_H
|
|
# include <signal.h> /* SIGINT */
|
|
#endif
|
|
#if defined(HAVE_GETPID) && defined(HAVE_UNISTD_H)
|
|
# include <unistd.h> /* getpid() */
|
|
#endif
|
|
#ifdef _MSC_VER
|
|
# include <crtdbg.h> /* STATUS_CONTROL_C_EXIT */
|
|
#endif
|
|
/* End of includes for exit_sigint() */
|
|
|
|
#define COPYRIGHT \
|
|
"Type \"help\", \"copyright\", \"credits\" or \"license\" " \
|
|
"for more information."
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* --- PyMainInterpreter ------------------------------------------ */
|
|
|
|
void
|
|
_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config)
|
|
{
|
|
Py_CLEAR(config->argv);
|
|
Py_CLEAR(config->executable);
|
|
Py_CLEAR(config->prefix);
|
|
Py_CLEAR(config->base_prefix);
|
|
Py_CLEAR(config->exec_prefix);
|
|
Py_CLEAR(config->base_exec_prefix);
|
|
Py_CLEAR(config->warnoptions);
|
|
Py_CLEAR(config->xoptions);
|
|
Py_CLEAR(config->module_search_path);
|
|
Py_CLEAR(config->pycache_prefix);
|
|
}
|
|
|
|
|
|
static int
|
|
mainconfig_add_xoption(PyObject *opts, const wchar_t *s)
|
|
{
|
|
PyObject *name, *value;
|
|
|
|
const wchar_t *name_end = wcschr(s, L'=');
|
|
if (!name_end) {
|
|
name = PyUnicode_FromWideChar(s, -1);
|
|
value = Py_True;
|
|
Py_INCREF(value);
|
|
}
|
|
else {
|
|
name = PyUnicode_FromWideChar(s, name_end - s);
|
|
value = PyUnicode_FromWideChar(name_end + 1, -1);
|
|
}
|
|
if (name == NULL || value == NULL) {
|
|
goto error;
|
|
}
|
|
if (PyDict_SetItem(opts, name, value) < 0) {
|
|
goto error;
|
|
}
|
|
Py_DECREF(name);
|
|
Py_DECREF(value);
|
|
return 0;
|
|
|
|
error:
|
|
Py_XDECREF(name);
|
|
Py_XDECREF(value);
|
|
return -1;
|
|
}
|
|
|
|
|
|
static PyObject*
|
|
mainconfig_create_xoptions_dict(const _PyCoreConfig *config)
|
|
{
|
|
int nxoption = config->nxoption;
|
|
wchar_t **xoptions = config->xoptions;
|
|
PyObject *dict = PyDict_New();
|
|
if (dict == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
for (int i=0; i < nxoption; i++) {
|
|
wchar_t *option = xoptions[i];
|
|
if (mainconfig_add_xoption(dict, option) < 0) {
|
|
Py_DECREF(dict);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return dict;
|
|
}
|
|
|
|
|
|
static PyObject*
|
|
mainconfig_copy_attr(PyObject *obj)
|
|
{
|
|
if (PyUnicode_Check(obj)) {
|
|
Py_INCREF(obj);
|
|
return obj;
|
|
}
|
|
else if (PyList_Check(obj)) {
|
|
return PyList_GetSlice(obj, 0, Py_SIZE(obj));
|
|
}
|
|
else if (PyDict_Check(obj)) {
|
|
/* The dict type is used for xoptions. Make the assumption that keys
|
|
and values are immutables */
|
|
return PyDict_Copy(obj);
|
|
}
|
|
else {
|
|
PyErr_Format(PyExc_TypeError,
|
|
"cannot copy config attribute of type %.200s",
|
|
Py_TYPE(obj)->tp_name);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
_PyMainInterpreterConfig_Copy(_PyMainInterpreterConfig *config,
|
|
const _PyMainInterpreterConfig *config2)
|
|
{
|
|
_PyMainInterpreterConfig_Clear(config);
|
|
|
|
#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
|
|
#define COPY_OBJ_ATTR(ATTR) \
|
|
do { \
|
|
if (config2->ATTR != NULL) { \
|
|
config->ATTR = mainconfig_copy_attr(config2->ATTR); \
|
|
if (config->ATTR == NULL) { \
|
|
return -1; \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
COPY_ATTR(install_signal_handlers);
|
|
COPY_OBJ_ATTR(argv);
|
|
COPY_OBJ_ATTR(executable);
|
|
COPY_OBJ_ATTR(prefix);
|
|
COPY_OBJ_ATTR(base_prefix);
|
|
COPY_OBJ_ATTR(exec_prefix);
|
|
COPY_OBJ_ATTR(base_exec_prefix);
|
|
COPY_OBJ_ATTR(warnoptions);
|
|
COPY_OBJ_ATTR(xoptions);
|
|
COPY_OBJ_ATTR(module_search_path);
|
|
COPY_OBJ_ATTR(pycache_prefix);
|
|
#undef COPY_ATTR
|
|
#undef COPY_OBJ_ATTR
|
|
return 0;
|
|
}
|
|
|
|
|
|
PyObject*
|
|
_PyMainInterpreterConfig_AsDict(const _PyMainInterpreterConfig *config)
|
|
{
|
|
PyObject *dict, *obj;
|
|
int res;
|
|
|
|
dict = PyDict_New();
|
|
if (dict == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
#define SET_ITEM_INT(ATTR) \
|
|
do { \
|
|
obj = PyLong_FromLong(config->ATTR); \
|
|
if (obj == NULL) { \
|
|
goto fail; \
|
|
} \
|
|
res = PyDict_SetItemString(dict, #ATTR, obj); \
|
|
Py_DECREF(obj); \
|
|
if (res < 0) { \
|
|
goto fail; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define SET_ITEM_OBJ(ATTR) \
|
|
do { \
|
|
obj = config->ATTR; \
|
|
if (obj == NULL) { \
|
|
obj = Py_None; \
|
|
} \
|
|
res = PyDict_SetItemString(dict, #ATTR, obj); \
|
|
if (res < 0) { \
|
|
goto fail; \
|
|
} \
|
|
} while (0)
|
|
|
|
SET_ITEM_INT(install_signal_handlers);
|
|
SET_ITEM_OBJ(argv);
|
|
SET_ITEM_OBJ(executable);
|
|
SET_ITEM_OBJ(prefix);
|
|
SET_ITEM_OBJ(base_prefix);
|
|
SET_ITEM_OBJ(exec_prefix);
|
|
SET_ITEM_OBJ(base_exec_prefix);
|
|
SET_ITEM_OBJ(warnoptions);
|
|
SET_ITEM_OBJ(xoptions);
|
|
SET_ITEM_OBJ(module_search_path);
|
|
SET_ITEM_OBJ(pycache_prefix);
|
|
|
|
return dict;
|
|
|
|
fail:
|
|
Py_DECREF(dict);
|
|
return NULL;
|
|
|
|
#undef SET_ITEM_OBJ
|
|
}
|
|
|
|
|
|
_PyInitError
|
|
_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *main_config,
|
|
const _PyCoreConfig *config)
|
|
{
|
|
if (main_config->install_signal_handlers < 0) {
|
|
main_config->install_signal_handlers = config->install_signal_handlers;
|
|
}
|
|
|
|
if (main_config->xoptions == NULL) {
|
|
main_config->xoptions = mainconfig_create_xoptions_dict(config);
|
|
if (main_config->xoptions == NULL) {
|
|
return _Py_INIT_NO_MEMORY();
|
|
}
|
|
}
|
|
|
|
#define COPY_WSTR(ATTR) \
|
|
do { \
|
|
if (main_config->ATTR == NULL && config->ATTR != NULL) { \
|
|
main_config->ATTR = PyUnicode_FromWideChar(config->ATTR, -1); \
|
|
if (main_config->ATTR == NULL) { \
|
|
return _Py_INIT_NO_MEMORY(); \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
#define COPY_WSTRLIST(ATTR, LEN, LIST) \
|
|
do { \
|
|
if (ATTR == NULL) { \
|
|
ATTR = _Py_wstrlist_as_pylist(LEN, LIST); \
|
|
if (ATTR == NULL) { \
|
|
return _Py_INIT_NO_MEMORY(); \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
COPY_WSTRLIST(main_config->warnoptions,
|
|
config->nwarnoption, config->warnoptions);
|
|
if (config->argc >= 0) {
|
|
COPY_WSTRLIST(main_config->argv,
|
|
config->argc, config->argv);
|
|
}
|
|
|
|
if (config->_install_importlib) {
|
|
COPY_WSTR(executable);
|
|
COPY_WSTR(prefix);
|
|
COPY_WSTR(base_prefix);
|
|
COPY_WSTR(exec_prefix);
|
|
COPY_WSTR(base_exec_prefix);
|
|
|
|
COPY_WSTRLIST(main_config->module_search_path,
|
|
config->nmodule_search_path, config->module_search_paths);
|
|
|
|
if (config->pycache_prefix != NULL) {
|
|
COPY_WSTR(pycache_prefix);
|
|
} else {
|
|
main_config->pycache_prefix = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
return _Py_INIT_OK();
|
|
#undef COPY_WSTR
|
|
#undef COPY_WSTRLIST
|
|
}
|
|
|
|
|
|
/* --- pymain_init() ---------------------------------------------- */
|
|
|
|
static void
|
|
config_clear(_PyCoreConfig *config)
|
|
{
|
|
PyMemAllocatorEx old_alloc;
|
|
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
|
|
|
_PyCoreConfig_Clear(config);
|
|
|
|
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
|
}
|
|
|
|
|
|
static _PyInitError
|
|
config_read_write(_PyCoreConfig *config, const _PyArgv *args)
|
|
{
|
|
_PyInitError err;
|
|
|
|
PyMemAllocatorEx old_alloc;
|
|
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
|
|
|
_PyCoreConfig_GetGlobalConfig(config);
|
|
|
|
err = _PyCoreConfig_ReadFromArgv(config, args);
|
|
|
|
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
|
|
|
if (_Py_INIT_FAILED(err)) {
|
|
return err;
|
|
}
|
|
|
|
_PyCoreConfig_Write(config);
|
|
return _Py_INIT_OK();
|
|
}
|
|
|
|
|
|
static _PyInitError
|
|
pymain_init_python_main(PyInterpreterState *interp)
|
|
{
|
|
_PyInitError err;
|
|
|
|
_PyMainInterpreterConfig main_config = _PyMainInterpreterConfig_INIT;
|
|
err = _PyMainInterpreterConfig_Read(&main_config, &interp->core_config);
|
|
if (!_Py_INIT_FAILED(err)) {
|
|
err = _Py_InitializeMainInterpreter(interp, &main_config);
|
|
}
|
|
_PyMainInterpreterConfig_Clear(&main_config);
|
|
|
|
if (_Py_INIT_FAILED(err)) {
|
|
return err;
|
|
}
|
|
return _Py_INIT_OK();
|
|
}
|
|
|
|
|
|
static _PyInitError
|
|
pymain_init(const _PyArgv *args, PyInterpreterState **interp_p)
|
|
{
|
|
_PyInitError err;
|
|
|
|
err = _PyRuntime_Initialize();
|
|
if (_Py_INIT_FAILED(err)) {
|
|
return err;
|
|
}
|
|
|
|
/* 754 requires that FP exceptions run in "no stop" mode by default,
|
|
* and until C vendors implement C99's ways to control FP exceptions,
|
|
* Python requires non-stop mode. Alas, some platforms enable FP
|
|
* exceptions by default. Here we disable them.
|
|
*/
|
|
#ifdef __FreeBSD__
|
|
fedisableexcept(FE_OVERFLOW);
|
|
#endif
|
|
|
|
_PyCoreConfig local_config = _PyCoreConfig_INIT;
|
|
_PyCoreConfig *config = &local_config;
|
|
|
|
err = config_read_write(config, args);
|
|
if (_Py_INIT_FAILED(err)) {
|
|
goto done;
|
|
}
|
|
|
|
PyInterpreterState *interp;
|
|
err = _Py_InitializeCore(&interp, config);
|
|
if (_Py_INIT_FAILED(err)) {
|
|
goto done;
|
|
}
|
|
*interp_p = interp;
|
|
|
|
err = pymain_init_python_main(interp);
|
|
if (_Py_INIT_FAILED(err)) {
|
|
goto done;
|
|
}
|
|
|
|
err = _Py_INIT_OK();
|
|
|
|
done:
|
|
config_clear(config);
|
|
return err;
|
|
}
|
|
|
|
|
|
/* --- pymain_run_python() ---------------------------------------- */
|
|
|
|
/* Non-zero if filename, command (-c) or module (-m) is set
|
|
on the command line */
|
|
#define RUN_CODE(config) \
|
|
(config->run_command != NULL || config->run_filename != NULL \
|
|
|| config->run_module != NULL)
|
|
|
|
/* Return non-zero is stdin is a TTY or if -i command line option is used */
|
|
static int
|
|
stdin_is_interactive(const _PyCoreConfig *config)
|
|
{
|
|
return (isatty(fileno(stdin)) || config->interactive);
|
|
}
|
|
|
|
|
|
static PyObject *
|
|
pymain_get_importer(const wchar_t *filename)
|
|
{
|
|
PyObject *sys_path0 = NULL, *importer;
|
|
|
|
sys_path0 = PyUnicode_FromWideChar(filename, wcslen(filename));
|
|
if (sys_path0 == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
importer = PyImport_GetImporter(sys_path0);
|
|
if (importer == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
if (importer == Py_None) {
|
|
Py_DECREF(sys_path0);
|
|
Py_DECREF(importer);
|
|
return NULL;
|
|
}
|
|
|
|
Py_DECREF(importer);
|
|
return sys_path0;
|
|
|
|
error:
|
|
Py_XDECREF(sys_path0);
|
|
PySys_WriteStderr("Failed checking if argv[0] is an import path entry\n");
|
|
PyErr_Print();
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static int
|
|
pymain_sys_path_add_path0(PyInterpreterState *interp, PyObject *path0)
|
|
{
|
|
_Py_IDENTIFIER(path);
|
|
PyObject *sys_path;
|
|
PyObject *sysdict = interp->sysdict;
|
|
if (sysdict != NULL) {
|
|
sys_path = _PyDict_GetItemIdWithError(sysdict, &PyId_path);
|
|
if (sys_path == NULL && PyErr_Occurred()) {
|
|
goto error;
|
|
}
|
|
}
|
|
else {
|
|
sys_path = NULL;
|
|
}
|
|
if (sys_path == NULL) {
|
|
PyErr_SetString(PyExc_RuntimeError, "unable to get sys.path");
|
|
goto error;
|
|
}
|
|
|
|
if (PyList_Insert(sys_path, 0, path0)) {
|
|
goto error;
|
|
}
|
|
return 0;
|
|
|
|
error:
|
|
PyErr_Print();
|
|
return -1;
|
|
}
|
|
|
|
|
|
static void
|
|
pymain_header(const _PyCoreConfig *config)
|
|
{
|
|
if (config->quiet) {
|
|
return;
|
|
}
|
|
|
|
if (!config->verbose && (RUN_CODE(config) || !stdin_is_interactive(config))) {
|
|
return;
|
|
}
|
|
|
|
fprintf(stderr, "Python %s on %s\n", Py_GetVersion(), Py_GetPlatform());
|
|
if (config->site_import) {
|
|
fprintf(stderr, "%s\n", COPYRIGHT);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
pymain_import_readline(const _PyCoreConfig *config)
|
|
{
|
|
if (config->isolated) {
|
|
return;
|
|
}
|
|
if (!config->inspect && RUN_CODE(config)) {
|
|
return;
|
|
}
|
|
if (!isatty(fileno(stdin))) {
|
|
return;
|
|
}
|
|
|
|
PyObject *mod = PyImport_ImportModule("readline");
|
|
if (mod == NULL) {
|
|
PyErr_Clear();
|
|
}
|
|
else {
|
|
Py_DECREF(mod);
|
|
}
|
|
}
|
|
|
|
|
|
static int
|
|
pymain_run_command(wchar_t *command, PyCompilerFlags *cf)
|
|
{
|
|
PyObject *unicode, *bytes;
|
|
int ret;
|
|
|
|
unicode = PyUnicode_FromWideChar(command, -1);
|
|
if (unicode == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
bytes = PyUnicode_AsUTF8String(unicode);
|
|
Py_DECREF(unicode);
|
|
if (bytes == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
ret = PyRun_SimpleStringFlags(PyBytes_AsString(bytes), cf);
|
|
Py_DECREF(bytes);
|
|
return (ret != 0);
|
|
|
|
error:
|
|
PySys_WriteStderr("Unable to decode the command from the command line:\n");
|
|
PyErr_Print();
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int
|
|
pymain_run_module(const wchar_t *modname, int set_argv0)
|
|
{
|
|
PyObject *module, *runpy, *runmodule, *runargs, *result;
|
|
runpy = PyImport_ImportModule("runpy");
|
|
if (runpy == NULL) {
|
|
fprintf(stderr, "Could not import runpy module\n");
|
|
PyErr_Print();
|
|
return -1;
|
|
}
|
|
runmodule = PyObject_GetAttrString(runpy, "_run_module_as_main");
|
|
if (runmodule == NULL) {
|
|
fprintf(stderr, "Could not access runpy._run_module_as_main\n");
|
|
PyErr_Print();
|
|
Py_DECREF(runpy);
|
|
return -1;
|
|
}
|
|
module = PyUnicode_FromWideChar(modname, wcslen(modname));
|
|
if (module == NULL) {
|
|
fprintf(stderr, "Could not convert module name to unicode\n");
|
|
PyErr_Print();
|
|
Py_DECREF(runpy);
|
|
Py_DECREF(runmodule);
|
|
return -1;
|
|
}
|
|
runargs = Py_BuildValue("(Oi)", module, set_argv0);
|
|
if (runargs == NULL) {
|
|
fprintf(stderr,
|
|
"Could not create arguments for runpy._run_module_as_main\n");
|
|
PyErr_Print();
|
|
Py_DECREF(runpy);
|
|
Py_DECREF(runmodule);
|
|
Py_DECREF(module);
|
|
return -1;
|
|
}
|
|
result = PyObject_Call(runmodule, runargs, NULL);
|
|
if (result == NULL) {
|
|
PyErr_Print();
|
|
}
|
|
Py_DECREF(runpy);
|
|
Py_DECREF(runmodule);
|
|
Py_DECREF(module);
|
|
Py_DECREF(runargs);
|
|
if (result == NULL) {
|
|
return -1;
|
|
}
|
|
Py_DECREF(result);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
pymain_run_file(_PyCoreConfig *config, PyCompilerFlags *cf)
|
|
{
|
|
const wchar_t *filename = config->run_filename;
|
|
FILE *fp = _Py_wfopen(filename, L"r");
|
|
if (fp == NULL) {
|
|
char *cfilename_buffer;
|
|
const char *cfilename;
|
|
int err = errno;
|
|
cfilename_buffer = _Py_EncodeLocaleRaw(filename, NULL);
|
|
if (cfilename_buffer != NULL)
|
|
cfilename = cfilename_buffer;
|
|
else
|
|
cfilename = "<unprintable file name>";
|
|
fprintf(stderr, "%ls: can't open file '%s': [Errno %d] %s\n",
|
|
config->program, cfilename, err, strerror(err));
|
|
PyMem_RawFree(cfilename_buffer);
|
|
return 2;
|
|
}
|
|
|
|
if (config->skip_source_first_line) {
|
|
int ch;
|
|
/* Push back first newline so line numbers remain the same */
|
|
while ((ch = getc(fp)) != EOF) {
|
|
if (ch == '\n') {
|
|
(void)ungetc(ch, fp);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
struct _Py_stat_struct sb;
|
|
if (_Py_fstat_noraise(fileno(fp), &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
|
fprintf(stderr,
|
|
"%ls: '%ls' is a directory, cannot continue\n",
|
|
config->program, filename);
|
|
fclose(fp);
|
|
return 1;
|
|
}
|
|
|
|
/* call pending calls like signal handlers (SIGINT) */
|
|
if (Py_MakePendingCalls() == -1) {
|
|
PyErr_Print();
|
|
fclose(fp);
|
|
return 1;
|
|
}
|
|
|
|
PyObject *unicode, *bytes = NULL;
|
|
const char *filename_str;
|
|
|
|
unicode = PyUnicode_FromWideChar(filename, wcslen(filename));
|
|
if (unicode != NULL) {
|
|
bytes = PyUnicode_EncodeFSDefault(unicode);
|
|
Py_DECREF(unicode);
|
|
}
|
|
if (bytes != NULL) {
|
|
filename_str = PyBytes_AsString(bytes);
|
|
}
|
|
else {
|
|
PyErr_Clear();
|
|
filename_str = "<filename encoding error>";
|
|
}
|
|
|
|
/* PyRun_AnyFileExFlags(closeit=1) calls fclose(fp) before running code */
|
|
int run = PyRun_AnyFileExFlags(fp, filename_str, 1, cf);
|
|
Py_XDECREF(bytes);
|
|
return (run != 0);
|
|
}
|
|
|
|
|
|
static void
|
|
pymain_run_startup(_PyCoreConfig *config, PyCompilerFlags *cf)
|
|
{
|
|
const char *startup = _PyCoreConfig_GetEnv(config, "PYTHONSTARTUP");
|
|
if (startup == NULL) {
|
|
return;
|
|
}
|
|
|
|
FILE *fp = _Py_fopen(startup, "r");
|
|
if (fp == NULL) {
|
|
int save_errno = errno;
|
|
PySys_WriteStderr("Could not open PYTHONSTARTUP\n");
|
|
errno = save_errno;
|
|
|
|
PyErr_SetFromErrnoWithFilename(PyExc_OSError,
|
|
startup);
|
|
PyErr_Print();
|
|
return;
|
|
}
|
|
|
|
(void) PyRun_SimpleFileExFlags(fp, startup, 0, cf);
|
|
PyErr_Clear();
|
|
fclose(fp);
|
|
}
|
|
|
|
|
|
static void
|
|
pymain_run_interactive_hook(void)
|
|
{
|
|
PyObject *sys, *hook, *result;
|
|
sys = PyImport_ImportModule("sys");
|
|
if (sys == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
hook = PyObject_GetAttrString(sys, "__interactivehook__");
|
|
Py_DECREF(sys);
|
|
if (hook == NULL) {
|
|
PyErr_Clear();
|
|
return;
|
|
}
|
|
|
|
result = _PyObject_CallNoArg(hook);
|
|
Py_DECREF(hook);
|
|
if (result == NULL) {
|
|
goto error;
|
|
}
|
|
Py_DECREF(result);
|
|
|
|
return;
|
|
|
|
error:
|
|
PySys_WriteStderr("Failed calling sys.__interactivehook__\n");
|
|
PyErr_Print();
|
|
}
|
|
|
|
|
|
static int
|
|
pymain_run_stdin(_PyCoreConfig *config, PyCompilerFlags *cf)
|
|
{
|
|
if (stdin_is_interactive(config)) {
|
|
Py_InspectFlag = 0; /* do exit on SystemExit */
|
|
config->inspect = 0;
|
|
pymain_run_startup(config, cf);
|
|
pymain_run_interactive_hook();
|
|
}
|
|
|
|
/* call pending calls like signal handlers (SIGINT) */
|
|
if (Py_MakePendingCalls() == -1) {
|
|
PyErr_Print();
|
|
return 1;
|
|
}
|
|
|
|
int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, cf);
|
|
return (run != 0);
|
|
}
|
|
|
|
|
|
static void
|
|
pymain_repl(_PyCoreConfig *config, PyCompilerFlags *cf, int *exitcode)
|
|
{
|
|
/* Check this environment variable at the end, to give programs the
|
|
opportunity to set it from Python. */
|
|
if (!Py_InspectFlag && _PyCoreConfig_GetEnv(config, "PYTHONINSPECT")) {
|
|
Py_InspectFlag = 1;
|
|
config->inspect = 1;
|
|
}
|
|
|
|
if (!(Py_InspectFlag && stdin_is_interactive(config) && RUN_CODE(config))) {
|
|
return;
|
|
}
|
|
|
|
Py_InspectFlag = 0;
|
|
config->inspect = 0;
|
|
pymain_run_interactive_hook();
|
|
|
|
int res = PyRun_AnyFileFlags(stdin, "<stdin>", cf);
|
|
*exitcode = (res != 0);
|
|
}
|
|
|
|
|
|
static _PyInitError
|
|
pymain_run_python(PyInterpreterState *interp, int *exitcode)
|
|
{
|
|
_PyInitError err;
|
|
_PyCoreConfig *config = &interp->core_config;
|
|
|
|
PyObject *main_importer_path = NULL;
|
|
if (config->run_filename != NULL) {
|
|
/* If filename is a package (ex: directory or ZIP file) which contains
|
|
__main__.py, main_importer_path is set to filename and will be
|
|
prepended to sys.path.
|
|
|
|
Otherwise, main_importer_path is set to NULL. */
|
|
main_importer_path = pymain_get_importer(config->run_filename);
|
|
}
|
|
|
|
if (main_importer_path != NULL) {
|
|
if (pymain_sys_path_add_path0(interp, main_importer_path) < 0) {
|
|
err = _Py_INIT_EXIT(1);
|
|
goto done;
|
|
}
|
|
}
|
|
else if (!config->isolated) {
|
|
PyObject *path0 = _PyPathConfig_ComputeArgv0(config->argc,
|
|
config->argv);
|
|
if (path0 == NULL) {
|
|
err = _Py_INIT_NO_MEMORY();
|
|
goto done;
|
|
}
|
|
|
|
if (pymain_sys_path_add_path0(interp, path0) < 0) {
|
|
Py_DECREF(path0);
|
|
err = _Py_INIT_EXIT(1);
|
|
goto done;
|
|
}
|
|
Py_DECREF(path0);
|
|
}
|
|
|
|
PyCompilerFlags cf = {.cf_flags = 0};
|
|
|
|
pymain_header(config);
|
|
pymain_import_readline(config);
|
|
|
|
if (config->run_command) {
|
|
*exitcode = pymain_run_command(config->run_command, &cf);
|
|
}
|
|
else if (config->run_module) {
|
|
*exitcode = (pymain_run_module(config->run_module, 1) != 0);
|
|
}
|
|
else if (main_importer_path != NULL) {
|
|
int sts = pymain_run_module(L"__main__", 0);
|
|
*exitcode = (sts != 0);
|
|
}
|
|
else if (config->run_filename != NULL) {
|
|
*exitcode = pymain_run_file(config, &cf);
|
|
}
|
|
else {
|
|
*exitcode = pymain_run_stdin(config, &cf);
|
|
}
|
|
|
|
pymain_repl(config, &cf, exitcode);
|
|
err = _Py_INIT_OK();
|
|
|
|
done:
|
|
Py_XDECREF(main_importer_path);
|
|
return err;
|
|
}
|
|
|
|
|
|
/* --- pymain_main() ---------------------------------------------- */
|
|
|
|
static void
|
|
pymain_free(void)
|
|
{
|
|
_PyImport_Fini2();
|
|
|
|
/* Free global variables which cannot be freed in Py_Finalize():
|
|
configuration options set before Py_Initialize() which should
|
|
remain valid after Py_Finalize(), since
|
|
Py_Initialize()-Py_Finalize() can be called multiple times. */
|
|
_PyPathConfig_ClearGlobal();
|
|
_Py_ClearStandardStreamEncoding();
|
|
_Py_ClearArgcArgv();
|
|
#ifdef __INSURE__
|
|
/* Insure++ is a memory analysis tool that aids in discovering
|
|
* memory leaks and other memory problems. On Python exit, the
|
|
* interned string dictionaries are flagged as being in use at exit
|
|
* (which it is). Under normal circumstances, this is fine because
|
|
* the memory will be automatically reclaimed by the system. Under
|
|
* memory debugging, it's a huge source of useless noise, so we
|
|
* trade off slower shutdown for less distraction in the memory
|
|
* reports. -baw
|
|
*/
|
|
_Py_ReleaseInternedUnicodeStrings();
|
|
#endif /* __INSURE__ */
|
|
}
|
|
|
|
|
|
static int
|
|
exit_sigint(void)
|
|
{
|
|
/* bpo-1054041: We need to exit via the
|
|
* SIG_DFL handler for SIGINT if KeyboardInterrupt went unhandled.
|
|
* If we don't, a calling process such as a shell may not know
|
|
* about the user's ^C. https://www.cons.org/cracauer/sigint.html */
|
|
#if defined(HAVE_GETPID) && !defined(MS_WINDOWS)
|
|
if (PyOS_setsig(SIGINT, SIG_DFL) == SIG_ERR) {
|
|
perror("signal"); /* Impossible in normal environments. */
|
|
} else {
|
|
kill(getpid(), SIGINT);
|
|
}
|
|
/* If setting SIG_DFL failed, or kill failed to terminate us,
|
|
* there isn't much else we can do aside from an error code. */
|
|
#endif /* HAVE_GETPID && !MS_WINDOWS */
|
|
#ifdef MS_WINDOWS
|
|
/* cmd.exe detects this, prints ^C, and offers to terminate. */
|
|
/* https://msdn.microsoft.com/en-us/library/cc704588.aspx */
|
|
return STATUS_CONTROL_C_EXIT;
|
|
#else
|
|
return SIGINT + 128;
|
|
#endif /* !MS_WINDOWS */
|
|
}
|
|
|
|
|
|
static int
|
|
pymain_main(_PyArgv *args)
|
|
{
|
|
_PyInitError err;
|
|
|
|
PyInterpreterState *interp;
|
|
err = pymain_init(args, &interp);
|
|
if (_Py_INIT_FAILED(err)) {
|
|
_Py_ExitInitError(err);
|
|
}
|
|
|
|
int exitcode = 0;
|
|
err = pymain_run_python(interp, &exitcode);
|
|
if (_Py_INIT_FAILED(err)) {
|
|
_Py_ExitInitError(err);
|
|
}
|
|
|
|
if (Py_FinalizeEx() < 0) {
|
|
/* Value unlikely to be confused with a non-error exit status or
|
|
other special meaning */
|
|
exitcode = 120;
|
|
}
|
|
|
|
pymain_free();
|
|
|
|
if (_Py_UnhandledKeyboardInterrupt) {
|
|
exitcode = exit_sigint();
|
|
}
|
|
|
|
return exitcode;
|
|
}
|
|
|
|
|
|
int
|
|
Py_Main(int argc, wchar_t **argv)
|
|
{
|
|
_PyArgv args = {
|
|
.argc = argc,
|
|
.use_bytes_argv = 0,
|
|
.bytes_argv = NULL,
|
|
.wchar_argv = argv};
|
|
return pymain_main(&args);
|
|
}
|
|
|
|
|
|
int
|
|
_Py_UnixMain(int argc, char **argv)
|
|
{
|
|
_PyArgv args = {
|
|
.argc = argc,
|
|
.use_bytes_argv = 1,
|
|
.bytes_argv = argv,
|
|
.wchar_argv = NULL};
|
|
return pymain_main(&args);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|