Unverified Kaydet (Commit) 19760863 authored tarafından Victor Stinner's avatar Victor Stinner Kaydeden (comit) GitHub

bpo-32030: Cleanup pymain_main() (#4935)

* Reorganize pymain_main() to make the code more flat
* Clear configurations before pymain_update_sys_path()
* Mark Py_FatalError() and _Py_FatalInitError() with _Py_NO_RETURN
* Replace _PyMain.run_code variable with a new RUN_CODE() macro
* Move _PyMain.cf into a local variable in pymain_run_python()
üst c4bca951
...@@ -389,6 +389,7 @@ typedef struct { ...@@ -389,6 +389,7 @@ typedef struct {
wchar_t *command; /* -c argument */ wchar_t *command; /* -c argument */
const wchar_t *module; /* -m argument */ const wchar_t *module; /* -m argument */
_Py_OptList warning_options; /* -W options */ _Py_OptList warning_options; /* -W options */
_Py_OptList env_warning_options; /* PYTHONWARNINGS env var */
int print_help; /* -h, -? options */ int print_help; /* -h, -? options */
int print_version; /* -V option */ int print_version; /* -V option */
int bytes_warning; /* Py_BytesWarningFlag, -b */ int bytes_warning; /* Py_BytesWarningFlag, -b */
...@@ -412,41 +413,47 @@ typedef struct { ...@@ -412,41 +413,47 @@ typedef struct {
int legacy_windows_stdio; /* Py_LegacyWindowsStdioFlag, int legacy_windows_stdio; /* Py_LegacyWindowsStdioFlag,
PYTHONLEGACYWINDOWSSTDIO */ PYTHONLEGACYWINDOWSSTDIO */
#endif #endif
_Py_OptList env_warning_options; /* PYTHONWARNINGS env var */
} _Py_CommandLineDetails; } _Py_CommandLineDetails;
/* Structure used by Py_Main() to pass data to subfunctions */ /* Structure used by Py_Main() to pass data to subfunctions */
typedef struct { typedef struct {
/* Exit status ("exit code") */ /* Input arguments */
int argc;
int use_bytes_argv;
char **bytes_argv;
wchar_t **wchar_argv;
/* Exit status or "exit code": result of pymain_main() */
int status; int status;
PyCompilerFlags cf; /* Error message if a function failed */
_PyInitError err;
_Py_CommandLineDetails cmdline;
/* non-zero is stdin is a TTY or if -i option is used */ /* non-zero is stdin is a TTY or if -i option is used */
int stdin_is_interactive; int stdin_is_interactive;
_PyCoreConfig core_config; _PyCoreConfig core_config;
_PyMainInterpreterConfig config; _PyMainInterpreterConfig config;
_Py_CommandLineDetails cmdline;
PyObject *main_importer_path;
/* non-zero if filename, command (-c) or module (-m) is set
on the command line */
int run_code;
/* Error message if a function failed */
_PyInitError err;
int argc; PyObject *main_importer_path;
int use_bytes_argv;
char **bytes_argv;
wchar_t **wchar_argv;
} _PyMain; } _PyMain;
/* .cmdline is initialized to zeros */ /* .cmdline is initialized to zeros */
#define _PyMain_INIT \ #define _PyMain_INIT \
{.core_config = _PyCoreConfig_INIT, \ {.core_config = _PyCoreConfig_INIT, \
.config = _PyMainInterpreterConfig_INIT, \ .config = _PyMainInterpreterConfig_INIT, \
.run_code = -1, \
.err = _Py_INIT_OK()} .err = _Py_INIT_OK()}
/* Note: _PyMain_INIT sets other fields to 0/NULL */ /* Note: _PyMain_INIT sets other fields to 0/NULL */
/* Non-zero if filename, command (-c) or module (-m) is set
on the command line */
#define RUN_CODE(pymain) \
(pymain->cmdline.command != NULL \
|| pymain->cmdline.filename != NULL \
|| pymain->cmdline.module != NULL)
static void static void
pymain_optlist_clear(_Py_OptList *list) pymain_optlist_clear(_Py_OptList *list)
{ {
...@@ -526,7 +533,6 @@ pymain_clear_cmdline(_PyMain *pymain) ...@@ -526,7 +533,6 @@ pymain_clear_cmdline(_PyMain *pymain)
cmdline->argv = NULL; cmdline->argv = NULL;
} }
static void static void
pymain_clear_configs(_PyMain *pymain) pymain_clear_configs(_PyMain *pymain)
{ {
...@@ -816,9 +822,6 @@ pymain_parse_cmdline_impl(_PyMain *pymain) ...@@ -816,9 +822,6 @@ pymain_parse_cmdline_impl(_PyMain *pymain)
cmdline->filename = cmdline->argv[_PyOS_optind]; cmdline->filename = cmdline->argv[_PyOS_optind];
} }
pymain->run_code = (cmdline->command != NULL || cmdline->filename != NULL
|| cmdline->module != NULL);
/* -c and -m options are exclusive */ /* -c and -m options are exclusive */
assert(!(cmdline->command != NULL && cmdline->module != NULL)); assert(!(cmdline->command != NULL && cmdline->module != NULL));
...@@ -1174,12 +1177,11 @@ pymain_get_program_name(_PyMain *pymain) ...@@ -1174,12 +1177,11 @@ pymain_get_program_name(_PyMain *pymain)
static void static void
pymain_header(_PyMain *pymain) pymain_header(_PyMain *pymain)
{ {
/* TODO: Move this to _PyRun_PrepareMain */
if (Py_QuietFlag) { if (Py_QuietFlag) {
return; return;
} }
if (!Py_VerboseFlag && (pymain->run_code || !pymain->stdin_is_interactive)) { if (!Py_VerboseFlag && (RUN_CODE(pymain) || !pymain->stdin_is_interactive)) {
return; return;
} }
...@@ -1291,17 +1293,32 @@ config_init_argv(_PyMainInterpreterConfig *config, const _PyCoreConfig *core_con ...@@ -1291,17 +1293,32 @@ config_init_argv(_PyMainInterpreterConfig *config, const _PyCoreConfig *core_con
static int static int
pymain_update_sys_path(_PyMain *pymain) pymain_init_path0(_PyMain *pymain, PyObject **path0)
{ {
if (pymain->main_importer_path != NULL) { if (pymain->main_importer_path != NULL) {
/* Let pymain_run_main_from_importer() adjust sys.path[0] later */ /* Let pymain_run_main_from_importer() adjust sys.path[0] later */
*path0 = NULL;
return 0; return 0;
} }
if (Py_IsolatedFlag) { if (Py_IsolatedFlag) {
*path0 = NULL;
return 0; return 0;
} }
*path0 = _PyPathConfig_ComputeArgv0(pymain->core_config.argc,
pymain->core_config.argv);
if (*path0 == NULL) {
pymain->err = _Py_INIT_NO_MEMORY();
return -1;
}
return 0;
}
static int
pymain_update_sys_path(_PyMain *pymain, PyObject *path0)
{
/* Prepend argv[0] to sys.path. /* Prepend argv[0] to sys.path.
If argv[0] is a symlink, use the real path. */ If argv[0] is a symlink, use the real path. */
PyObject *sys_path = PySys_GetObject("path"); PyObject *sys_path = PySys_GetObject("path");
...@@ -1310,20 +1327,11 @@ pymain_update_sys_path(_PyMain *pymain) ...@@ -1310,20 +1327,11 @@ pymain_update_sys_path(_PyMain *pymain)
return -1; return -1;
} }
PyObject *path0 = _PyPathConfig_ComputeArgv0(pymain->core_config.argc, pymain->core_config.argv);
if (path0 == NULL) {
pymain->err = _Py_INIT_NO_MEMORY();
return -1;
}
/* Prepend path0 to sys.path */ /* Prepend path0 to sys.path */
if (PyList_Insert(sys_path, 0, path0) < 0) { if (PyList_Insert(sys_path, 0, path0) < 0) {
Py_DECREF(path0);
pymain->err = _Py_INIT_ERR("sys.path.insert(0, path0) failed"); pymain->err = _Py_INIT_ERR("sys.path.insert(0, path0) failed");
return -1; return -1;
} }
Py_DECREF(path0);
return 0; return 0;
} }
...@@ -1357,7 +1365,7 @@ pymain_get_global_config(_PyMain *pymain) ...@@ -1357,7 +1365,7 @@ pymain_get_global_config(_PyMain *pymain)
} }
/* Set Py_XXX global configuration variables */ /* Set Py_xxx global configuration variables */
static void static void
pymain_set_global_config(_PyMain *pymain) pymain_set_global_config(_PyMain *pymain)
{ {
...@@ -1396,7 +1404,7 @@ pymain_import_readline(_PyMain *pymain) ...@@ -1396,7 +1404,7 @@ pymain_import_readline(_PyMain *pymain)
if (Py_IsolatedFlag) { if (Py_IsolatedFlag) {
return; return;
} }
if (!Py_InspectFlag && pymain->run_code) { if (!Py_InspectFlag && RUN_CODE(pymain)) {
return; return;
} }
if (!isatty(fileno(stdin))) { if (!isatty(fileno(stdin))) {
...@@ -1464,13 +1472,13 @@ pymain_open_filename(_PyMain *pymain) ...@@ -1464,13 +1472,13 @@ pymain_open_filename(_PyMain *pymain)
static void static void
pymain_run_filename(_PyMain *pymain) pymain_run_filename(_PyMain *pymain, PyCompilerFlags *cf)
{ {
_Py_CommandLineDetails *cmdline = &pymain->cmdline; _Py_CommandLineDetails *cmdline = &pymain->cmdline;
if (cmdline->filename == NULL && pymain->stdin_is_interactive) { if (cmdline->filename == NULL && pymain->stdin_is_interactive) {
Py_InspectFlag = 0; /* do exit on SystemExit */ Py_InspectFlag = 0; /* do exit on SystemExit */
pymain_run_startup(&pymain->cf); pymain_run_startup(cf);
pymain_run_interactive_hook(); pymain_run_interactive_hook();
} }
...@@ -1490,12 +1498,12 @@ pymain_run_filename(_PyMain *pymain) ...@@ -1490,12 +1498,12 @@ pymain_run_filename(_PyMain *pymain)
fp = stdin; fp = stdin;
} }
pymain->status = pymain_run_file(fp, cmdline->filename, &pymain->cf); pymain->status = pymain_run_file(fp, cmdline->filename, cf);
} }
static void static void
pymain_repl(_PyMain *pymain) pymain_repl(_PyMain *pymain, PyCompilerFlags *cf)
{ {
/* Check this environment variable at the end, to give programs the /* Check this environment variable at the end, to give programs the
opportunity to set it from Python. */ opportunity to set it from Python. */
...@@ -1503,15 +1511,14 @@ pymain_repl(_PyMain *pymain) ...@@ -1503,15 +1511,14 @@ pymain_repl(_PyMain *pymain)
Py_InspectFlag = 1; Py_InspectFlag = 1;
} }
if (!(Py_InspectFlag && pymain->stdin_is_interactive if (!(Py_InspectFlag && pymain->stdin_is_interactive && RUN_CODE(pymain))) {
&& pymain->run_code)) {
return; return;
} }
Py_InspectFlag = 0; Py_InspectFlag = 0;
pymain_run_interactive_hook(); pymain_run_interactive_hook();
int res = PyRun_AnyFileFlags(stdin, "<stdin>", &pymain->cf); int res = PyRun_AnyFileFlags(stdin, "<stdin>", cf);
pymain->status = (res != 0); pymain->status = (res != 0);
} }
...@@ -1966,6 +1973,10 @@ pymain_read_conf_impl(_PyMain *pymain) ...@@ -1966,6 +1973,10 @@ pymain_read_conf_impl(_PyMain *pymain)
return res; return res;
} }
if (pymain_init_core_argv(pymain) < 0) {
return -1;
}
/* Set Py_IgnoreEnvironmentFlag for Py_GETENV() */ /* Set Py_IgnoreEnvironmentFlag for Py_GETENV() */
Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment; Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment;
...@@ -1973,10 +1984,6 @@ pymain_read_conf_impl(_PyMain *pymain) ...@@ -1973,10 +1984,6 @@ pymain_read_conf_impl(_PyMain *pymain)
return -1; return -1;
} }
if (pymain_init_core_argv(pymain) < 0) {
return -1;
}
_PyInitError err = _PyCoreConfig_Read(&pymain->core_config); _PyInitError err = _PyCoreConfig_Read(&pymain->core_config);
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
pymain->err = err; pymain->err = err;
...@@ -1986,6 +1993,8 @@ pymain_read_conf_impl(_PyMain *pymain) ...@@ -1986,6 +1993,8 @@ pymain_read_conf_impl(_PyMain *pymain)
} }
/* Read the configuration, but initialize also the LC_CTYPE locale:
enable UTF-8 mode (PEP 540) and/or coerce the C locale (PEP 538) */
static int static int
pymain_read_conf(_PyMain *pymain) pymain_read_conf(_PyMain *pymain)
{ {
...@@ -2426,9 +2435,21 @@ pymain_init_python_main(_PyMain *pymain) ...@@ -2426,9 +2435,21 @@ pymain_init_python_main(_PyMain *pymain)
pymain->main_importer_path = pymain_get_importer(pymain->cmdline.filename); pymain->main_importer_path = pymain_get_importer(pymain->cmdline.filename);
} }
if (pymain_update_sys_path(pymain) < 0) { PyObject *path0;
if (pymain_init_path0(pymain, &path0) < 0) {
return -1;
}
pymain_clear_configs(pymain);
if (path0 != NULL) {
if (pymain_update_sys_path(pymain, path0) < 0) {
Py_DECREF(path0);
return -1; return -1;
} }
Py_DECREF(path0);
}
return 0; return 0;
} }
...@@ -2436,21 +2457,22 @@ pymain_init_python_main(_PyMain *pymain) ...@@ -2436,21 +2457,22 @@ pymain_init_python_main(_PyMain *pymain)
static void static void
pymain_run_python(_PyMain *pymain) pymain_run_python(_PyMain *pymain)
{ {
PyCompilerFlags cf = {.cf_flags = 0};
_Py_CommandLineDetails *cmdline = &pymain->cmdline; _Py_CommandLineDetails *cmdline = &pymain->cmdline;
pymain_header(pymain); pymain_header(pymain);
pymain_import_readline(pymain); pymain_import_readline(pymain);
if (cmdline->command) { if (cmdline->command) {
pymain->status = pymain_run_command(cmdline->command, &pymain->cf); pymain->status = pymain_run_command(cmdline->command, &cf);
} }
else if (cmdline->module) { else if (cmdline->module) {
pymain->status = (pymain_run_module(cmdline->module, 1) != 0); pymain->status = (pymain_run_module(cmdline->module, 1) != 0);
} }
else { else {
pymain_run_filename(pymain); pymain_run_filename(pymain, &cf);
} }
pymain_repl(pymain); pymain_repl(pymain, &cf);
} }
...@@ -2476,51 +2498,61 @@ pymain_init(_PyMain *pymain) ...@@ -2476,51 +2498,61 @@ pymain_init(_PyMain *pymain)
static int static int
pymain_impl(_PyMain *pymain) pymain_init_cmdline(_PyMain *pymain)
{ {
pymain->err = _PyRuntime_Initialize(); pymain->err = _PyRuntime_Initialize();
if (_Py_INIT_FAILED(pymain->err)) { if (_Py_INIT_FAILED(pymain->err)) {
return -1; return -1;
} }
/* Read the configuration, but initialize also the LC_CTYPE locale:
enable UTF-8 mode (PEP 540) and/or coerce the C locale (PEP 538) */
int res = pymain_read_conf(pymain); int res = pymain_read_conf(pymain);
if (res < 0) { if (res < 0) {
return -1; return -1;
} }
if (res > 0) { if (res > 0) {
/* --help or --version command: we are done */ /* --help or --version command: we are done */
return 0; return 1;
} }
_Py_CommandLineDetails *cmdline = &pymain->cmdline; _Py_CommandLineDetails *cmdline = &pymain->cmdline;
if (cmdline->print_help) { if (cmdline->print_help) {
pymain_usage(0, cmdline->argv[0]); pymain_usage(0, cmdline->argv[0]);
return 0; return 1;
} }
if (cmdline->print_version) { if (cmdline->print_version) {
printf("Python %s\n", printf("Python %s\n",
(cmdline->print_version >= 2) ? Py_GetVersion() : PY_VERSION); (cmdline->print_version >= 2) ? Py_GetVersion() : PY_VERSION);
return 0; return 1;
} }
/* For Py_GetArgcArgv(). Cleared by pymain_free(). */ /* For Py_GetArgcArgv(). Cleared by pymain_free(). */
orig_argc = pymain->argc; orig_argc = pymain->argc;
orig_argv = cmdline->argv; orig_argv = cmdline->argv;
return 0;
}
static int
pymain_main(_PyMain *pymain)
{
pymain_init(pymain);
res = pymain_init_python_core(pymain); int res = pymain_init_cmdline(pymain);
if (res < 0) { if (res < 0) {
return -1; _Py_FatalInitError(pymain->err);
}
if (res == 1) {
goto done;
} }
res = pymain_init_python_main(pymain); if (pymain_init_python_core(pymain) < 0) {
if (res < 0) { _Py_FatalInitError(pymain->err);
return -1;
} }
pymain_clear_configs(pymain); if (pymain_init_python_main(pymain) < 0) {
_Py_FatalInitError(pymain->err);
}
pymain_run_python(pymain); pymain_run_python(pymain);
...@@ -2529,18 +2561,8 @@ pymain_impl(_PyMain *pymain) ...@@ -2529,18 +2561,8 @@ pymain_impl(_PyMain *pymain)
other special meaning */ other special meaning */
pymain->status = 120; pymain->status = 120;
} }
return 0;
}
static int
pymain_main(_PyMain *pymain)
{
pymain_init(pymain);
if (pymain_impl(pymain) < 0) { done:
_Py_FatalInitError(pymain->err);
}
pymain_free(pymain); pymain_free(pymain);
return pymain->status; return pymain->status;
......
...@@ -2003,13 +2003,13 @@ exit: ...@@ -2003,13 +2003,13 @@ exit:
} }
} }
void void _Py_NO_RETURN
Py_FatalError(const char *msg) Py_FatalError(const char *msg)
{ {
fatal_error(NULL, msg, -1); fatal_error(NULL, msg, -1);
} }
void void _Py_NO_RETURN
_Py_FatalInitError(_PyInitError err) _Py_FatalInitError(_PyInitError err)
{ {
/* On "user" error: exit with status 1. /* On "user" error: exit with status 1.
......
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