summaryrefslogtreecommitdiff
path: root/Modules/main.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2017-05-22 21:36:03 -0700
committerGitHub <noreply@github.com>2017-05-22 21:36:03 -0700
commit6b4be195cd8868b76eb6fbe166acc39beee8ce36 (patch)
treebbab44fad32c576b9eb7e4b83368e200adc33f00 /Modules/main.c
parentf9169ce6b48c7cc7cc62d9eb5e4ee1ac7066d14b (diff)
downloadcpython-git-6b4be195cd8868b76eb6fbe166acc39beee8ce36.tar.gz
bpo-22257: Small changes for PEP 432. (#1728)
PEP 432 specifies a number of large changes to interpreter startup code, including exposing a cleaner C-API. The major changes depend on a number of smaller changes. This patch includes all those smaller changes.
Diffstat (limited to 'Modules/main.c')
-rw-r--r--Modules/main.c287
1 files changed, 180 insertions, 107 deletions
diff --git a/Modules/main.c b/Modules/main.c
index 2fb230a60b..c8d3afd38d 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -343,49 +343,44 @@ run_file(FILE *fp, const wchar_t *filename, PyCompilerFlags *p_cf)
/* Main program */
-int
-Py_Main(int argc, wchar_t **argv)
+/*TODO: Add arg processing to PEP 432 as a new configuration setup API
+ */
+typedef struct {
+ wchar_t *filename; /* Trailing arg without -c or -m */
+ wchar_t *command; /* -c argument */
+ wchar_t *module; /* -m argument */
+ PyObject *warning_options; /* -W options */
+ PyObject *extra_options; /* -X options */
+ int print_help; /* -h, -? options */
+ int print_version; /* -V option */
+ int bytes_warning; /* Py_BytesWarningFlag */
+ int debug; /* Py_DebugFlag */
+ int inspect; /* Py_InspectFlag */
+ int interactive; /* Py_InteractiveFlag */
+ int isolated; /* Py_IsolatedFlag */
+ int optimization_level; /* Py_OptimizeFlag */
+ int dont_write_bytecode; /* Py_DontWriteBytecodeFlag */
+ int no_user_site_directory; /* Py_NoUserSiteDirectory */
+ int no_site_import; /* Py_NoSiteFlag */
+ int use_unbuffered_io; /* Py_UnbufferedStdioFlag */
+ int verbosity; /* Py_VerboseFlag */
+ int quiet_flag; /* Py_QuietFlag */
+ int skip_first_line; /* -x option */
+} _Py_CommandLineDetails;
+
+#define _Py_CommandLineDetails_INIT \
+ {NULL, NULL, NULL, NULL, NULL, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0}
+
+static int
+read_command_line(int argc, wchar_t **argv, _Py_CommandLineDetails *cmdline)
{
- int c;
- int sts;
+ PyObject *warning_option = NULL;
wchar_t *command = NULL;
- wchar_t *filename = NULL;
wchar_t *module = NULL;
- FILE *fp = stdin;
- char *p;
-#ifdef MS_WINDOWS
- wchar_t *wp;
-#endif
- int skipfirstline = 0;
- int stdin_is_interactive = 0;
- int help = 0;
- int version = 0;
- int saw_unbuffered_flag = 0;
+ char c;
char *opt;
- PyCompilerFlags cf;
- PyObject *main_importer_path = NULL;
- PyObject *warning_option = NULL;
- PyObject *warning_options = NULL;
-
- cf.cf_flags = 0;
-
- orig_argc = argc; /* For Py_GetArgcArgv() */
- orig_argv = argv;
-
- /* Hash randomization needed early for all string operations
- (including -W and -X options). */
- _PyOS_opterr = 0; /* prevent printing the error in 1st pass */
- while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
- if (c == 'm' || c == 'c') {
- /* -c / -m is the last option: following arguments are
- not interpreter options. */
- break;
- }
- if (c == 'E') {
- Py_IgnoreEnvironmentFlag++;
- break;
- }
- }
opt = Py_GETENV("PYTHONMALLOC");
if (_PyMem_SetupAllocators(opt) < 0) {
@@ -394,10 +389,11 @@ Py_Main(int argc, wchar_t **argv)
exit(1);
}
+ // TODO: Move these to core runtime init.
Py_HashRandomizationFlag = 1;
- _PyRandom_Init();
-
+ _Py_HashRandomization_Init();
PySys_ResetWarnOptions();
+
_PyOS_ResetGetOpt();
while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
@@ -415,6 +411,7 @@ Py_Main(int argc, wchar_t **argv)
wcscpy(command, _PyOS_optarg);
command[len - 2] = '\n';
command[len - 1] = 0;
+ cmdline->command = command;
break;
}
@@ -423,49 +420,49 @@ Py_Main(int argc, wchar_t **argv)
that look like options are left for the
module to interpret. */
module = _PyOS_optarg;
+ cmdline->module = module;
break;
}
switch (c) {
case 'b':
- Py_BytesWarningFlag++;
+ cmdline->bytes_warning++;
break;
case 'd':
- Py_DebugFlag++;
+ cmdline->debug++;
break;
case 'i':
- Py_InspectFlag++;
- Py_InteractiveFlag++;
+ cmdline->inspect++;
+ cmdline->interactive++;
break;
case 'I':
- Py_IsolatedFlag++;
- Py_NoUserSiteDirectory++;
- Py_IgnoreEnvironmentFlag++;
+ cmdline->isolated++;
+ cmdline->no_user_site_directory++;
break;
/* case 'J': reserved for Jython */
case 'O':
- Py_OptimizeFlag++;
+ cmdline->optimization_level++;
break;
case 'B':
- Py_DontWriteBytecodeFlag++;
+ cmdline->dont_write_bytecode++;
break;
case 's':
- Py_NoUserSiteDirectory++;
+ cmdline->no_user_site_directory++;
break;
case 'S':
- Py_NoSiteFlag++;
+ cmdline->no_site_import++;
break;
case 'E':
- /* Already handled above */
+ /* Handled prior to core initialization */
break;
case 't':
@@ -473,46 +470,46 @@ Py_Main(int argc, wchar_t **argv)
break;
case 'u':
- Py_UnbufferedStdioFlag = 1;
- saw_unbuffered_flag = 1;
+ cmdline->use_unbuffered_io = 1;
break;
case 'v':
- Py_VerboseFlag++;
+ cmdline->verbosity++;
break;
case 'x':
- skipfirstline = 1;
+ cmdline->skip_first_line = 1;
break;
case 'h':
case '?':
- help++;
+ cmdline->print_help++;
break;
case 'V':
- version++;
+ cmdline->print_version++;
break;
case 'W':
- if (warning_options == NULL)
- warning_options = PyList_New(0);
- if (warning_options == NULL)
+ if (cmdline->warning_options == NULL)
+ cmdline->warning_options = PyList_New(0);
+ if (cmdline->warning_options == NULL)
Py_FatalError("failure in handling of -W argument");
warning_option = PyUnicode_FromWideChar(_PyOS_optarg, -1);
if (warning_option == NULL)
Py_FatalError("failure in handling of -W argument");
- if (PyList_Append(warning_options, warning_option) == -1)
+ if (PyList_Append(cmdline->warning_options, warning_option) == -1)
Py_FatalError("failure in handling of -W argument");
Py_DECREF(warning_option);
break;
case 'X':
+ /* TODO: Delay addition of X options to sys module */
PySys_AddXOption(_PyOS_optarg);
break;
case 'q':
- Py_QuietFlag++;
+ cmdline->quiet_flag++;
break;
case 'R':
@@ -522,30 +519,110 @@ Py_Main(int argc, wchar_t **argv)
/* This space reserved for other options */
default:
- return usage(2, argv[0]);
+ return -1;
/*NOTREACHED*/
}
}
- if (help)
- return usage(0, argv[0]);
-
- if (version) {
- printf("Python %s\n", version >= 2 ? Py_GetVersion() : PY_VERSION);
- return 0;
+ if (command == NULL && module == NULL && _PyOS_optind < argc &&
+ wcscmp(argv[_PyOS_optind], L"-") != 0)
+ {
+ cmdline->filename = argv[_PyOS_optind];
}
+ return 0;
+}
+
+static int
+apply_command_line_and_environment(_Py_CommandLineDetails *cmdline)
+{
+ char *p;
+ Py_BytesWarningFlag = cmdline->bytes_warning;
+ Py_DebugFlag = cmdline->debug;
+ Py_InspectFlag = cmdline->inspect;
+ Py_InteractiveFlag = cmdline->interactive;
+ Py_IsolatedFlag = cmdline->isolated;
+ Py_OptimizeFlag = cmdline->optimization_level;
+ Py_DontWriteBytecodeFlag = cmdline->dont_write_bytecode;
+ Py_NoUserSiteDirectory = cmdline->no_user_site_directory;
+ Py_NoSiteFlag = cmdline->no_site_import;
+ Py_UnbufferedStdioFlag = cmdline->use_unbuffered_io;
+ Py_VerboseFlag = cmdline->verbosity;
+ Py_QuietFlag = cmdline->quiet_flag;
if (!Py_InspectFlag &&
- (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
+ (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') {
Py_InspectFlag = 1;
- if (!saw_unbuffered_flag &&
- (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
+ cmdline->inspect = 1;
+ }
+ if (!cmdline->use_unbuffered_io &&
+ (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0') {
Py_UnbufferedStdioFlag = 1;
+ cmdline->use_unbuffered_io = 1;
+ }
if (!Py_NoUserSiteDirectory &&
- (p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0')
+ (p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0') {
Py_NoUserSiteDirectory = 1;
+ cmdline->no_user_site_directory = 1;
+ }
+
+ /* TODO: Apply PYTHONWARNINGS & -W options to sys module here */
+ /* TODO: Apply -X options to sys module here */
+ return 0;
+}
+
+int
+Py_Main(int argc, wchar_t **argv)
+{
+ int c;
+ int sts;
+ FILE *fp = stdin;
+ char *p;
+#ifdef MS_WINDOWS
+ wchar_t *wp;
+#endif
+ int stdin_is_interactive = 0;
+ _Py_CommandLineDetails cmdline = _Py_CommandLineDetails_INIT;
+ PyCompilerFlags cf;
+ PyObject *main_importer_path = NULL;
+
+ cf.cf_flags = 0;
+
+ orig_argc = argc; /* For Py_GetArgcArgv() */
+ orig_argv = argv;
+
+ /* Hash randomization needed early for all string operations
+ (including -W and -X options). */
+ _PyOS_opterr = 0; /* prevent printing the error in 1st pass */
+ while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
+ if (c == 'm' || c == 'c') {
+ /* -c / -m is the last option: following arguments are
+ not interpreter options. */
+ break;
+ }
+ if (c == 'E' || c == 'I') {
+ Py_IgnoreEnvironmentFlag++;
+ break;
+ }
+ }
+
+ /* Reprocess the command line with the language runtime available */
+ if (read_command_line(argc, argv, &cmdline)) {
+ return usage(2, argv[0]);
+ }
+
+ if (cmdline.print_help) {
+ return usage(0, argv[0]);
+ }
+
+ if (cmdline.print_version) {
+ printf("Python %s\n", cmdline.print_version >= 2 ? Py_GetVersion() : PY_VERSION);
+ return 0;
+ }
+
+ PySys_ResetWarnOptions();
+ apply_command_line_and_environment(&cmdline);
#ifdef MS_WINDOWS
if (!Py_IgnoreEnvironmentFlag && (wp = _wgetenv(L"PYTHONWARNINGS")) &&
@@ -598,19 +675,13 @@ Py_Main(int argc, wchar_t **argv)
PyMem_RawFree(buf);
}
#endif
- if (warning_options != NULL) {
+ if (cmdline.warning_options != NULL) {
Py_ssize_t i;
- for (i = 0; i < PyList_GET_SIZE(warning_options); i++) {
- PySys_AddWarnOptionUnicode(PyList_GET_ITEM(warning_options, i));
+ for (i = 0; i < PyList_GET_SIZE(cmdline.warning_options); i++) {
+ PySys_AddWarnOptionUnicode(PyList_GET_ITEM(cmdline.warning_options, i));
}
}
- if (command == NULL && module == NULL && _PyOS_optind < argc &&
- wcscmp(argv[_PyOS_optind], L"-") != 0)
- {
- filename = argv[_PyOS_optind];
- }
-
stdin_is_interactive = Py_FdIsInteractive(stdin, (char *)0);
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
@@ -697,31 +768,31 @@ Py_Main(int argc, wchar_t **argv)
Py_SetProgramName(argv[0]);
#endif
Py_Initialize();
- Py_XDECREF(warning_options);
+ Py_XDECREF(cmdline.warning_options);
if (!Py_QuietFlag && (Py_VerboseFlag ||
- (command == NULL && filename == NULL &&
- module == NULL && stdin_is_interactive))) {
+ (cmdline.command == NULL && cmdline.filename == NULL &&
+ cmdline.module == NULL && stdin_is_interactive))) {
fprintf(stderr, "Python %s on %s\n",
Py_GetVersion(), Py_GetPlatform());
if (!Py_NoSiteFlag)
fprintf(stderr, "%s\n", COPYRIGHT);
}
- if (command != NULL) {
+ if (cmdline.command != NULL) {
/* Backup _PyOS_optind and force sys.argv[0] = '-c' */
_PyOS_optind--;
argv[_PyOS_optind] = L"-c";
}
- if (module != NULL) {
+ if (cmdline.module != NULL) {
/* Backup _PyOS_optind and force sys.argv[0] = '-m'*/
_PyOS_optind--;
argv[_PyOS_optind] = L"-m";
}
- if (filename != NULL) {
- main_importer_path = AsImportPathEntry(filename);
+ if (cmdline.filename != NULL) {
+ main_importer_path = AsImportPathEntry(cmdline.filename);
}
if (main_importer_path != NULL) {
@@ -732,9 +803,11 @@ Py_Main(int argc, wchar_t **argv)
PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
}
- if ((Py_InspectFlag || (command == NULL && filename == NULL && module == NULL)) &&
- isatty(fileno(stdin)) &&
- !Py_IsolatedFlag) {
+ if ((Py_InspectFlag || (cmdline.command == NULL &&
+ cmdline.filename == NULL &&
+ cmdline.module == NULL)) &&
+ isatty(fileno(stdin)) &&
+ !Py_IsolatedFlag) {
PyObject *v;
v = PyImport_ImportModule("readline");
if (v == NULL)
@@ -743,15 +816,15 @@ Py_Main(int argc, wchar_t **argv)
Py_DECREF(v);
}
- if (command) {
- sts = run_command(command, &cf);
- PyMem_RawFree(command);
- } else if (module) {
- sts = (RunModule(module, 1) != 0);
+ if (cmdline.command) {
+ sts = run_command(cmdline.command, &cf);
+ PyMem_RawFree(cmdline.command);
+ } else if (cmdline.module) {
+ sts = (RunModule(cmdline.module, 1) != 0);
}
else {
- if (filename == NULL && stdin_is_interactive) {
+ if (cmdline.filename == NULL && stdin_is_interactive) {
Py_InspectFlag = 0; /* do exit on SystemExit */
RunStartupFile(&cf);
RunInteractiveHook();
@@ -764,13 +837,13 @@ Py_Main(int argc, wchar_t **argv)
sts = RunMainFromImporter(main_importer_path);
}
- if (sts==-1 && filename != NULL) {
- fp = _Py_wfopen(filename, L"r");
+ if (sts==-1 && cmdline.filename != NULL) {
+ fp = _Py_wfopen(cmdline.filename, L"r");
if (fp == NULL) {
char *cfilename_buffer;
const char *cfilename;
int err = errno;
- cfilename_buffer = Py_EncodeLocale(filename, NULL);
+ cfilename_buffer = Py_EncodeLocale(cmdline.filename, NULL);
if (cfilename_buffer != NULL)
cfilename = cfilename_buffer;
else
@@ -781,7 +854,7 @@ Py_Main(int argc, wchar_t **argv)
PyMem_Free(cfilename_buffer);
return 2;
}
- else if (skipfirstline) {
+ else if (cmdline.skip_first_line) {
int ch;
/* Push back first newline so line numbers
remain the same */
@@ -798,7 +871,7 @@ Py_Main(int argc, wchar_t **argv)
S_ISDIR(sb.st_mode)) {
fprintf(stderr,
"%ls: '%ls' is a directory, cannot continue\n",
- argv[0], filename);
+ argv[0], cmdline.filename);
fclose(fp);
return 1;
}
@@ -806,7 +879,7 @@ Py_Main(int argc, wchar_t **argv)
}
if (sts == -1)
- sts = run_file(fp, filename, &cf);
+ sts = run_file(fp, cmdline.filename, &cf);
}
/* Check this environment variable at the end, to give programs the
@@ -819,7 +892,7 @@ Py_Main(int argc, wchar_t **argv)
}
if (Py_InspectFlag && stdin_is_interactive &&
- (filename != NULL || command != NULL || module != NULL)) {
+ (cmdline.filename != NULL || cmdline.command != NULL || cmdline.module != NULL)) {
Py_InspectFlag = 0;
RunInteractiveHook();
/* XXX */