1 | /* Python interpreter main program */ |
2 | |
3 | #include "Python.h" |
4 | #include "pycore_initconfig.h" // _PyArgv |
5 | #include "pycore_interp.h" // _PyInterpreterState.sysdict |
6 | #include "pycore_pathconfig.h" // _PyPathConfig_ComputeSysPath0() |
7 | #include "pycore_pylifecycle.h" // _Py_PreInitializeFromPyArgv() |
8 | #include "pycore_pystate.h" // _PyInterpreterState_GET() |
9 | |
10 | /* Includes for exit_sigint() */ |
11 | #include <stdio.h> // perror() |
12 | #ifdef HAVE_SIGNAL_H |
13 | # include <signal.h> // SIGINT |
14 | #endif |
15 | #if defined(HAVE_GETPID) && defined(HAVE_UNISTD_H) |
16 | # include <unistd.h> // getpid() |
17 | #endif |
18 | #ifdef MS_WINDOWS |
19 | # include <windows.h> // STATUS_CONTROL_C_EXIT |
20 | #endif |
21 | /* End of includes for exit_sigint() */ |
22 | |
23 | #define COPYRIGHT \ |
24 | "Type \"help\", \"copyright\", \"credits\" or \"license\" " \ |
25 | "for more information." |
26 | |
27 | #ifdef __cplusplus |
28 | extern "C" { |
29 | #endif |
30 | |
31 | /* --- pymain_init() ---------------------------------------------- */ |
32 | |
33 | static PyStatus |
34 | pymain_init(const _PyArgv *args) |
35 | { |
36 | PyStatus status; |
37 | |
38 | status = _PyRuntime_Initialize(); |
39 | if (_PyStatus_EXCEPTION(status)) { |
40 | return status; |
41 | } |
42 | |
43 | PyPreConfig preconfig; |
44 | PyPreConfig_InitPythonConfig(&preconfig); |
45 | |
46 | status = _Py_PreInitializeFromPyArgv(&preconfig, args); |
47 | if (_PyStatus_EXCEPTION(status)) { |
48 | return status; |
49 | } |
50 | |
51 | PyConfig config; |
52 | PyConfig_InitPythonConfig(&config); |
53 | |
54 | /* pass NULL as the config: config is read from command line arguments, |
55 | environment variables, configuration files */ |
56 | if (args->use_bytes_argv) { |
57 | status = PyConfig_SetBytesArgv(&config, args->argc, args->bytes_argv); |
58 | } |
59 | else { |
60 | status = PyConfig_SetArgv(&config, args->argc, args->wchar_argv); |
61 | } |
62 | if (_PyStatus_EXCEPTION(status)) { |
63 | goto done; |
64 | } |
65 | |
66 | status = Py_InitializeFromConfig(&config); |
67 | if (_PyStatus_EXCEPTION(status)) { |
68 | goto done; |
69 | } |
70 | status = _PyStatus_OK(); |
71 | |
72 | done: |
73 | PyConfig_Clear(&config); |
74 | return status; |
75 | } |
76 | |
77 | |
78 | /* --- pymain_run_python() ---------------------------------------- */ |
79 | |
80 | /* Non-zero if filename, command (-c) or module (-m) is set |
81 | on the command line */ |
82 | static inline int config_run_code(const PyConfig *config) |
83 | { |
84 | return (config->run_command != NULL |
85 | || config->run_filename != NULL |
86 | || config->run_module != NULL); |
87 | } |
88 | |
89 | |
90 | /* Return non-zero if stdin is a TTY or if -i command line option is used */ |
91 | static int |
92 | stdin_is_interactive(const PyConfig *config) |
93 | { |
94 | return (isatty(fileno(stdin)) || config->interactive); |
95 | } |
96 | |
97 | |
98 | /* Display the current Python exception and return an exitcode */ |
99 | static int |
100 | pymain_err_print(int *exitcode_p) |
101 | { |
102 | int exitcode; |
103 | if (_Py_HandleSystemExit(&exitcode)) { |
104 | *exitcode_p = exitcode; |
105 | return 1; |
106 | } |
107 | |
108 | PyErr_Print(); |
109 | return 0; |
110 | } |
111 | |
112 | |
113 | static int |
114 | pymain_exit_err_print(void) |
115 | { |
116 | int exitcode = 1; |
117 | pymain_err_print(&exitcode); |
118 | return exitcode; |
119 | } |
120 | |
121 | |
122 | /* Write an exitcode into *exitcode and return 1 if we have to exit Python. |
123 | Return 0 otherwise. */ |
124 | static int |
125 | pymain_get_importer(const wchar_t *filename, PyObject **importer_p, int *exitcode) |
126 | { |
127 | PyObject *sys_path0 = NULL, *importer; |
128 | |
129 | sys_path0 = PyUnicode_FromWideChar(filename, wcslen(filename)); |
130 | if (sys_path0 == NULL) { |
131 | goto error; |
132 | } |
133 | |
134 | importer = PyImport_GetImporter(sys_path0); |
135 | if (importer == NULL) { |
136 | goto error; |
137 | } |
138 | |
139 | if (importer == Py_None) { |
140 | Py_DECREF(sys_path0); |
141 | Py_DECREF(importer); |
142 | return 0; |
143 | } |
144 | |
145 | Py_DECREF(importer); |
146 | *importer_p = sys_path0; |
147 | return 0; |
148 | |
149 | error: |
150 | Py_XDECREF(sys_path0); |
151 | |
152 | PySys_WriteStderr("Failed checking if argv[0] is an import path entry\n" ); |
153 | return pymain_err_print(exitcode); |
154 | } |
155 | |
156 | |
157 | static int |
158 | pymain_sys_path_add_path0(PyInterpreterState *interp, PyObject *path0) |
159 | { |
160 | _Py_IDENTIFIER(path); |
161 | PyObject *sys_path; |
162 | PyObject *sysdict = interp->sysdict; |
163 | if (sysdict != NULL) { |
164 | sys_path = _PyDict_GetItemIdWithError(sysdict, &PyId_path); |
165 | if (sys_path == NULL && PyErr_Occurred()) { |
166 | return -1; |
167 | } |
168 | } |
169 | else { |
170 | sys_path = NULL; |
171 | } |
172 | if (sys_path == NULL) { |
173 | PyErr_SetString(PyExc_RuntimeError, "unable to get sys.path" ); |
174 | return -1; |
175 | } |
176 | |
177 | if (PyList_Insert(sys_path, 0, path0)) { |
178 | return -1; |
179 | } |
180 | return 0; |
181 | } |
182 | |
183 | |
184 | static void |
185 | pymain_header(const PyConfig *config) |
186 | { |
187 | if (config->quiet) { |
188 | return; |
189 | } |
190 | |
191 | if (!config->verbose && (config_run_code(config) || !stdin_is_interactive(config))) { |
192 | return; |
193 | } |
194 | |
195 | fprintf(stderr, "Python %s on %s\n" , Py_GetVersion(), Py_GetPlatform()); |
196 | if (config->site_import) { |
197 | fprintf(stderr, "%s\n" , COPYRIGHT); |
198 | } |
199 | } |
200 | |
201 | |
202 | static void |
203 | pymain_import_readline(const PyConfig *config) |
204 | { |
205 | if (config->isolated) { |
206 | return; |
207 | } |
208 | if (!config->inspect && config_run_code(config)) { |
209 | return; |
210 | } |
211 | if (!isatty(fileno(stdin))) { |
212 | return; |
213 | } |
214 | |
215 | PyObject *mod = PyImport_ImportModule("readline" ); |
216 | if (mod == NULL) { |
217 | PyErr_Clear(); |
218 | } |
219 | else { |
220 | Py_DECREF(mod); |
221 | } |
222 | } |
223 | |
224 | |
225 | static int |
226 | pymain_run_command(wchar_t *command) |
227 | { |
228 | PyObject *unicode, *bytes; |
229 | int ret; |
230 | |
231 | unicode = PyUnicode_FromWideChar(command, -1); |
232 | if (unicode == NULL) { |
233 | goto error; |
234 | } |
235 | |
236 | if (PySys_Audit("cpython.run_command" , "O" , unicode) < 0) { |
237 | return pymain_exit_err_print(); |
238 | } |
239 | |
240 | bytes = PyUnicode_AsUTF8String(unicode); |
241 | Py_DECREF(unicode); |
242 | if (bytes == NULL) { |
243 | goto error; |
244 | } |
245 | |
246 | PyCompilerFlags cf = _PyCompilerFlags_INIT; |
247 | cf.cf_flags |= PyCF_IGNORE_COOKIE; |
248 | ret = PyRun_SimpleStringFlags(PyBytes_AsString(bytes), &cf); |
249 | Py_DECREF(bytes); |
250 | return (ret != 0); |
251 | |
252 | error: |
253 | PySys_WriteStderr("Unable to decode the command from the command line:\n" ); |
254 | return pymain_exit_err_print(); |
255 | } |
256 | |
257 | |
258 | static int |
259 | pymain_run_module(const wchar_t *modname, int set_argv0) |
260 | { |
261 | PyObject *module, *runpy, *runmodule, *runargs, *result; |
262 | if (PySys_Audit("cpython.run_module" , "u" , modname) < 0) { |
263 | return pymain_exit_err_print(); |
264 | } |
265 | runpy = PyImport_ImportModule("runpy" ); |
266 | if (runpy == NULL) { |
267 | fprintf(stderr, "Could not import runpy module\n" ); |
268 | return pymain_exit_err_print(); |
269 | } |
270 | runmodule = PyObject_GetAttrString(runpy, "_run_module_as_main" ); |
271 | if (runmodule == NULL) { |
272 | fprintf(stderr, "Could not access runpy._run_module_as_main\n" ); |
273 | Py_DECREF(runpy); |
274 | return pymain_exit_err_print(); |
275 | } |
276 | module = PyUnicode_FromWideChar(modname, wcslen(modname)); |
277 | if (module == NULL) { |
278 | fprintf(stderr, "Could not convert module name to unicode\n" ); |
279 | Py_DECREF(runpy); |
280 | Py_DECREF(runmodule); |
281 | return pymain_exit_err_print(); |
282 | } |
283 | runargs = PyTuple_Pack(2, module, set_argv0 ? Py_True : Py_False); |
284 | if (runargs == NULL) { |
285 | fprintf(stderr, |
286 | "Could not create arguments for runpy._run_module_as_main\n" ); |
287 | Py_DECREF(runpy); |
288 | Py_DECREF(runmodule); |
289 | Py_DECREF(module); |
290 | return pymain_exit_err_print(); |
291 | } |
292 | _Py_UnhandledKeyboardInterrupt = 0; |
293 | result = PyObject_Call(runmodule, runargs, NULL); |
294 | if (!result && PyErr_Occurred() == PyExc_KeyboardInterrupt) { |
295 | _Py_UnhandledKeyboardInterrupt = 1; |
296 | } |
297 | Py_DECREF(runpy); |
298 | Py_DECREF(runmodule); |
299 | Py_DECREF(module); |
300 | Py_DECREF(runargs); |
301 | if (result == NULL) { |
302 | return pymain_exit_err_print(); |
303 | } |
304 | Py_DECREF(result); |
305 | return 0; |
306 | } |
307 | |
308 | |
309 | static int |
310 | pymain_run_file_obj(PyObject *program_name, PyObject *filename, |
311 | int skip_source_first_line) |
312 | { |
313 | if (PySys_Audit("cpython.run_file" , "O" , filename) < 0) { |
314 | return pymain_exit_err_print(); |
315 | } |
316 | |
317 | FILE *fp = _Py_fopen_obj(filename, "rb" ); |
318 | if (fp == NULL) { |
319 | // Ignore the OSError |
320 | PyErr_Clear(); |
321 | PySys_FormatStderr("%S: can't open file %R: [Errno %d] %s\n" , |
322 | program_name, filename, errno, strerror(errno)); |
323 | return 2; |
324 | } |
325 | |
326 | if (skip_source_first_line) { |
327 | int ch; |
328 | /* Push back first newline so line numbers remain the same */ |
329 | while ((ch = getc(fp)) != EOF) { |
330 | if (ch == '\n') { |
331 | (void)ungetc(ch, fp); |
332 | break; |
333 | } |
334 | } |
335 | } |
336 | |
337 | struct _Py_stat_struct sb; |
338 | if (_Py_fstat_noraise(fileno(fp), &sb) == 0 && S_ISDIR(sb.st_mode)) { |
339 | PySys_FormatStderr("%S: %R is a directory, cannot continue\n" , |
340 | program_name, filename); |
341 | fclose(fp); |
342 | return 1; |
343 | } |
344 | |
345 | // Call pending calls like signal handlers (SIGINT) |
346 | if (Py_MakePendingCalls() == -1) { |
347 | fclose(fp); |
348 | return pymain_exit_err_print(); |
349 | } |
350 | |
351 | /* PyRun_AnyFileExFlags(closeit=1) calls fclose(fp) before running code */ |
352 | PyCompilerFlags cf = _PyCompilerFlags_INIT; |
353 | int run = _PyRun_AnyFileObject(fp, filename, 1, &cf); |
354 | return (run != 0); |
355 | } |
356 | |
357 | static int |
358 | pymain_run_file(const PyConfig *config) |
359 | { |
360 | PyObject *filename = PyUnicode_FromWideChar(config->run_filename, -1); |
361 | if (filename == NULL) { |
362 | PyErr_Print(); |
363 | return -1; |
364 | } |
365 | PyObject *program_name = PyUnicode_FromWideChar(config->program_name, -1); |
366 | if (program_name == NULL) { |
367 | Py_DECREF(filename); |
368 | PyErr_Print(); |
369 | return -1; |
370 | } |
371 | |
372 | int res = pymain_run_file_obj(program_name, filename, |
373 | config->skip_source_first_line); |
374 | Py_DECREF(filename); |
375 | Py_DECREF(program_name); |
376 | return res; |
377 | } |
378 | |
379 | |
380 | static int |
381 | pymain_run_startup(PyConfig *config, int *exitcode) |
382 | { |
383 | int ret; |
384 | if (!config->use_environment) { |
385 | return 0; |
386 | } |
387 | PyObject *startup = NULL; |
388 | #ifdef MS_WINDOWS |
389 | const wchar_t *env = _wgetenv(L"PYTHONSTARTUP" ); |
390 | if (env == NULL || env[0] == L'\0') { |
391 | return 0; |
392 | } |
393 | startup = PyUnicode_FromWideChar(env, wcslen(env)); |
394 | if (startup == NULL) { |
395 | goto error; |
396 | } |
397 | #else |
398 | const char *env = _Py_GetEnv(config->use_environment, "PYTHONSTARTUP" ); |
399 | if (env == NULL) { |
400 | return 0; |
401 | } |
402 | startup = PyUnicode_DecodeFSDefault(env); |
403 | if (startup == NULL) { |
404 | goto error; |
405 | } |
406 | #endif |
407 | if (PySys_Audit("cpython.run_startup" , "O" , startup) < 0) { |
408 | goto error; |
409 | } |
410 | |
411 | FILE *fp = _Py_fopen_obj(startup, "r" ); |
412 | if (fp == NULL) { |
413 | int save_errno = errno; |
414 | PyErr_Clear(); |
415 | PySys_WriteStderr("Could not open PYTHONSTARTUP\n" ); |
416 | |
417 | errno = save_errno; |
418 | PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, startup, NULL); |
419 | goto error; |
420 | } |
421 | |
422 | PyCompilerFlags cf = _PyCompilerFlags_INIT; |
423 | (void) _PyRun_SimpleFileObject(fp, startup, 0, &cf); |
424 | PyErr_Clear(); |
425 | fclose(fp); |
426 | ret = 0; |
427 | |
428 | done: |
429 | Py_XDECREF(startup); |
430 | return ret; |
431 | |
432 | error: |
433 | ret = pymain_err_print(exitcode); |
434 | goto done; |
435 | } |
436 | |
437 | |
438 | /* Write an exitcode into *exitcode and return 1 if we have to exit Python. |
439 | Return 0 otherwise. */ |
440 | static int |
441 | pymain_run_interactive_hook(int *exitcode) |
442 | { |
443 | PyObject *sys, *hook, *result; |
444 | sys = PyImport_ImportModule("sys" ); |
445 | if (sys == NULL) { |
446 | goto error; |
447 | } |
448 | |
449 | hook = PyObject_GetAttrString(sys, "__interactivehook__" ); |
450 | Py_DECREF(sys); |
451 | if (hook == NULL) { |
452 | PyErr_Clear(); |
453 | return 0; |
454 | } |
455 | |
456 | if (PySys_Audit("cpython.run_interactivehook" , "O" , hook) < 0) { |
457 | goto error; |
458 | } |
459 | |
460 | result = _PyObject_CallNoArg(hook); |
461 | Py_DECREF(hook); |
462 | if (result == NULL) { |
463 | goto error; |
464 | } |
465 | Py_DECREF(result); |
466 | |
467 | return 0; |
468 | |
469 | error: |
470 | PySys_WriteStderr("Failed calling sys.__interactivehook__\n" ); |
471 | return pymain_err_print(exitcode); |
472 | } |
473 | |
474 | |
475 | static int |
476 | pymain_run_stdin(PyConfig *config) |
477 | { |
478 | if (stdin_is_interactive(config)) { |
479 | config->inspect = 0; |
480 | Py_InspectFlag = 0; /* do exit on SystemExit */ |
481 | |
482 | int exitcode; |
483 | if (pymain_run_startup(config, &exitcode)) { |
484 | return exitcode; |
485 | } |
486 | |
487 | if (pymain_run_interactive_hook(&exitcode)) { |
488 | return exitcode; |
489 | } |
490 | } |
491 | |
492 | /* call pending calls like signal handlers (SIGINT) */ |
493 | if (Py_MakePendingCalls() == -1) { |
494 | return pymain_exit_err_print(); |
495 | } |
496 | |
497 | if (PySys_Audit("cpython.run_stdin" , NULL) < 0) { |
498 | return pymain_exit_err_print(); |
499 | } |
500 | |
501 | PyCompilerFlags cf = _PyCompilerFlags_INIT; |
502 | int run = PyRun_AnyFileExFlags(stdin, "<stdin>" , 0, &cf); |
503 | return (run != 0); |
504 | } |
505 | |
506 | |
507 | static void |
508 | pymain_repl(PyConfig *config, int *exitcode) |
509 | { |
510 | /* Check this environment variable at the end, to give programs the |
511 | opportunity to set it from Python. */ |
512 | if (!config->inspect && _Py_GetEnv(config->use_environment, "PYTHONINSPECT" )) { |
513 | config->inspect = 1; |
514 | Py_InspectFlag = 1; |
515 | } |
516 | |
517 | if (!(config->inspect && stdin_is_interactive(config) && config_run_code(config))) { |
518 | return; |
519 | } |
520 | |
521 | config->inspect = 0; |
522 | Py_InspectFlag = 0; |
523 | if (pymain_run_interactive_hook(exitcode)) { |
524 | return; |
525 | } |
526 | |
527 | PyCompilerFlags cf = _PyCompilerFlags_INIT; |
528 | int res = PyRun_AnyFileFlags(stdin, "<stdin>" , &cf); |
529 | *exitcode = (res != 0); |
530 | } |
531 | |
532 | |
533 | static void |
534 | pymain_run_python(int *exitcode) |
535 | { |
536 | PyInterpreterState *interp = _PyInterpreterState_GET(); |
537 | /* pymain_run_stdin() modify the config */ |
538 | PyConfig *config = (PyConfig*)_PyInterpreterState_GetConfig(interp); |
539 | |
540 | PyObject *main_importer_path = NULL; |
541 | if (config->run_filename != NULL) { |
542 | /* If filename is a package (ex: directory or ZIP file) which contains |
543 | __main__.py, main_importer_path is set to filename and will be |
544 | prepended to sys.path. |
545 | |
546 | Otherwise, main_importer_path is left unchanged. */ |
547 | if (pymain_get_importer(config->run_filename, &main_importer_path, |
548 | exitcode)) { |
549 | return; |
550 | } |
551 | } |
552 | |
553 | if (main_importer_path != NULL) { |
554 | if (pymain_sys_path_add_path0(interp, main_importer_path) < 0) { |
555 | goto error; |
556 | } |
557 | } |
558 | else if (!config->isolated) { |
559 | PyObject *path0 = NULL; |
560 | int res = _PyPathConfig_ComputeSysPath0(&config->argv, &path0); |
561 | if (res < 0) { |
562 | goto error; |
563 | } |
564 | |
565 | if (res > 0) { |
566 | if (pymain_sys_path_add_path0(interp, path0) < 0) { |
567 | Py_DECREF(path0); |
568 | goto error; |
569 | } |
570 | Py_DECREF(path0); |
571 | } |
572 | } |
573 | |
574 | pymain_header(config); |
575 | pymain_import_readline(config); |
576 | |
577 | if (config->run_command) { |
578 | *exitcode = pymain_run_command(config->run_command); |
579 | } |
580 | else if (config->run_module) { |
581 | *exitcode = pymain_run_module(config->run_module, 1); |
582 | } |
583 | else if (main_importer_path != NULL) { |
584 | *exitcode = pymain_run_module(L"__main__" , 0); |
585 | } |
586 | else if (config->run_filename != NULL) { |
587 | *exitcode = pymain_run_file(config); |
588 | } |
589 | else { |
590 | *exitcode = pymain_run_stdin(config); |
591 | } |
592 | |
593 | pymain_repl(config, exitcode); |
594 | goto done; |
595 | |
596 | error: |
597 | *exitcode = pymain_exit_err_print(); |
598 | |
599 | done: |
600 | Py_XDECREF(main_importer_path); |
601 | } |
602 | |
603 | |
604 | /* --- pymain_main() ---------------------------------------------- */ |
605 | |
606 | static void |
607 | pymain_free(void) |
608 | { |
609 | _PyImport_Fini2(); |
610 | |
611 | /* Free global variables which cannot be freed in Py_Finalize(): |
612 | configuration options set before Py_Initialize() which should |
613 | remain valid after Py_Finalize(), since |
614 | Py_Initialize()-Py_Finalize() can be called multiple times. */ |
615 | _PyPathConfig_ClearGlobal(); |
616 | _Py_ClearStandardStreamEncoding(); |
617 | _Py_ClearArgcArgv(); |
618 | _PyRuntime_Finalize(); |
619 | } |
620 | |
621 | |
622 | static int |
623 | exit_sigint(void) |
624 | { |
625 | /* bpo-1054041: We need to exit via the |
626 | * SIG_DFL handler for SIGINT if KeyboardInterrupt went unhandled. |
627 | * If we don't, a calling process such as a shell may not know |
628 | * about the user's ^C. https://www.cons.org/cracauer/sigint.html */ |
629 | #if defined(HAVE_GETPID) && !defined(MS_WINDOWS) |
630 | if (PyOS_setsig(SIGINT, SIG_DFL) == SIG_ERR) { |
631 | perror("signal" ); /* Impossible in normal environments. */ |
632 | } else { |
633 | kill(getpid(), SIGINT); |
634 | } |
635 | /* If setting SIG_DFL failed, or kill failed to terminate us, |
636 | * there isn't much else we can do aside from an error code. */ |
637 | #endif /* HAVE_GETPID && !MS_WINDOWS */ |
638 | #ifdef MS_WINDOWS |
639 | /* cmd.exe detects this, prints ^C, and offers to terminate. */ |
640 | /* https://msdn.microsoft.com/en-us/library/cc704588.aspx */ |
641 | return STATUS_CONTROL_C_EXIT; |
642 | #else |
643 | return SIGINT + 128; |
644 | #endif /* !MS_WINDOWS */ |
645 | } |
646 | |
647 | |
648 | static void _Py_NO_RETURN |
649 | pymain_exit_error(PyStatus status) |
650 | { |
651 | if (_PyStatus_IS_EXIT(status)) { |
652 | /* If it's an error rather than a regular exit, leave Python runtime |
653 | alive: Py_ExitStatusException() uses the current exception and use |
654 | sys.stdout in this case. */ |
655 | pymain_free(); |
656 | } |
657 | Py_ExitStatusException(status); |
658 | } |
659 | |
660 | |
661 | int |
662 | Py_RunMain(void) |
663 | { |
664 | int exitcode = 0; |
665 | |
666 | pymain_run_python(&exitcode); |
667 | |
668 | if (Py_FinalizeEx() < 0) { |
669 | /* Value unlikely to be confused with a non-error exit status or |
670 | other special meaning */ |
671 | exitcode = 120; |
672 | } |
673 | |
674 | pymain_free(); |
675 | |
676 | if (_Py_UnhandledKeyboardInterrupt) { |
677 | exitcode = exit_sigint(); |
678 | } |
679 | |
680 | return exitcode; |
681 | } |
682 | |
683 | |
684 | static int |
685 | pymain_main(_PyArgv *args) |
686 | { |
687 | PyStatus status = pymain_init(args); |
688 | if (_PyStatus_IS_EXIT(status)) { |
689 | pymain_free(); |
690 | return status.exitcode; |
691 | } |
692 | if (_PyStatus_EXCEPTION(status)) { |
693 | pymain_exit_error(status); |
694 | } |
695 | |
696 | return Py_RunMain(); |
697 | } |
698 | |
699 | |
700 | int |
701 | Py_Main(int argc, wchar_t **argv) |
702 | { |
703 | _PyArgv args = { |
704 | .argc = argc, |
705 | .use_bytes_argv = 0, |
706 | .bytes_argv = NULL, |
707 | .wchar_argv = argv}; |
708 | return pymain_main(&args); |
709 | } |
710 | |
711 | |
712 | int |
713 | Py_BytesMain(int argc, char **argv) |
714 | { |
715 | _PyArgv args = { |
716 | .argc = argc, |
717 | .use_bytes_argv = 1, |
718 | .bytes_argv = argv, |
719 | .wchar_argv = NULL}; |
720 | return pymain_main(&args); |
721 | } |
722 | |
723 | #ifdef __cplusplus |
724 | } |
725 | #endif |
726 | |