Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Include/internal/pycore_coreconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
67 changes: 38 additions & 29 deletions Python/coreconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -1658,7 +1658,7 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config)
/* --- _PyCmdline ------------------------------------------------- */

typedef struct {
_PyWstrList argv;
_PyPreCmdline precmdline;
_PyWstrList warnoptions; /* Command line -W options */
_PyWstrList env_warnoptions; /* PYTHONWARNINGS environment variables */
int print_help; /* -h, -? options */
Expand All @@ -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);
}


Expand All @@ -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;
}
Expand Down Expand Up @@ -1754,6 +1756,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,

case 'E':
case 'I':
case 'X':
/* option handled by _PyPreConfig_ReadFromArgv() */
break;

Expand Down Expand Up @@ -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;
Expand All @@ -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();
}
Expand Down Expand Up @@ -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"";
Expand Down Expand Up @@ -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) {
Expand All @@ -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();
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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;
}
Expand Down
55 changes: 37 additions & 18 deletions Python/preconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -567,28 +583,30 @@ _PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict)


/* 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;
}

switch (c) {
case 'E':
config->use_environment = 0;
cmdline->use_environment = 0;
break;

case 'I':
config->isolated++;
cmdline->isolated = 1;
break;

case 'X':
Expand All @@ -615,27 +633,28 @@ 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;
}
err = _Py_INIT_OK();

done:
precmdline_clear(&cmdline);
_PyPreCmdline_Clear(&cmdline);
return err;
}

Expand Down