bpo-36142: Add preconfig.c (GH-12128)

* Add _PyArgv_Decode() function
* Move _Py_ClearFileSystemEncoding() and _Py_SetFileSystemEncoding()
  to preconfig.c.
This commit is contained in:
Victor Stinner 2019-03-01 17:52:56 +01:00 committed by GitHub
parent c991f2415d
commit 91b9ecf82c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 115 additions and 87 deletions

View File

@ -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);

View File

@ -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 *);

View File

@ -10,6 +10,8 @@ extern "C" {
#include <locale.h> /* struct lconv */
PyAPI_DATA(int) _Py_HasFileSystemDefaultEncodeErrors;
PyAPI_FUNC(int) _Py_DecodeUTF8Ex(
const char *arg,
Py_ssize_t arglen,

View File

@ -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 \

View File

@ -425,6 +425,7 @@
<ClCompile Include="..\Python\mystrtoul.c" />
<ClCompile Include="..\Python\pathconfig.c" />
<ClCompile Include="..\Python\peephole.c" />
<ClCompile Include="..\Python\preconfig.c" />
<ClCompile Include="..\Python\pyarena.c" />
<ClCompile Include="..\Python\pyctype.c" />
<ClCompile Include="..\Python\pyfpe.c" />

View File

@ -989,6 +989,9 @@
<ClCompile Include="..\Python\peephole.c">
<Filter>Python</Filter>
</ClCompile>
<ClCompile Include="..\Python\preconfig.c">
<Filter>Python</Filter>
</ClCompile>
<ClCompile Include="..\Python\pyarena.c">
<Filter>Python</Filter>
</ClCompile>

View File

@ -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;
}

92
Python/preconfig.c Normal file
View File

@ -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();
}