bpo-36301: Add _PyWstrList structure (GH-12343)

Replace messy _Py_wstrlist_xxx() functions with a new clean
_PyWstrList structure and new _PyWstrList_xxx() functions.

Changes:

* Add _PyCoreConfig.use_module_search_paths to decide if
  _PyCoreConfig.module_search_paths should be computed or not, to
  support empty search path list.
* _PyWstrList_Clear() sets length to 0 and items to NULL, whereas
  _Py_wstrlist_clear() only freed memory.
* _PyWstrList_Append() returns an int, whereas _Py_wstrlist_append()
  returned _PyInitError.
* _PyWstrList uses Py_ssize_t for the length, instead of int.
* Replace (int, wchar_t**) with _PyWstrList in:

  * _PyPreConfig
  * _PyCoreConfig
  * _PyPreCmdline
  * _PyCmdline

* Replace "int orig_argv; wchar_t **orig_argv;"
  with "_PyWstrList orig_argv".
* _PyCmdline and _PyPreCmdline now also copy wchar_argv.
* Rename _PyArgv_Decode() to _PyArgv_AsWstrList().
* PySys_SetArgvEx() now pass the fixed (argc, argv) to
  _PyPathConfig_ComputeArgv0() (don't pass negative argc or NULL
  argv).
* _PyOS_GetOpt() uses Py_ssize_t
This commit is contained in:
Victor Stinner 2019-03-15 15:08:05 +01:00 committed by GitHub
parent 86082c22d2
commit 74f6568bbd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 303 additions and 345 deletions

View file

@ -64,33 +64,38 @@ _Py_SetFileSystemEncoding(const char *encoding, const char *errors)
/* --- _PyArgv ---------------------------------------------------- */
_PyInitError
_PyArgv_Decode(const _PyArgv *args, wchar_t*** argv_p)
_PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list)
{
wchar_t** argv;
_PyWstrList wargv = _PyWstrList_INIT;
if (args->use_bytes_argv) {
/* +1 for a the NULL terminator */
size_t size = sizeof(wchar_t*) * (args->argc + 1);
argv = (wchar_t **)PyMem_RawMalloc(size);
if (argv == NULL) {
size_t size = sizeof(wchar_t*) * args->argc;
wargv.items = (wchar_t **)PyMem_RawMalloc(size);
if (wargv.items == NULL) {
return _Py_INIT_NO_MEMORY();
}
for (int i = 0; i < args->argc; i++) {
for (Py_ssize_t i = 0; i < args->argc; i++) {
size_t len;
wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
if (arg == NULL) {
_Py_wstrlist_clear(i, argv);
_PyWstrList_Clear(&wargv);
return DECODE_LOCALE_ERR("command line arguments",
(Py_ssize_t)len);
}
argv[i] = arg;
wargv.items[i] = arg;
wargv.length++;
}
argv[args->argc] = NULL;
_PyWstrList_Clear(list);
*list = wargv;
}
else {
argv = args->wchar_argv;
wargv.length = args->argc;
wargv.items = args->wchar_argv;
if (_PyWstrList_Copy(list, &wargv) < 0) {
return _Py_INIT_NO_MEMORY();
}
}
*argv_p = argv;
return _Py_INIT_OK();
}
@ -98,25 +103,16 @@ _PyArgv_Decode(const _PyArgv *args, wchar_t*** argv_p)
/* --- _PyPreCmdline ------------------------------------------------- */
typedef struct {
const _PyArgv *args;
int argc;
wchar_t **argv;
int nxoption; /* Number of -X options */
wchar_t **xoptions; /* -X options */
_PyWstrList argv;
_PyWstrList xoptions; /* -X options */
} _PyPreCmdline;
static void
precmdline_clear(_PyPreCmdline *cmdline)
{
if (cmdline->args->use_bytes_argv && cmdline->argv != NULL) {
_Py_wstrlist_clear(cmdline->args->argc, cmdline->argv);
}
cmdline->argv = NULL;
_Py_wstrlist_clear(cmdline->nxoption, cmdline->xoptions);
cmdline->nxoption = 0;
cmdline->xoptions = NULL;
_PyWstrList_Clear(&cmdline->argv);
_PyWstrList_Clear(&cmdline->xoptions);
}
@ -267,10 +263,10 @@ _Py_get_env_flag(_PyPreConfig *config, int *flag, const char *name)
const wchar_t*
_Py_get_xoption(int nxoption, wchar_t * const *xoptions, const wchar_t *name)
_Py_get_xoption(const _PyWstrList *xoptions, const wchar_t *name)
{
for (int i=0; i < nxoption; i++) {
const wchar_t *option = xoptions[i];
for (Py_ssize_t i=0; i < xoptions->length; i++) {
const wchar_t *option = xoptions->items[i];
size_t len;
wchar_t *sep = wcschr(option, L'=');
if (sep != NULL) {
@ -292,7 +288,7 @@ preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
{
const wchar_t *xopt;
if (cmdline) {
xopt = _Py_get_xoption(cmdline->nxoption, cmdline->xoptions, L"utf8");
xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
}
else {
xopt = NULL;
@ -435,7 +431,7 @@ preconfig_read(_PyPreConfig *config, const _PyPreCmdline *cmdline)
}
/* dev_mode */
if ((cmdline && _Py_get_xoption(cmdline->nxoption, cmdline->xoptions, L"dev"))
if ((cmdline && _Py_get_xoption(&cmdline->xoptions, L"dev"))
|| _PyPreConfig_GetEnv(config, "PYTHONDEVMODE"))
{
config->dev_mode = 1;
@ -579,7 +575,7 @@ preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline)
_PyOS_opterr = 0;
do {
int longindex = -1;
int c = _PyOS_GetOpt(cmdline->args->argc, cmdline->argv, &longindex);
int c = _PyOS_GetOpt(cmdline->argv.length, cmdline->argv.items, &longindex);
if (c == EOF || c == 'c' || c == 'm') {
break;
@ -596,12 +592,8 @@ preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline)
case 'X':
{
_PyInitError err;
err = _Py_wstrlist_append(&cmdline->nxoption,
&cmdline->xoptions,
_PyOS_optarg);
if (_Py_INIT_FAILED(err)) {
return err;
if (_PyWstrList_Append(&cmdline->xoptions, _PyOS_optarg) < 0) {
return _Py_INIT_NO_MEMORY();
}
break;
}
@ -624,9 +616,8 @@ preconfig_from_argv(_PyPreConfig *config, const _PyArgv *args)
_PyPreCmdline cmdline;
memset(&cmdline, 0, sizeof(cmdline));
cmdline.args = args;
err = _PyArgv_Decode(cmdline.args, &cmdline.argv);
err = _PyArgv_AsWstrList(args, &cmdline.argv);
if (_Py_INIT_FAILED(err)) {
goto done;
}