diff options
author | Victor Stinner <vstinner@redhat.com> | 2019-03-20 03:25:38 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-20 03:25:38 (GMT) |
commit | fa1537684869186da7938e4330361bf02363bac8 (patch) | |
tree | 919f5d59429afe03b6bbfd24b0f289018a8a254e | |
parent | abbdd1fc5c2017683da8d2ed3e8843e8c159bc8c (diff) | |
download | cpython-fa1537684869186da7938e4330361bf02363bac8.zip cpython-fa1537684869186da7938e4330361bf02363bac8.tar.gz cpython-fa1537684869186da7938e4330361bf02363bac8.tar.bz2 |
bpo-36301: Add _PyPreCmdline internal API (GH-12458)
_PyCoreConfig_ReadFromArgv() now reuses the code parsing command line
options from preconfig.c.
-rw-r--r-- | Include/internal/pycore_coreconfig.h | 24 | ||||
-rw-r--r-- | Python/coreconfig.c | 67 | ||||
-rw-r--r-- | Python/preconfig.c | 55 |
3 files changed, 99 insertions, 47 deletions
diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h index 8c5a072..29261df 100644 --- a/Include/internal/pycore_coreconfig.h +++ b/Include/internal/pycore_coreconfig.h @@ -9,6 +9,30 @@ extern "C" { #endif +/* --- _PyPreCmdline ------------------------------------------------- */ + +typedef struct { + _PyWstrList argv; + _PyWstrList xoptions; /* "-X value" option */ + int use_environment; /* -E option */ + int isolated; /* -I option */ +} _PyPreCmdline; + +#define _PyPreCmdline_INIT \ + (_PyPreCmdline){ \ + .use_environment = -1, \ + .isolated = -1} +/* Note: _PyPreCmdline_INIT sets other fields to 0/NULL */ + +PyAPI_FUNC(void) _PyPreCmdline_Clear(_PyPreCmdline *cmdline); +PyAPI_FUNC(_PyInitError) _PyPreCmdline_Init(_PyPreCmdline *cmdline, + const _PyArgv *args); +PyAPI_FUNC(_PyInitError) _PyPreCmdline_Read(_PyPreCmdline *cmdline); +PyAPI_FUNC(void) _PyPreCmdline_SetPreConfig( + const _PyPreCmdline *cmdline, + _PyPreConfig *config); + + /* --- _PyWstrList ------------------------------------------------ */ #ifndef NDEBUG diff --git a/Python/coreconfig.c b/Python/coreconfig.c index e1d883c..1881f00 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1658,7 +1658,7 @@ fail: /* --- _PyCmdline ------------------------------------------------- */ typedef struct { - _PyWstrList argv; + _PyPreCmdline precmdline; _PyWstrList warnoptions; /* Command line -W options */ _PyWstrList env_warnoptions; /* PYTHONWARNINGS environment variables */ int print_help; /* -h, -? options */ @@ -1669,9 +1669,9 @@ typedef struct { static void cmdline_clear(_PyCmdline *cmdline) { + _PyPreCmdline_Clear(&cmdline->precmdline); _PyWstrList_Clear(&cmdline->warnoptions); _PyWstrList_Clear(&cmdline->env_warnoptions); - _PyWstrList_Clear(&cmdline->argv); } @@ -1682,10 +1682,12 @@ static _PyInitError config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, int *need_usage) { + const _PyWstrList *argv = &cmdline->precmdline.argv; + _PyOS_ResetGetOpt(); do { int longindex = -1; - int c = _PyOS_GetOpt(cmdline->argv.length, cmdline->argv.items, &longindex); + int c = _PyOS_GetOpt(argv->length, argv->items, &longindex); if (c == EOF) { break; } @@ -1754,6 +1756,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, case 'E': case 'I': + case 'X': /* option handled by _PyPreConfig_ReadFromArgv() */ break; @@ -1806,12 +1809,6 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, } break; - case 'X': - if (_PyWstrList_Append(&config->xoptions, _PyOS_optarg) < 0) { - return _Py_INIT_NO_MEMORY(); - } - break; - case 'q': config->quiet++; break; @@ -1830,11 +1827,11 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, } while (1); if (config->run_command == NULL && config->run_module == NULL - && _PyOS_optind < cmdline->argv.length - && wcscmp(cmdline->argv.items[_PyOS_optind], L"-") != 0 + && _PyOS_optind < argv->length + && wcscmp(argv->items[_PyOS_optind], L"-") != 0 && config->run_filename == NULL) { - config->run_filename = _PyMem_RawWcsdup(cmdline->argv.items[_PyOS_optind]); + config->run_filename = _PyMem_RawWcsdup(argv->items[_PyOS_optind]); if (config->run_filename == NULL) { return _Py_INIT_NO_MEMORY(); } @@ -1892,9 +1889,10 @@ cmdline_init_env_warnoptions(_PyCmdline *cmdline, const _PyCoreConfig *config) static _PyInitError config_init_program(_PyCoreConfig *config, const _PyCmdline *cmdline) { + const _PyWstrList *argv = &cmdline->precmdline.argv; wchar_t *program; - if (cmdline->argv.length >= 1) { - program = cmdline->argv.items[0]; + if (argv->length >= 1) { + program = argv->items[0]; } else { program = L""; @@ -1965,24 +1963,25 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline) static _PyInitError config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline) { - _PyWstrList wargv = _PyWstrList_INIT; + const _PyWstrList *cmdline_argv = &cmdline->precmdline.argv; + _PyWstrList config_argv = _PyWstrList_INIT; /* Copy argv to be able to modify it (to force -c/-m) */ - if (cmdline->argv.length <= _PyOS_optind) { + if (cmdline_argv->length <= _PyOS_optind) { /* Ensure at least one (empty) argument is seen */ - if (_PyWstrList_Append(&wargv, L"") < 0) { + if (_PyWstrList_Append(&config_argv, L"") < 0) { return _Py_INIT_NO_MEMORY(); } } else { _PyWstrList slice; - slice.length = cmdline->argv.length - _PyOS_optind; - slice.items = &cmdline->argv.items[_PyOS_optind]; - if (_PyWstrList_Copy(&wargv, &slice) < 0) { + slice.length = cmdline_argv->length - _PyOS_optind; + slice.items = &cmdline_argv->items[_PyOS_optind]; + if (_PyWstrList_Copy(&config_argv, &slice) < 0) { return _Py_INIT_NO_MEMORY(); } } - assert(wargv.length >= 1); + assert(config_argv.length >= 1); wchar_t *arg0 = NULL; if (config->run_command != NULL) { @@ -1996,16 +1995,16 @@ config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline) if (arg0 != NULL) { arg0 = _PyMem_RawWcsdup(arg0); if (arg0 == NULL) { - _PyWstrList_Clear(&wargv); + _PyWstrList_Clear(&config_argv); return _Py_INIT_NO_MEMORY(); } - PyMem_RawFree(wargv.items[0]); - wargv.items[0] = arg0; + PyMem_RawFree(config_argv.items[0]); + config_argv.items[0] = arg0; } _PyWstrList_Clear(&config->argv); - config->argv = wargv; + config->argv = config_argv; return _Py_INIT_OK(); } @@ -2046,6 +2045,16 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, } } + err = _PyPreCmdline_Read(&cmdline->precmdline); + if (_Py_INIT_FAILED(err)) { + return err; + } + + _PyPreCmdline_SetPreConfig(&cmdline->precmdline, &config->preconfig); + if (_PyWstrList_Extend(&config->xoptions, &cmdline->precmdline.xoptions) < 0) { + return _Py_INIT_NO_MEMORY(); + } + err = config_parse_cmdline(config, cmdline, &need_usage); if (_Py_INIT_FAILED(err)) { return err; @@ -2089,7 +2098,8 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, return err; } - if (_Py_SetArgcArgv(cmdline->argv.length, cmdline->argv.items) < 0) { + const _PyWstrList *argv = &cmdline->precmdline.argv; + if (_Py_SetArgcArgv(argv->length, argv->items) < 0) { return _Py_INIT_NO_MEMORY(); } return _Py_INIT_OK(); @@ -2107,10 +2117,9 @@ _PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args, { _PyInitError err; - _PyCmdline cmdline; - memset(&cmdline, 0, sizeof(cmdline)); + _PyCmdline cmdline = {.precmdline = _PyPreCmdline_INIT}; - err = _PyArgv_AsWstrList(args, &cmdline.argv); + err = _PyPreCmdline_Init(&cmdline.precmdline, args); if (_Py_INIT_FAILED(err)) { goto done; } diff --git a/Python/preconfig.c b/Python/preconfig.c index a149ea5..d856c12 100644 --- a/Python/preconfig.c +++ b/Python/preconfig.c @@ -102,20 +102,21 @@ _PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list) /* --- _PyPreCmdline ------------------------------------------------- */ -typedef struct { - _PyWstrList argv; - _PyWstrList xoptions; /* -X options */ -} _PyPreCmdline; - - -static void -precmdline_clear(_PyPreCmdline *cmdline) +void +_PyPreCmdline_Clear(_PyPreCmdline *cmdline) { _PyWstrList_Clear(&cmdline->argv); _PyWstrList_Clear(&cmdline->xoptions); } +_PyInitError +_PyPreCmdline_Init(_PyPreCmdline *cmdline, const _PyArgv *args) +{ + return _PyArgv_AsWstrList(args, &cmdline->argv); +} + + /* --- _PyPreConfig ----------------------------------------------- */ void @@ -520,6 +521,21 @@ _PyPreConfig_Read(_PyPreConfig *config) } +void +_PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config) +{ +#define COPY_ATTR(ATTR) \ + if (cmdline->ATTR != -1) { \ + config->ATTR = cmdline->ATTR; \ + } + + COPY_ATTR(use_environment); + COPY_ATTR(isolated); + +#undef COPY_ATTR +} + + int _PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict) { @@ -567,16 +583,18 @@ fail: /* Parse the command line arguments */ -static _PyInitError -preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline) +_PyInitError +_PyPreCmdline_Read(_PyPreCmdline *cmdline) { + _PyWstrList *argv = &cmdline->argv; + _PyOS_ResetGetOpt(); /* Don't log parsing errors into stderr here: _PyCoreConfig_ReadFromArgv() is responsible for that */ _PyOS_opterr = 0; do { int longindex = -1; - int c = _PyOS_GetOpt(cmdline->argv.length, cmdline->argv.items, &longindex); + int c = _PyOS_GetOpt(argv->length, argv->items, &longindex); if (c == EOF || c == 'c' || c == 'm') { break; @@ -584,11 +602,11 @@ preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline) switch (c) { case 'E': - config->use_environment = 0; + cmdline->use_environment = 0; break; case 'I': - config->isolated++; + cmdline->isolated = 1; break; case 'X': @@ -615,19 +633,20 @@ preconfig_from_argv(_PyPreConfig *config, const _PyArgv *args) { _PyInitError err; - _PyPreCmdline cmdline; - memset(&cmdline, 0, sizeof(cmdline)); + _PyPreCmdline cmdline = _PyPreCmdline_INIT; - err = _PyArgv_AsWstrList(args, &cmdline.argv); + err = _PyPreCmdline_Init(&cmdline, args); if (_Py_INIT_FAILED(err)) { goto done; } - err = preconfig_parse_cmdline(config, &cmdline); + err = _PyPreCmdline_Read(&cmdline); if (_Py_INIT_FAILED(err)) { goto done; } + _PyPreCmdline_SetPreConfig(&cmdline, config); + err = preconfig_read(config, &cmdline); if (_Py_INIT_FAILED(err)) { goto done; @@ -635,7 +654,7 @@ preconfig_from_argv(_PyPreConfig *config, const _PyArgv *args) err = _Py_INIT_OK(); done: - precmdline_clear(&cmdline); + _PyPreCmdline_Clear(&cmdline); return err; } |