From 91b9ecf82c3287b45f39158c5134a87414ff26bc Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 1 Mar 2019 17:52:56 +0100 Subject: bpo-36142: Add preconfig.c (GH-12128) * Add _PyArgv_Decode() function * Move _Py_ClearFileSystemEncoding() and _Py_SetFileSystemEncoding() to preconfig.c. --- Include/cpython/coreconfig.h | 9 ++-- Include/internal/pycore_coreconfig.h | 11 +++-- Include/internal/pycore_fileutils.h | 2 + Makefile.pre.in | 1 + PCbuild/pythoncore.vcxproj | 1 + PCbuild/pythoncore.vcxproj.filters | 3 ++ Python/coreconfig.c | 83 ++------------------------------ Python/preconfig.c | 92 ++++++++++++++++++++++++++++++++++++ 8 files changed, 115 insertions(+), 87 deletions(-) create mode 100644 Python/preconfig.c diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h index 8109d4a..e3ebf73 100644 --- a/Include/cpython/coreconfig.h +++ b/Include/cpython/coreconfig.h @@ -5,7 +5,7 @@ extern "C" { #endif -/* _PyArgv */ +/* --- _PyArgv ---------------------------------------------------- */ typedef struct { int argc; @@ -15,7 +15,7 @@ typedef struct { } _PyArgv; -/* _PyInitError */ +/* --- _PyInitError ----------------------------------------------- */ typedef struct { const char *prefix; @@ -46,7 +46,7 @@ typedef struct { #define _Py_INIT_FAILED(err) \ (err.msg != NULL || err.exitcode != -1) -/* _PyCoreConfig */ +/* --- _PyCoreConfig ---------------------------------------------- */ typedef struct { /* Install signal handlers? Yes by default. */ @@ -364,7 +364,8 @@ typedef struct { /* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */ -/* Functions used for testing */ +/* --- Function used for testing ---------------------------------- */ + PyAPI_FUNC(PyObject *) _Py_GetGlobalVariablesAsDict(void); PyAPI_FUNC(PyObject *) _PyCoreConfig_AsDict(const _PyCoreConfig *config); diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h index ebb0a9e..9f3a4c7 100644 --- a/Include/internal/pycore_coreconfig.h +++ b/Include/internal/pycore_coreconfig.h @@ -8,7 +8,7 @@ extern "C" { # error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN defined" #endif -/* _Py_wstrlist */ +/* --- _Py_wstrlist ----------------------------------------------- */ PyAPI_FUNC(void) _Py_wstrlist_clear( int len, @@ -24,12 +24,17 @@ PyAPI_FUNC(PyObject*) _Py_wstrlist_as_pylist( int len, wchar_t **list); -/* Py_GetArgcArgv() helpers */ +/* --- _PyArgv ---------------------------------------------------- */ + +PyAPI_FUNC(_PyInitError) _PyArgv_Decode(const _PyArgv *args, + wchar_t*** argv_p); + +/* --- Py_GetArgcArgv() helpers ----------------------------------- */ PyAPI_FUNC(void) _Py_ClearArgcArgv(void); PyAPI_FUNC(int) _Py_SetArgcArgv(int argc, wchar_t * const *argv); -/* _PyCoreConfig */ +/* --- _PyCoreConfig ---------------------------------------------- */ PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config); PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *); diff --git a/Include/internal/pycore_fileutils.h b/Include/internal/pycore_fileutils.h index 2500665..23ae201 100644 --- a/Include/internal/pycore_fileutils.h +++ b/Include/internal/pycore_fileutils.h @@ -10,6 +10,8 @@ extern "C" { #include /* struct lconv */ +PyAPI_DATA(int) _Py_HasFileSystemDefaultEncodeErrors; + PyAPI_FUNC(int) _Py_DecodeUTF8Ex( const char *arg, Py_ssize_t arglen, diff --git a/Makefile.pre.in b/Makefile.pre.in index 9c2d3d6..5ae6948 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -357,6 +357,7 @@ PYTHON_OBJS= \ Python/mystrtoul.o \ Python/pathconfig.o \ Python/peephole.o \ + Python/preconfig.o \ Python/pyarena.o \ Python/pyctype.o \ Python/pyfpe.o \ diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 1ec5f75..992c84f 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -425,6 +425,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 5053dcf..293bded 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -989,6 +989,9 @@ Python + + Python + Python diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 47dbe66..e1bf8b5 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -136,13 +136,6 @@ int Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */ int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */ #endif -/* The filesystem encoding is chosen by config_init_fs_encoding(), - see also initfsencoding(). */ -const char *Py_FileSystemDefaultEncoding = NULL; -int Py_HasFileSystemDefaultEncoding = 0; -const char *Py_FileSystemDefaultEncodeErrors = NULL; -static int _Py_HasFileSystemDefaultEncodeErrors = 0; - PyObject * _Py_GetGlobalVariablesAsDict(void) @@ -296,49 +289,6 @@ _Py_wstrlist_as_pylist(int len, wchar_t **list) } -void -_Py_ClearFileSystemEncoding(void) -{ - if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) { - PyMem_RawFree((char*)Py_FileSystemDefaultEncoding); - Py_FileSystemDefaultEncoding = NULL; - } - if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) { - PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors); - Py_FileSystemDefaultEncodeErrors = NULL; - } -} - - -/* --- File system encoding/errors -------------------------------- */ - -/* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors - global configuration variables. */ -int -_Py_SetFileSystemEncoding(const char *encoding, const char *errors) -{ - char *encoding2 = _PyMem_RawStrdup(encoding); - if (encoding2 == NULL) { - return -1; - } - - char *errors2 = _PyMem_RawStrdup(errors); - if (errors2 == NULL) { - PyMem_RawFree(encoding2); - return -1; - } - - _Py_ClearFileSystemEncoding(); - - Py_FileSystemDefaultEncoding = encoding2; - Py_HasFileSystemDefaultEncoding = 0; - - Py_FileSystemDefaultEncodeErrors = errors2; - _Py_HasFileSystemDefaultEncodeErrors = 0; - return 0; -} - - /* --- Py_SetStandardStreamEncoding() ----------------------------- */ /* Helper to allow an embedding application to override the normal @@ -1849,6 +1799,7 @@ fail: 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 */ @@ -1881,35 +1832,7 @@ static _PyInitError cmdline_decode_argv(_PyCmdline *cmdline) { assert(cmdline->argv == NULL); - - const _PyArgv *args = cmdline->args; - - if (args->use_bytes_argv) { - /* +1 for a the NULL terminator */ - size_t size = sizeof(wchar_t*) * (args->argc + 1); - wchar_t** argv = (wchar_t **)PyMem_RawMalloc(size); - if (argv == NULL) { - return _Py_INIT_NO_MEMORY(); - } - - for (int 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); - return DECODE_LOCALE_ERR("command line arguments", - (Py_ssize_t)len); - } - argv[i] = arg; - } - argv[args->argc] = NULL; - - cmdline->argv = argv; - } - else { - cmdline->argv = args->wchar_argv; - } - return _Py_INIT_OK(); + return _PyArgv_Decode(cmdline->args, &cmdline->argv); } @@ -2377,7 +2300,7 @@ config_read_from_argv_impl(_PyCoreConfig *config, const _PyArgv *args) memset(&cmdline, 0, sizeof(cmdline)); cmdline.args = args; - err = cmdline_decode_argv(&cmdline); + err = _PyArgv_Decode(cmdline.args, &cmdline.argv); if (_Py_INIT_FAILED(err)) { goto done; } diff --git a/Python/preconfig.c b/Python/preconfig.c new file mode 100644 index 0000000..8102924 --- /dev/null +++ b/Python/preconfig.c @@ -0,0 +1,92 @@ +#include "Python.h" +#include "pycore_coreconfig.h" + + +#define DECODE_LOCALE_ERR(NAME, LEN) \ + (((LEN) == -2) \ + ? _Py_INIT_USER_ERR("cannot decode " NAME) \ + : _Py_INIT_NO_MEMORY()) + + +/* --- File system encoding/errors -------------------------------- */ + +/* The filesystem encoding is chosen by config_init_fs_encoding(), + see also initfsencoding(). */ +const char *Py_FileSystemDefaultEncoding = NULL; +int Py_HasFileSystemDefaultEncoding = 0; +const char *Py_FileSystemDefaultEncodeErrors = NULL; +int _Py_HasFileSystemDefaultEncodeErrors = 0; + +void +_Py_ClearFileSystemEncoding(void) +{ + if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) { + PyMem_RawFree((char*)Py_FileSystemDefaultEncoding); + Py_FileSystemDefaultEncoding = NULL; + } + if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) { + PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors); + Py_FileSystemDefaultEncodeErrors = NULL; + } +} + + +/* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors + global configuration variables. */ +int +_Py_SetFileSystemEncoding(const char *encoding, const char *errors) +{ + char *encoding2 = _PyMem_RawStrdup(encoding); + if (encoding2 == NULL) { + return -1; + } + + char *errors2 = _PyMem_RawStrdup(errors); + if (errors2 == NULL) { + PyMem_RawFree(encoding2); + return -1; + } + + _Py_ClearFileSystemEncoding(); + + Py_FileSystemDefaultEncoding = encoding2; + Py_HasFileSystemDefaultEncoding = 0; + + Py_FileSystemDefaultEncodeErrors = errors2; + _Py_HasFileSystemDefaultEncodeErrors = 0; + return 0; +} + + +/* --- _PyArgv ---------------------------------------------------- */ + +_PyInitError +_PyArgv_Decode(const _PyArgv *args, wchar_t*** argv_p) +{ + wchar_t** argv; + 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) { + return _Py_INIT_NO_MEMORY(); + } + + for (int 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); + return DECODE_LOCALE_ERR("command line arguments", + (Py_ssize_t)len); + } + argv[i] = arg; + } + argv[args->argc] = NULL; + } + else { + argv = args->wchar_argv; + } + *argv_p = argv; + return _Py_INIT_OK(); +} -- cgit v0.12