]> granicus.if.org Git - python/commitdiff
bpo-36301: Add _PyWstrList structure (GH-12343)
authorVictor Stinner <vstinner@redhat.com>
Fri, 15 Mar 2019 14:08:05 +0000 (15:08 +0100)
committerGitHub <noreply@github.com>
Fri, 15 Mar 2019 14:08:05 +0000 (15:08 +0100)
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

Include/cpython/coreconfig.h
Include/internal/pycore_coreconfig.h
Include/internal/pycore_getopt.h
Include/internal/pycore_pathconfig.h
Modules/main.c
Programs/_testembed.c
Python/coreconfig.c
Python/getopt.c
Python/pathconfig.c
Python/preconfig.c
Python/sysmodule.c

index 267357676bf0e0dbc8c6fcd64077ed5248c188ea..bd28c371ce52247fe0b759fb50a75b4cecee902b 100644 (file)
@@ -46,6 +46,18 @@ typedef struct {
 #define _Py_INIT_FAILED(err) \
     (err.msg != NULL || err.exitcode != -1)
 
+/* --- _PyWstrList ------------------------------------------------ */
+
+typedef struct {
+    /* If length is greater than zero, items must be non-NULL
+       and all items strings must be non-NULL */
+    Py_ssize_t length;
+    wchar_t **items;
+} _PyWstrList;
+
+#define _PyWstrList_INIT (_PyWstrList){.length = 0, .items = NULL}
+
+
 /* --- _PyPreConfig ----------------------------------------------- */
 
 typedef struct {
@@ -162,19 +174,12 @@ typedef struct {
     char *filesystem_encoding;
     char *filesystem_errors;
 
-    wchar_t *pycache_prefix; /* PYTHONPYCACHEPREFIX, -X pycache_prefix=PATH */
-
-    wchar_t *program_name;  /* Program name, see also Py_GetProgramName() */
-    int argc;               /* Number of command line arguments,
-                               -1 means unset */
-    wchar_t **argv;         /* Command line arguments */
-    wchar_t *program;       /* argv[0] or "" */
-
-    int nxoption;           /* Number of -X options */
-    wchar_t **xoptions;     /* -X options */
-
-    int nwarnoption;        /* Number of warnings options */
-    wchar_t **warnoptions;  /* Warnings options */
+    wchar_t *pycache_prefix;  /* PYTHONPYCACHEPREFIX, -X pycache_prefix=PATH */
+    wchar_t *program_name;    /* Program name, see also Py_GetProgramName() */
+    _PyWstrList argv;         /* Command line arguments */
+    wchar_t *program;         /* argv[0] or "" */
+    _PyWstrList xoptions;     /* Command line -X options */
+    _PyWstrList warnoptions;  /* Warnings options */
 
     /* Path configuration inputs */
     wchar_t *module_search_path_env; /* PYTHONPATH environment variable */
@@ -182,9 +187,11 @@ typedef struct {
                                see also Py_SetPythonHome(). */
 
     /* Path configuration outputs */
-    int nmodule_search_path;        /* Number of sys.path paths,
-                                       -1 means unset */
-    wchar_t **module_search_paths;  /* sys.path paths */
+    int use_module_search_paths;  /* If non-zero, use module_search_paths */
+    _PyWstrList module_search_paths;  /* sys.path paths. Computed if
+                                       use_module_search_paths is equal
+                                       to zero. */
+
     wchar_t *executable;    /* sys.executable */
     wchar_t *prefix;        /* sys.prefix */
     wchar_t *base_prefix;   /* sys.base_prefix */
@@ -366,8 +373,7 @@ typedef struct {
         .use_hash_seed = -1, \
         .faulthandler = -1, \
         .tracemalloc = -1, \
-        .argc = -1, \
-        .nmodule_search_path = -1, \
+        .use_module_search_paths = 0, \
         .site_import = -1, \
         .bytes_warning = -1, \
         .inspect = -1, \
index 153309de4ff6c894462d6d9c079582eb15fe3a4a..8c5a072e56771dfb5b36294204160d4a1272f97a 100644 (file)
@@ -8,39 +8,38 @@ extern "C" {
 #  error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN defined"
 #endif
 
-/* --- _Py_wstrlist ----------------------------------------------- */
-
-PyAPI_FUNC(void) _Py_wstrlist_clear(
-    int len,
-    wchar_t **list);
-PyAPI_FUNC(wchar_t**) _Py_wstrlist_copy(
-    int len,
-    wchar_t * const *list);
-PyAPI_FUNC(_PyInitError) _Py_wstrlist_append(
-    int *len,
-    wchar_t ***list,
-    const wchar_t *str);
-PyAPI_FUNC(PyObject*) _Py_wstrlist_as_pylist(
-    int len,
-    wchar_t **list);
+
+/* --- _PyWstrList ------------------------------------------------ */
+
+#ifndef NDEBUG
+PyAPI_FUNC(int) _PyWstrList_CheckConsistency(const _PyWstrList *list);
+#endif
+PyAPI_FUNC(void) _PyWstrList_Clear(_PyWstrList *list);
+PyAPI_FUNC(int) _PyWstrList_Copy(_PyWstrList *list,
+    const _PyWstrList *list2);
+PyAPI_FUNC(int) _PyWstrList_Append(_PyWstrList *list,
+    const wchar_t *item);
+PyAPI_FUNC(PyObject*) _PyWstrList_AsList(const _PyWstrList *list);
+
 
 /* --- _PyArgv ---------------------------------------------------- */
 
-PyAPI_FUNC(_PyInitError) _PyArgv_Decode(const _PyArgv *args,
-    wchar_t*** argv_p);
+PyAPI_FUNC(_PyInitError) _PyArgv_AsWstrList(const _PyArgv *args,
+    _PyWstrList *list);
+
 
 /* --- Py_GetArgcArgv() helpers ----------------------------------- */
 
 PyAPI_FUNC(void) _Py_ClearArgcArgv(void);
 
+
 /* --- _PyPreConfig ----------------------------------------------- */
 
 PyAPI_FUNC(int) _Py_str_to_int(
     const char *str,
     int *result);
 PyAPI_FUNC(const wchar_t*) _Py_get_xoption(
-    int nxoption,
-    wchar_t * const *xoptions,
+    const _PyWstrList *xoptions,
     const wchar_t *name);
 
 PyAPI_FUNC(void) _PyPreConfig_Clear(_PyPreConfig *config);
index 1d30f5bb99f831305e10b2fbcb400bbf22fee84b..0d1897c75a6403ca237aa20197b800161b4e08a6 100644 (file)
@@ -6,8 +6,8 @@
 #endif
 
 extern int _PyOS_opterr;
-extern int _PyOS_optind;
-extern wchar_t *_PyOS_optarg;
+extern Py_ssize_t _PyOS_optind;
+extern const wchar_t *_PyOS_optarg;
 
 extern void _PyOS_ResetGetOpt(void);
 
@@ -17,6 +17,6 @@ typedef struct {
     int val;
 } _PyOS_LongOption;
 
-extern int _PyOS_GetOpt(int argc, wchar_t **argv, int *longindex);
+extern int _PyOS_GetOpt(Py_ssize_t argc, wchar_t **argv, int *longindex);
 
 #endif /* !Py_INTERNAL_PYGETOPT_H */
index fb6b1d78b364237fac3850257eca77e6e5f0f3d7..d0938df541452c34418a2752301ccb4615ece90b 100644 (file)
@@ -44,7 +44,7 @@ PyAPI_FUNC(_PyInitError) _PyPathConfig_SetGlobal(
 PyAPI_FUNC(_PyInitError) _PyPathConfig_Calculate_impl(
     _PyPathConfig *config,
     const _PyCoreConfig *core_config);
-PyAPI_FUNC(PyObject*) _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv);
+PyAPI_FUNC(PyObject*) _PyPathConfig_ComputeArgv0(const _PyWstrList *argv);
 PyAPI_FUNC(int) _Py_FindEnvConfigValue(
     FILE *env_file,
     const wchar_t *key,
index ae99901f1d89be8743dc18ed36a22f3b3d40a7e1..5c7f7e45673a122c9a7237ad2cdbc4a4a9bf2fa0 100644 (file)
@@ -84,15 +84,15 @@ error:
 static PyObject*
 mainconfig_create_xoptions_dict(const _PyCoreConfig *config)
 {
-    int nxoption = config->nxoption;
-    wchar_t **xoptions = config->xoptions;
+    Py_ssize_t nxoption = config->xoptions.length;
+    wchar_t * const * xoptions = config->xoptions.items;
     PyObject *dict = PyDict_New();
     if (dict == NULL) {
         return NULL;
     }
 
-    for (int i=0; i < nxoption; i++) {
-        wchar_t *option = xoptions[i];
+    for (Py_ssize_t i=0; i < nxoption; i++) {
+        const wchar_t *option = xoptions[i];
         if (mainconfig_add_xoption(dict, option) < 0) {
             Py_DECREF(dict);
             return NULL;
@@ -243,22 +243,18 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *main_config,
             } \
         } \
     } while (0)
-#define COPY_WSTRLIST(ATTR, LEN, LIST) \
+#define COPY_WSTRLIST(ATTR, LIST) \
     do { \
         if (ATTR == NULL) { \
-            ATTR = _Py_wstrlist_as_pylist(LEN, LIST); \
+            ATTR = _PyWstrList_AsList(LIST); \
             if (ATTR == NULL) { \
                 return _Py_INIT_NO_MEMORY(); \
             } \
         } \
     } while (0)
 
-    COPY_WSTRLIST(main_config->warnoptions,
-                  config->nwarnoption, config->warnoptions);
-    if (config->argc >= 0) {
-        COPY_WSTRLIST(main_config->argv,
-                      config->argc, config->argv);
-    }
+    COPY_WSTRLIST(main_config->warnoptions, &config->warnoptions);
+    COPY_WSTRLIST(main_config->argv, &config->argv);
 
     if (config->_install_importlib) {
         COPY_WSTR(executable);
@@ -268,7 +264,7 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *main_config,
         COPY_WSTR(base_exec_prefix);
 
         COPY_WSTRLIST(main_config->module_search_path,
-                      config->nmodule_search_path, config->module_search_paths);
+                      &config->module_search_paths);
 
         if (config->pycache_prefix != NULL) {
             COPY_WSTR(pycache_prefix);
@@ -784,8 +780,7 @@ pymain_run_python(PyInterpreterState *interp, int *exitcode)
         }
     }
     else if (!config->preconfig.isolated) {
-        PyObject *path0 = _PyPathConfig_ComputeArgv0(config->argc,
-                                                     config->argv);
+        PyObject *path0 = _PyPathConfig_ComputeArgv0(&config->argv);
         if (path0 == NULL) {
             err = _Py_INIT_NO_MEMORY();
             goto done;
index bba25108bdf7ff0969148771c4e188787df147f3..7c143f1ef387b42f4684574e0ffd04593caad122 100644 (file)
@@ -479,8 +479,8 @@ static int test_init_from_config(void)
         L"-c",
         L"pass",
     };
-    config.argc = Py_ARRAY_LENGTH(argv);
-    config.argv = argv;
+    config.argv.length = Py_ARRAY_LENGTH(argv);
+    config.argv.items = argv;
 
     config.program = L"conf_program";
 
@@ -489,15 +489,15 @@ static int test_init_from_config(void)
         L"core_xoption2=",
         L"core_xoption3",
     };
-    config.nxoption = Py_ARRAY_LENGTH(xoptions);
-    config.xoptions = xoptions;
+    config.xoptions.length = Py_ARRAY_LENGTH(xoptions);
+    config.xoptions.items = xoptions;
 
     static wchar_t* warnoptions[2] = {
         L"default",
         L"error::ResourceWarning",
     };
-    config.nwarnoption = Py_ARRAY_LENGTH(warnoptions);
-    config.warnoptions = warnoptions;
+    config.warnoptions.length = Py_ARRAY_LENGTH(warnoptions);
+    config.warnoptions.items = warnoptions;
 
     /* FIXME: test module_search_path_env */
     /* FIXME: test home */
index 845e4c9a163ab73c0965776ea473e0e2991a3b36..15107fa36ce9e6df23500a8c6c191ad6e93569d0 100644 (file)
@@ -202,81 +202,128 @@ fail:
 }
 
 
-/* --- _Py_wstrlist ----------------------------------------------- */
+/* --- _PyWstrList ------------------------------------------------ */
+
+#ifndef NDEBUG
+int
+_PyWstrList_CheckConsistency(const _PyWstrList *list)
+{
+    assert(list->length >= 0);
+    if (list->length != 0) {
+        assert(list->items != NULL);
+    }
+    for (Py_ssize_t i = 0; i < list->length; i++) {
+        assert(list->items[i] != NULL);
+    }
+    return 1;
+}
+#endif   /* Py_DEBUG */
+
 
 void
-_Py_wstrlist_clear(int len, wchar_t **list)
+_PyWstrList_Clear(_PyWstrList *list)
 {
-    for (int i=0; i < len; i++) {
-        PyMem_RawFree(list[i]);
+    assert(_PyWstrList_CheckConsistency(list));
+    for (Py_ssize_t i=0; i < list->length; i++) {
+        PyMem_RawFree(list->items[i]);
     }
-    PyMem_RawFree(list);
+    PyMem_RawFree(list->items);
+    list->length = 0;
+    list->items = NULL;
 }
 
 
-wchar_t**
-_Py_wstrlist_copy(int len, wchar_t * const *list)
+int
+_PyWstrList_Copy(_PyWstrList *list, const _PyWstrList *list2)
 {
-    assert((len > 0 && list != NULL) || len == 0);
-    size_t size = len * sizeof(list[0]);
-    wchar_t **list_copy = PyMem_RawMalloc(size);
-    if (list_copy == NULL) {
-        return NULL;
+    assert(_PyWstrList_CheckConsistency(list));
+    assert(_PyWstrList_CheckConsistency(list2));
+
+    if (list2->length == 0) {
+        _PyWstrList_Clear(list);
+        return 0;
     }
-    for (int i=0; i < len; i++) {
-        wchar_t* arg = _PyMem_RawWcsdup(list[i]);
-        if (arg == NULL) {
-            _Py_wstrlist_clear(i, list_copy);
-            return NULL;
+
+    _PyWstrList copy = _PyWstrList_INIT;
+
+    size_t size = list2->length * sizeof(list2->items[0]);
+    copy.items = PyMem_RawMalloc(size);
+    if (copy.items == NULL) {
+        return -1;
+    }
+
+    for (Py_ssize_t i=0; i < list2->length; i++) {
+        wchar_t *item = _PyMem_RawWcsdup(list2->items[i]);
+        if (item == NULL) {
+            _PyWstrList_Clear(&copy);
+            return -1;
         }
-        list_copy[i] = arg;
+        copy.items[i] = item;
+        copy.length = i + 1;
     }
-    return list_copy;
+
+    _PyWstrList_Clear(list);
+    *list = copy;
+    return 0;
 }
 
 
-_PyInitError
-_Py_wstrlist_append(int *len, wchar_t ***list, const wchar_t *str)
+int
+_PyWstrList_Append(_PyWstrList *list, const wchar_t *item)
 {
-    if (*len == INT_MAX) {
-        /* len+1 would overflow */
-        return _Py_INIT_NO_MEMORY();
+    if (list->length == PY_SSIZE_T_MAX) {
+        /* lenght+1 would overflow */
+        return -1;
     }
-    wchar_t *str2 = _PyMem_RawWcsdup(str);
-    if (str2 == NULL) {
-        return _Py_INIT_NO_MEMORY();
+
+    wchar_t *item2 = _PyMem_RawWcsdup(item);
+    if (item2 == NULL) {
+        return -1;
     }
 
-    size_t size = (*len + 1) * sizeof(list[0]);
-    wchar_t **list2 = (wchar_t **)PyMem_RawRealloc(*list, size);
-    if (list2 == NULL) {
-        PyMem_RawFree(str2);
-        return _Py_INIT_NO_MEMORY();
+    size_t size = (list->length + 1) * sizeof(list->items[0]);
+    wchar_t **items2 = (wchar_t **)PyMem_RawRealloc(list->items, size);
+    if (items2 == NULL) {
+        PyMem_RawFree(item2);
+        return -1;
     }
-    list2[*len] = str2;
-    *list = list2;
-    (*len)++;
-    return _Py_INIT_OK();
+
+    items2[list->length] = item2;
+    list->items = items2;
+    list->length++;
+    return 0;
+}
+
+
+static int
+_PyWstrList_Extend(_PyWstrList *list, const _PyWstrList *list2)
+{
+    for (Py_ssize_t i = 0; i < list2->length; i++) {
+        if (_PyWstrList_Append(list, list2->items[i])) {
+            return -1;
+        }
+    }
+    return 0;
 }
 
 
 PyObject*
-_Py_wstrlist_as_pylist(int len, wchar_t **list)
+_PyWstrList_AsList(const _PyWstrList *list)
 {
-    assert(list != NULL || len < 1);
+    assert(_PyWstrList_CheckConsistency(list));
 
-    PyObject *pylist = PyList_New(len);
+    PyObject *pylist = PyList_New(list->length);
     if (pylist == NULL) {
         return NULL;
     }
 
-    for (int i = 0; i < len; i++) {
-        PyObject *v = PyUnicode_FromWideChar(list[i], -1);
-        if (v == NULL) {
+    for (Py_ssize_t i = 0; i < list->length; i++) {
+        PyObject *item = PyUnicode_FromWideChar(list->items[i], -1);
+        if (item == NULL) {
             Py_DECREF(pylist);
             return NULL;
         }
-        PyList_SET_ITEM(pylist, i, v);
+        PyList_SET_ITEM(pylist, i, item);
     }
     return pylist;
 }
@@ -369,8 +416,7 @@ _Py_ClearStandardStreamEncoding(void)
 /* --- Py_GetArgcArgv() ------------------------------------------- */
 
 /* For Py_GetArgcArgv(); set by _Py_SetArgcArgv() */
-static int orig_argc = 0;
-static wchar_t **orig_argv = NULL;
+static _PyWstrList orig_argv = {.length = 0, .items = NULL};
 
 
 void
@@ -379,32 +425,22 @@ _Py_ClearArgcArgv(void)
     PyMemAllocatorEx old_alloc;
     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
 
-    _Py_wstrlist_clear(orig_argc, orig_argv);
-    orig_argc = 0;
-    orig_argv = NULL;
+    _PyWstrList_Clear(&orig_argv);
 
     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
 }
 
 
 static int
-_Py_SetArgcArgv(int argc, wchar_t * const *argv)
+_Py_SetArgcArgv(Py_ssize_t argc, wchar_t * const *argv)
 {
+    const _PyWstrList argv_list = {.length = argc, .items = (wchar_t **)argv};
     int res;
 
     PyMemAllocatorEx old_alloc;
     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
 
-    wchar_t **argv_copy = _Py_wstrlist_copy(argc, argv);
-    if (argv_copy != NULL) {
-        _Py_ClearArgcArgv();
-        orig_argc = argc;
-        orig_argv = argv_copy;
-        res = 0;
-    }
-    else {
-        res = -1;
-    }
+    res = _PyWstrList_Copy(&orig_argv, &argv_list);
 
     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
     return res;
@@ -416,8 +452,8 @@ _Py_SetArgcArgv(int argc, wchar_t * const *argv)
 void
 Py_GetArgcArgv(int *argc, wchar_t ***argv)
 {
-    *argc = orig_argc;
-    *argv = orig_argv;
+    *argc = (int)orig_argv.length;
+    *argv = orig_argv.items;
 }
 
 
@@ -439,12 +475,6 @@ _PyCoreConfig_Clear(_PyCoreConfig *config)
         PyMem_RawFree(ATTR); \
         ATTR = NULL; \
     } while (0)
-#define CLEAR_WSTRLIST(LEN, LIST) \
-    do { \
-        _Py_wstrlist_clear(LEN, LIST); \
-        LEN = 0; \
-        LIST = NULL; \
-    } while (0)
 
     CLEAR(config->pycache_prefix);
     CLEAR(config->module_search_path_env);
@@ -452,13 +482,11 @@ _PyCoreConfig_Clear(_PyCoreConfig *config)
     CLEAR(config->program_name);
     CLEAR(config->program);
 
-    CLEAR_WSTRLIST(config->argc, config->argv);
-    config->argc = -1;
-
-    CLEAR_WSTRLIST(config->nwarnoption, config->warnoptions);
-    CLEAR_WSTRLIST(config->nxoption, config->xoptions);
-    CLEAR_WSTRLIST(config->nmodule_search_path, config->module_search_paths);
-    config->nmodule_search_path = -1;
+    _PyWstrList_Clear(&config->argv);
+    _PyWstrList_Clear(&config->warnoptions);
+    _PyWstrList_Clear(&config->xoptions);
+    _PyWstrList_Clear(&config->module_search_paths);
+    config->use_module_search_paths = 0;
 
     CLEAR(config->executable);
     CLEAR(config->prefix);
@@ -477,7 +505,6 @@ _PyCoreConfig_Clear(_PyCoreConfig *config)
     CLEAR(config->run_module);
     CLEAR(config->run_filename);
 #undef CLEAR
-#undef CLEAR_WSTRLIST
 }
 
 
@@ -509,15 +536,11 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
             } \
         } \
     } while (0)
-#define COPY_WSTRLIST(LEN, LIST) \
+#define COPY_WSTRLIST(LIST) \
     do { \
-        if (config2->LIST != NULL) { \
-            config->LIST = _Py_wstrlist_copy(config2->LEN, config2->LIST); \
-            if (config->LIST == NULL) { \
-                return -1; \
-            } \
+        if (_PyWstrList_Copy(&config->LIST, &config2->LIST) < 0 ) { \
+            return -1; \
         } \
-        config->LEN = config2->LEN; \
     } while (0)
 
     COPY_ATTR(install_signal_handlers);
@@ -538,10 +561,11 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
     COPY_WSTR_ATTR(program_name);
     COPY_WSTR_ATTR(program);
 
-    COPY_WSTRLIST(argc, argv);
-    COPY_WSTRLIST(nwarnoption, warnoptions);
-    COPY_WSTRLIST(nxoption, xoptions);
-    COPY_WSTRLIST(nmodule_search_path, module_search_paths);
+    COPY_WSTRLIST(argv);
+    COPY_WSTRLIST(warnoptions);
+    COPY_WSTRLIST(xoptions);
+    COPY_WSTRLIST(module_search_paths);
+    COPY_ATTR(use_module_search_paths);
 
     COPY_WSTR_ATTR(executable);
     COPY_WSTR_ATTR(prefix);
@@ -817,7 +841,7 @@ config_init_executable(_PyCoreConfig *config)
 static const wchar_t*
 config_get_xoption(const _PyCoreConfig *config, wchar_t *name)
 {
-    return _Py_get_xoption(config->nxoption, config->xoptions, name);
+    return _Py_get_xoption(&config->xoptions, name);
 }
 
 
@@ -1427,9 +1451,6 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyPreConfig *preconfig)
     if (config->tracemalloc < 0) {
         config->tracemalloc = 0;
     }
-    if (config->argc < 0) {
-        config->argc = 0;
-    }
 
     if (config->filesystem_encoding == NULL || config->filesystem_errors == NULL) {
         err = config_init_fs_encoding(config);
@@ -1449,6 +1470,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyPreConfig *preconfig)
     assert(config->stdio_encoding != NULL);
     assert(config->stdio_errors != NULL);
     assert(config->_check_hash_pycs_mode != NULL);
+    assert(_PyWstrList_CheckConsistency(&config->argv));
 
     return _Py_INIT_OK();
 }
@@ -1546,8 +1568,8 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config)
         : (Py_INCREF(Py_None), Py_None))
 #define SET_ITEM_WSTR(ATTR) \
     SET_ITEM(#ATTR, FROM_WSTRING(config->ATTR))
-#define SET_ITEM_WSTRLIST(NOPTION, OPTIONS) \
-    SET_ITEM(#OPTIONS, _Py_wstrlist_as_pylist(config->NOPTION, config->OPTIONS))
+#define SET_ITEM_WSTRLIST(LIST) \
+    SET_ITEM(#LIST, _PyWstrList_AsList(&config->LIST))
 
     SET_ITEM_INT(install_signal_handlers);
     SET_ITEM_INT(use_hash_seed);
@@ -1563,13 +1585,13 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config)
     SET_ITEM_STR(filesystem_errors);
     SET_ITEM_WSTR(pycache_prefix);
     SET_ITEM_WSTR(program_name);
-    SET_ITEM_WSTRLIST(argc, argv);
+    SET_ITEM_WSTRLIST(argv);
     SET_ITEM_WSTR(program);
-    SET_ITEM_WSTRLIST(nxoption, xoptions);
-    SET_ITEM_WSTRLIST(nwarnoption, warnoptions);
+    SET_ITEM_WSTRLIST(xoptions);
+    SET_ITEM_WSTRLIST(warnoptions);
     SET_ITEM_WSTR(module_search_path_env);
     SET_ITEM_WSTR(home);
-    SET_ITEM_WSTRLIST(nmodule_search_path, module_search_paths);
+    SET_ITEM_WSTRLIST(module_search_paths);
     SET_ITEM_WSTR(executable);
     SET_ITEM_WSTR(prefix);
     SET_ITEM_WSTR(base_prefix);
@@ -1622,13 +1644,9 @@ fail:
 /* --- _PyCmdline ------------------------------------------------- */
 
 typedef struct {
-    const _PyArgv *args;
-    int argc;
-    wchar_t **argv;
-    int nwarnoption;             /* Number of -W command line options */
-    wchar_t **warnoptions;       /* Command line -W options */
-    int nenv_warnoption;         /* Number of PYTHONWARNINGS environment variables */
-    wchar_t **env_warnoptions;   /* PYTHONWARNINGS environment variables */
+    _PyWstrList argv;
+    _PyWstrList warnoptions;     /* Command line -W options */
+    _PyWstrList env_warnoptions; /* PYTHONWARNINGS environment variables */
     int print_help;              /* -h, -? options */
     int print_version;           /* -V option */
 } _PyCmdline;
@@ -1637,18 +1655,9 @@ typedef struct {
 static void
 cmdline_clear(_PyCmdline *cmdline)
 {
-    _Py_wstrlist_clear(cmdline->nwarnoption, cmdline->warnoptions);
-    cmdline->nwarnoption = 0;
-    cmdline->warnoptions = NULL;
-
-    _Py_wstrlist_clear(cmdline->nenv_warnoption, cmdline->env_warnoptions);
-    cmdline->nenv_warnoption = 0;
-    cmdline->env_warnoptions = NULL;
-
-    if (cmdline->args->use_bytes_argv && cmdline->argv != NULL) {
-        _Py_wstrlist_clear(cmdline->args->argc, cmdline->argv);
-    }
-    cmdline->argv = NULL;
+    _PyWstrList_Clear(&cmdline->warnoptions);
+    _PyWstrList_Clear(&cmdline->env_warnoptions);
+    _PyWstrList_Clear(&cmdline->argv);
 }
 
 
@@ -1659,11 +1668,10 @@ static _PyInitError
 config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
                      int *need_usage)
 {
-    _PyInitError err;
     _PyOS_ResetGetOpt();
     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) {
             break;
         }
@@ -1775,20 +1783,14 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
             break;
 
         case 'W':
-            err = _Py_wstrlist_append(&cmdline->nwarnoption,
-                                      &cmdline->warnoptions,
-                                      _PyOS_optarg);
-            if (_Py_INIT_FAILED(err)) {
-                return err;
+            if (_PyWstrList_Append(&cmdline->warnoptions, _PyOS_optarg) < 0) {
+                return _Py_INIT_NO_MEMORY();
             }
             break;
 
         case 'X':
-            err = _Py_wstrlist_append(&config->nxoption,
-                                      &config->xoptions,
-                                      _PyOS_optarg);
-            if (_Py_INIT_FAILED(err)) {
-                return err;
+            if (_PyWstrList_Append(&config->xoptions, _PyOS_optarg) < 0) {
+                return _Py_INIT_NO_MEMORY();
             }
             break;
 
@@ -1810,10 +1812,10 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
     } while (1);
 
     if (config->run_command == NULL && config->run_module == NULL
-        && _PyOS_optind < cmdline->args->argc
-        && wcscmp(cmdline->argv[_PyOS_optind], L"-") != 0)
+        && _PyOS_optind < cmdline->argv.length
+        && wcscmp(cmdline->argv.items[_PyOS_optind], L"-") != 0)
     {
-        config->run_filename = _PyMem_RawWcsdup(cmdline->argv[_PyOS_optind]);
+        config->run_filename = _PyMem_RawWcsdup(cmdline->argv.items[_PyOS_optind]);
         if (config->run_filename == NULL) {
             return _Py_INIT_NO_MEMORY();
         }
@@ -1858,12 +1860,9 @@ cmdline_init_env_warnoptions(_PyCmdline *cmdline, const _PyCoreConfig *config)
          warning != NULL;
          warning = WCSTOK(NULL, L",", &context))
     {
-        _PyInitError err = _Py_wstrlist_append(&cmdline->nenv_warnoption,
-                                               &cmdline->env_warnoptions,
-                                               warning);
-        if (_Py_INIT_FAILED(err)) {
+        if (_PyWstrList_Append(&cmdline->env_warnoptions, warning) < 0) {
             PyMem_RawFree(env);
-            return err;
+            return _Py_INIT_NO_MEMORY();
         }
     }
     PyMem_RawFree(env);
@@ -1875,8 +1874,8 @@ static _PyInitError
 config_init_program(_PyCoreConfig *config, const _PyCmdline *cmdline)
 {
     wchar_t *program;
-    if (cmdline->args->argc >= 1 && cmdline->argv != NULL) {
-        program = cmdline->argv[0];
+    if (cmdline->argv.length >= 1) {
+        program = cmdline->argv.items[0];
     }
     else {
         program = L"";
@@ -1890,28 +1889,10 @@ config_init_program(_PyCoreConfig *config, const _PyCmdline *cmdline)
 }
 
 
-static _PyInitError
-config_add_warnings_optlist(_PyCoreConfig *config,
-                            int len, wchar_t * const *options)
-{
-    for (int i = 0; i < len; i++) {
-        _PyInitError err = _Py_wstrlist_append(&config->nwarnoption,
-                                               &config->warnoptions,
-                                               options[i]);
-        if (_Py_INIT_FAILED(err)) {
-            return err;
-        }
-    }
-    return _Py_INIT_OK();
-}
-
-
 static _PyInitError
 config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline)
 {
-    _PyInitError err;
-
-    assert(config->nwarnoption == 0);
+    assert(config->warnoptions.length == 0);
 
     /* The priority order for warnings configuration is (highest precedence
      * first):
@@ -1929,26 +1910,17 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline)
      */
 
     if (config->preconfig.dev_mode) {
-        err = _Py_wstrlist_append(&config->nwarnoption,
-                                  &config->warnoptions,
-                                  L"default");
-        if (_Py_INIT_FAILED(err)) {
-            return err;
+        if (_PyWstrList_Append(&config->warnoptions, L"default")) {
+            return _Py_INIT_NO_MEMORY();
         }
     }
 
-    err = config_add_warnings_optlist(config,
-                                      cmdline->nenv_warnoption,
-                                      cmdline->env_warnoptions);
-    if (_Py_INIT_FAILED(err)) {
-        return err;
+    if (_PyWstrList_Extend(&config->warnoptions, &cmdline->env_warnoptions) < 0) {
+        return _Py_INIT_NO_MEMORY();
     }
 
-    err = config_add_warnings_optlist(config,
-                                      cmdline->nwarnoption,
-                                      cmdline->warnoptions);
-    if (_Py_INIT_FAILED(err)) {
-        return err;
+    if (_PyWstrList_Extend(&config->warnoptions, &cmdline->warnoptions) < 0) {
+        return _Py_INIT_NO_MEMORY();
     }
 
     /* If the bytes_warning_flag isn't set, bytesobject.c and bytearrayobject.c
@@ -1956,18 +1928,15 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline)
      * case.
      */
     if (config->bytes_warning) {
-        wchar_t *filter;
+        const wchar_t *filter;
         if (config->bytes_warning> 1) {
             filter = L"error::BytesWarning";
         }
         else {
             filter = L"default::BytesWarning";
         }
-        err = _Py_wstrlist_append(&config->nwarnoption,
-                                  &config->warnoptions,
-                                  filter);
-        if (_Py_INIT_FAILED(err)) {
-            return err;
+        if (_PyWstrList_Append(&config->warnoptions, filter)) {
+            return _Py_INIT_NO_MEMORY();
         }
     }
     return _Py_INIT_OK();
@@ -1977,23 +1946,24 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline)
 static _PyInitError
 config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline)
 {
-    /* Copy argv to be able to modify it (to force -c/-m) */
-    int argc = cmdline->args->argc - _PyOS_optind;
-    wchar_t **argv;
+    _PyWstrList wargv = _PyWstrList_INIT;
 
-    if (argc <= 0 || cmdline->argv == NULL) {
+    /* Copy argv to be able to modify it (to force -c/-m) */
+    if (cmdline->argv.length <= _PyOS_optind) {
         /* Ensure at least one (empty) argument is seen */
-        static wchar_t *empty_argv[1] = {L""};
-        argc = 1;
-        argv = _Py_wstrlist_copy(1, empty_argv);
+        if (_PyWstrList_Append(&wargv, L"") < 0) {
+            return _Py_INIT_NO_MEMORY();
+        }
     }
     else {
-        argv = _Py_wstrlist_copy(argc, &cmdline->argv[_PyOS_optind]);
-    }
-
-    if (argv == NULL) {
-        return _Py_INIT_NO_MEMORY();
+        _PyWstrList slice;
+        slice.length = cmdline->argv.length - _PyOS_optind;
+        slice.items = &cmdline->argv.items[_PyOS_optind];
+        if (_PyWstrList_Copy(&wargv, &slice) < 0) {
+            return _Py_INIT_NO_MEMORY();
+        }
     }
+    assert(wargv.length >= 1);
 
     wchar_t *arg0 = NULL;
     if (config->run_command != NULL) {
@@ -2007,17 +1977,16 @@ config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline)
     if (arg0 != NULL) {
         arg0 = _PyMem_RawWcsdup(arg0);
         if (arg0 == NULL) {
-            _Py_wstrlist_clear(argc, argv);
+            _PyWstrList_Clear(&wargv);
             return _Py_INIT_NO_MEMORY();
         }
 
-        assert(argc >= 1);
-        PyMem_RawFree(argv[0]);
-        argv[0] = arg0;
+        PyMem_RawFree(wargv.items[0]);
+        wargv.items[0] = arg0;
     }
 
-    config->argc = argc;
-    config->argv = argv;
+    _PyWstrList_Clear(&config->argv);
+    config->argv = wargv;
     return _Py_INIT_OK();
 }
 
@@ -2097,7 +2066,7 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
         return err;
     }
 
-    if (_Py_SetArgcArgv(cmdline->args->argc, cmdline->argv) < 0) {
+    if (_Py_SetArgcArgv(cmdline->argv.length, cmdline->argv.items) < 0) {
         return _Py_INIT_NO_MEMORY();
     }
     return _Py_INIT_OK();
@@ -2117,9 +2086,8 @@ _PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args,
 
     _PyCmdline 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;
     }
index 1dc872041ff54d20f034e58160f3496a05c6165a..10bd1d49d7d1b78c634659ab5e23118f407ad23f 100644 (file)
@@ -37,9 +37,9 @@
 extern "C" {
 #endif
 
-int _PyOS_opterr = 1;          /* generate error messages */
-int _PyOS_optind = 1;          /* index into argv array   */
-wchar_t *_PyOS_optarg = NULL;     /* optional argument       */
+int _PyOS_opterr = 1;                 /* generate error messages */
+Py_ssize_t _PyOS_optind = 1;          /* index into argv array   */
+const wchar_t *_PyOS_optarg = NULL;   /* optional argument       */
 
 static wchar_t *opt_ptr = L"";
 
@@ -61,7 +61,7 @@ void _PyOS_ResetGetOpt(void)
     opt_ptr = L"";
 }
 
-int _PyOS_GetOpt(int argc, wchar_t **argv, int *longindex)
+int _PyOS_GetOpt(Py_ssize_t argc, wchar_t **argv, int *longindex)
 {
     wchar_t *ptr;
     wchar_t option;
index 14dbba78af12e3c9601f0a89dfd01de0aa168456..fb2d19e2797a7d2ba1b5ed97fbd6ffa92c3d74a3 100644 (file)
@@ -154,14 +154,14 @@ _PyPathConfig_ClearGlobal(void)
 
 
 static wchar_t*
-wstrlist_join(wchar_t sep, int count, wchar_t **list)
+_PyWstrList_Join(const _PyWstrList *list, wchar_t sep)
 {
     size_t len = 1;   /* NUL terminator */
-    for (int i=0; i < count; i++) {
+    for (Py_ssize_t i=0; i < list->length; i++) {
         if (i != 0) {
             len++;
         }
-        len += wcslen(list[i]);
+        len += wcslen(list->items[i]);
     }
 
     wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
@@ -169,8 +169,8 @@ wstrlist_join(wchar_t sep, int count, wchar_t **list)
         return NULL;
     }
     wchar_t *str = text;
-    for (int i=0; i < count; i++) {
-        wchar_t *path = list[i];
+    for (Py_ssize_t i=0; i < list->length; i++) {
+        wchar_t *path = list->items[i];
         if (i != 0) {
             *str++ = SEP;
         }
@@ -194,9 +194,7 @@ _PyCoreConfig_SetPathConfig(const _PyCoreConfig *core_config)
     _PyInitError err;
     _PyPathConfig path_config = _PyPathConfig_INIT;
 
-    path_config.module_search_path = wstrlist_join(DELIM,
-                                                   core_config->nmodule_search_path,
-                                                   core_config->module_search_paths);
+    path_config.module_search_path = _PyWstrList_Join(&core_config->module_search_paths, DELIM);
     if (path_config.module_search_path == NULL) {
         goto no_memory;
     }
@@ -244,10 +242,9 @@ static _PyInitError
 core_config_init_module_search_paths(_PyCoreConfig *config,
                                      _PyPathConfig *path_config)
 {
-    assert(config->module_search_paths == NULL);
-    assert(config->nmodule_search_path < 0);
+    assert(!config->use_module_search_paths);
 
-    config->nmodule_search_path = 0;
+    _PyWstrList_Clear(&config->module_search_paths);
 
     const wchar_t *sys_path = path_config->module_search_path;
     const wchar_t delim = DELIM;
@@ -266,12 +263,10 @@ core_config_init_module_search_paths(_PyCoreConfig *config,
         memcpy(path, sys_path, path_len * sizeof(wchar_t));
         path[path_len] = L'\0';
 
-        _PyInitError err = _Py_wstrlist_append(&config->nmodule_search_path,
-                                               &config->module_search_paths,
-                                               path);
+        int res = _PyWstrList_Append(&config->module_search_paths, path);
         PyMem_RawFree(path);
-        if (_Py_INIT_FAILED(err)) {
-            return err;
+        if (res < 0) {
+            return _Py_INIT_NO_MEMORY();
         }
 
         if (*p == '\0') {
@@ -279,6 +274,7 @@ core_config_init_module_search_paths(_PyCoreConfig *config,
         }
         sys_path = p + 1;
     }
+    config->use_module_search_paths = 1;
     return _Py_INIT_OK();
 }
 
@@ -294,7 +290,7 @@ _PyCoreConfig_CalculatePathConfig(_PyCoreConfig *config)
         goto error;
     }
 
-    if (config->nmodule_search_path < 0) {
+    if (!config->use_module_search_paths) {
         err = core_config_init_module_search_paths(config, &path_config);
         if (_Py_INIT_FAILED(err)) {
             goto error;
@@ -352,7 +348,7 @@ _PyInitError
 _PyCoreConfig_InitPathConfig(_PyCoreConfig *config)
 {
     /* Do we need to calculate the path? */
-    if ((config->nmodule_search_path < 0)
+    if (!config->use_module_search_paths
         || (config->executable == NULL)
         || (config->prefix == NULL)
 #ifdef MS_WINDOWS
@@ -567,8 +563,10 @@ Py_GetProgramName(void)
 
 /* Compute argv[0] which will be prepended to sys.argv */
 PyObject*
-_PyPathConfig_ComputeArgv0(int argc, wchar_t **argv)
+_PyPathConfig_ComputeArgv0(const _PyWstrList *argv)
 {
+    assert(_PyWstrList_CheckConsistency(argv));
+
     wchar_t *argv0;
     wchar_t *p = NULL;
     Py_ssize_t n = 0;
@@ -585,8 +583,8 @@ _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv)
     wchar_t fullpath[MAX_PATH];
 #endif
 
-    argv0 = argv[0];
-    if (argc > 0 && argv0 != NULL) {
+    if (argv->length > 0) {
+        argv0 = argv->items[0];
         have_module_arg = (wcscmp(argv0, L"-m") == 0);
         have_script_arg = !have_module_arg && (wcscmp(argv0, L"-c") != 0);
     }
index 50d66b1249220b1d269d8d55a32ed19455310490..a86ece57cfced938d9a7d7bc1a64cdc5fa1e52cb 100644 (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;
     }
index 99fd460ff5ab6e75e39bfdaa89ea8f80299f9aac..b3330a01f7c11e2851af1fcdf29574581602e18a 100644 (file)
@@ -2739,35 +2739,35 @@ PySys_SetPath(const wchar_t *path)
 }
 
 static PyObject *
-makeargvobject(int argc, wchar_t **argv)
+make_sys_argv(int argc, wchar_t * const * argv)
 {
-    PyObject *av;
-    if (argc <= 0 || argv == NULL) {
-        /* Ensure at least one (empty) argument is seen */
-        static wchar_t *empty_argv[1] = {L""};
-        argv = empty_argv;
-        argc = 1;
+    PyObject *list = PyList_New(argc);
+    if (list == NULL) {
+        return NULL;
     }
-    av = PyList_New(argc);
-    if (av != NULL) {
-        int i;
-        for (i = 0; i < argc; i++) {
-            PyObject *v = PyUnicode_FromWideChar(argv[i], -1);
-            if (v == NULL) {
-                Py_DECREF(av);
-                av = NULL;
-                break;
-            }
-            PyList_SET_ITEM(av, i, v);
+
+    for (Py_ssize_t i = 0; i < argc; i++) {
+        PyObject *v = PyUnicode_FromWideChar(argv[i], -1);
+        if (v == NULL) {
+            Py_DECREF(list);
+            return NULL;
         }
+        PyList_SET_ITEM(list, i, v);
     }
-    return av;
+    return list;
 }
 
 void
 PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
 {
-    PyObject *av = makeargvobject(argc, argv);
+    if (argc < 1 || argv == NULL) {
+        /* Ensure at least one (empty) argument is seen */
+        wchar_t* empty_argv[1] = {L""};
+        argv = empty_argv;
+        argc = 1;
+    }
+
+    PyObject *av = make_sys_argv(argc, argv);
     if (av == NULL) {
         Py_FatalError("no mem for sys.argv");
     }
@@ -2780,7 +2780,8 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
     if (updatepath) {
         /* If argv[0] is not '-c' nor '-m', prepend argv[0] to sys.path.
            If argv[0] is a symlink, use the real path. */
-        PyObject *argv0 = _PyPathConfig_ComputeArgv0(argc, argv);
+        const _PyWstrList argv_list = {.length = argc, .items = argv};
+        PyObject *argv0 = _PyPathConfig_ComputeArgv0(&argv_list);
         if (argv0 == NULL) {
             Py_FatalError("can't compute path0 from argv");
         }