Skip to content

Commit 91b9ecf

Browse files
authored
bpo-36142: Add preconfig.c (GH-12128)
* Add _PyArgv_Decode() function * Move _Py_ClearFileSystemEncoding() and _Py_SetFileSystemEncoding() to preconfig.c.
1 parent c991f24 commit 91b9ecf

8 files changed

Lines changed: 115 additions & 87 deletions

File tree

Include/cpython/coreconfig.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
extern "C" {
66
#endif
77

8-
/* _PyArgv */
8+
/* --- _PyArgv ---------------------------------------------------- */
99

1010
typedef struct {
1111
int argc;
@@ -15,7 +15,7 @@ typedef struct {
1515
} _PyArgv;
1616

1717

18-
/* _PyInitError */
18+
/* --- _PyInitError ----------------------------------------------- */
1919

2020
typedef struct {
2121
const char *prefix;
@@ -46,7 +46,7 @@ typedef struct {
4646
#define _Py_INIT_FAILED(err) \
4747
(err.msg != NULL || err.exitcode != -1)
4848

49-
/* _PyCoreConfig */
49+
/* --- _PyCoreConfig ---------------------------------------------- */
5050

5151
typedef struct {
5252
/* Install signal handlers? Yes by default. */
@@ -364,7 +364,8 @@ typedef struct {
364364
/* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */
365365

366366

367-
/* Functions used for testing */
367+
/* --- Function used for testing ---------------------------------- */
368+
368369
PyAPI_FUNC(PyObject *) _Py_GetGlobalVariablesAsDict(void);
369370
PyAPI_FUNC(PyObject *) _PyCoreConfig_AsDict(const _PyCoreConfig *config);
370371

Include/internal/pycore_coreconfig.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extern "C" {
88
# error "this header requires Py_BUILD_CORE or Py_BUILD_CORE_BUILTIN defined"
99
#endif
1010

11-
/* _Py_wstrlist */
11+
/* --- _Py_wstrlist ----------------------------------------------- */
1212

1313
PyAPI_FUNC(void) _Py_wstrlist_clear(
1414
int len,
@@ -24,12 +24,17 @@ PyAPI_FUNC(PyObject*) _Py_wstrlist_as_pylist(
2424
int len,
2525
wchar_t **list);
2626

27-
/* Py_GetArgcArgv() helpers */
27+
/* --- _PyArgv ---------------------------------------------------- */
28+
29+
PyAPI_FUNC(_PyInitError) _PyArgv_Decode(const _PyArgv *args,
30+
wchar_t*** argv_p);
31+
32+
/* --- Py_GetArgcArgv() helpers ----------------------------------- */
2833

2934
PyAPI_FUNC(void) _Py_ClearArgcArgv(void);
3035
PyAPI_FUNC(int) _Py_SetArgcArgv(int argc, wchar_t * const *argv);
3136

32-
/* _PyCoreConfig */
37+
/* --- _PyCoreConfig ---------------------------------------------- */
3338

3439
PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config);
3540
PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *);

Include/internal/pycore_fileutils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ extern "C" {
1010

1111
#include <locale.h> /* struct lconv */
1212

13+
PyAPI_DATA(int) _Py_HasFileSystemDefaultEncodeErrors;
14+
1315
PyAPI_FUNC(int) _Py_DecodeUTF8Ex(
1416
const char *arg,
1517
Py_ssize_t arglen,

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ PYTHON_OBJS= \
357357
Python/mystrtoul.o \
358358
Python/pathconfig.o \
359359
Python/peephole.o \
360+
Python/preconfig.o \
360361
Python/pyarena.o \
361362
Python/pyctype.o \
362363
Python/pyfpe.o \

PCbuild/pythoncore.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@
425425
<ClCompile Include="..\Python\mystrtoul.c" />
426426
<ClCompile Include="..\Python\pathconfig.c" />
427427
<ClCompile Include="..\Python\peephole.c" />
428+
<ClCompile Include="..\Python\preconfig.c" />
428429
<ClCompile Include="..\Python\pyarena.c" />
429430
<ClCompile Include="..\Python\pyctype.c" />
430431
<ClCompile Include="..\Python\pyfpe.c" />

PCbuild/pythoncore.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,9 @@
989989
<ClCompile Include="..\Python\peephole.c">
990990
<Filter>Python</Filter>
991991
</ClCompile>
992+
<ClCompile Include="..\Python\preconfig.c">
993+
<Filter>Python</Filter>
994+
</ClCompile>
992995
<ClCompile Include="..\Python\pyarena.c">
993996
<Filter>Python</Filter>
994997
</ClCompile>

Python/coreconfig.c

Lines changed: 3 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,6 @@ int Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */
136136
int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */
137137
#endif
138138

139-
/* The filesystem encoding is chosen by config_init_fs_encoding(),
140-
see also initfsencoding(). */
141-
const char *Py_FileSystemDefaultEncoding = NULL;
142-
int Py_HasFileSystemDefaultEncoding = 0;
143-
const char *Py_FileSystemDefaultEncodeErrors = NULL;
144-
static int _Py_HasFileSystemDefaultEncodeErrors = 0;
145-
146139

147140
PyObject *
148141
_Py_GetGlobalVariablesAsDict(void)
@@ -296,49 +289,6 @@ _Py_wstrlist_as_pylist(int len, wchar_t **list)
296289
}
297290

298291

299-
void
300-
_Py_ClearFileSystemEncoding(void)
301-
{
302-
if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
303-
PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
304-
Py_FileSystemDefaultEncoding = NULL;
305-
}
306-
if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) {
307-
PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors);
308-
Py_FileSystemDefaultEncodeErrors = NULL;
309-
}
310-
}
311-
312-
313-
/* --- File system encoding/errors -------------------------------- */
314-
315-
/* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
316-
global configuration variables. */
317-
int
318-
_Py_SetFileSystemEncoding(const char *encoding, const char *errors)
319-
{
320-
char *encoding2 = _PyMem_RawStrdup(encoding);
321-
if (encoding2 == NULL) {
322-
return -1;
323-
}
324-
325-
char *errors2 = _PyMem_RawStrdup(errors);
326-
if (errors2 == NULL) {
327-
PyMem_RawFree(encoding2);
328-
return -1;
329-
}
330-
331-
_Py_ClearFileSystemEncoding();
332-
333-
Py_FileSystemDefaultEncoding = encoding2;
334-
Py_HasFileSystemDefaultEncoding = 0;
335-
336-
Py_FileSystemDefaultEncodeErrors = errors2;
337-
_Py_HasFileSystemDefaultEncodeErrors = 0;
338-
return 0;
339-
}
340-
341-
342292
/* --- Py_SetStandardStreamEncoding() ----------------------------- */
343293

344294
/* Helper to allow an embedding application to override the normal
@@ -1849,6 +1799,7 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config)
18491799

18501800
typedef struct {
18511801
const _PyArgv *args;
1802+
int argc;
18521803
wchar_t **argv;
18531804
int nwarnoption; /* Number of -W command line options */
18541805
wchar_t **warnoptions; /* Command line -W options */
@@ -1881,35 +1832,7 @@ static _PyInitError
18811832
cmdline_decode_argv(_PyCmdline *cmdline)
18821833
{
18831834
assert(cmdline->argv == NULL);
1884-
1885-
const _PyArgv *args = cmdline->args;
1886-
1887-
if (args->use_bytes_argv) {
1888-
/* +1 for a the NULL terminator */
1889-
size_t size = sizeof(wchar_t*) * (args->argc + 1);
1890-
wchar_t** argv = (wchar_t **)PyMem_RawMalloc(size);
1891-
if (argv == NULL) {
1892-
return _Py_INIT_NO_MEMORY();
1893-
}
1894-
1895-
for (int i = 0; i < args->argc; i++) {
1896-
size_t len;
1897-
wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
1898-
if (arg == NULL) {
1899-
_Py_wstrlist_clear(i, argv);
1900-
return DECODE_LOCALE_ERR("command line arguments",
1901-
(Py_ssize_t)len);
1902-
}
1903-
argv[i] = arg;
1904-
}
1905-
argv[args->argc] = NULL;
1906-
1907-
cmdline->argv = argv;
1908-
}
1909-
else {
1910-
cmdline->argv = args->wchar_argv;
1911-
}
1912-
return _Py_INIT_OK();
1835+
return _PyArgv_Decode(cmdline->args, &cmdline->argv);
19131836
}
19141837

19151838

@@ -2377,7 +2300,7 @@ config_read_from_argv_impl(_PyCoreConfig *config, const _PyArgv *args)
23772300
memset(&cmdline, 0, sizeof(cmdline));
23782301
cmdline.args = args;
23792302

2380-
err = cmdline_decode_argv(&cmdline);
2303+
err = _PyArgv_Decode(cmdline.args, &cmdline.argv);
23812304
if (_Py_INIT_FAILED(err)) {
23822305
goto done;
23832306
}

Python/preconfig.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#include "Python.h"
2+
#include "pycore_coreconfig.h"
3+
4+
5+
#define DECODE_LOCALE_ERR(NAME, LEN) \
6+
(((LEN) == -2) \
7+
? _Py_INIT_USER_ERR("cannot decode " NAME) \
8+
: _Py_INIT_NO_MEMORY())
9+
10+
11+
/* --- File system encoding/errors -------------------------------- */
12+
13+
/* The filesystem encoding is chosen by config_init_fs_encoding(),
14+
see also initfsencoding(). */
15+
const char *Py_FileSystemDefaultEncoding = NULL;
16+
int Py_HasFileSystemDefaultEncoding = 0;
17+
const char *Py_FileSystemDefaultEncodeErrors = NULL;
18+
int _Py_HasFileSystemDefaultEncodeErrors = 0;
19+
20+
void
21+
_Py_ClearFileSystemEncoding(void)
22+
{
23+
if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
24+
PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
25+
Py_FileSystemDefaultEncoding = NULL;
26+
}
27+
if (!_Py_HasFileSystemDefaultEncodeErrors && Py_FileSystemDefaultEncodeErrors) {
28+
PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors);
29+
Py_FileSystemDefaultEncodeErrors = NULL;
30+
}
31+
}
32+
33+
34+
/* Set Py_FileSystemDefaultEncoding and Py_FileSystemDefaultEncodeErrors
35+
global configuration variables. */
36+
int
37+
_Py_SetFileSystemEncoding(const char *encoding, const char *errors)
38+
{
39+
char *encoding2 = _PyMem_RawStrdup(encoding);
40+
if (encoding2 == NULL) {
41+
return -1;
42+
}
43+
44+
char *errors2 = _PyMem_RawStrdup(errors);
45+
if (errors2 == NULL) {
46+
PyMem_RawFree(encoding2);
47+
return -1;
48+
}
49+
50+
_Py_ClearFileSystemEncoding();
51+
52+
Py_FileSystemDefaultEncoding = encoding2;
53+
Py_HasFileSystemDefaultEncoding = 0;
54+
55+
Py_FileSystemDefaultEncodeErrors = errors2;
56+
_Py_HasFileSystemDefaultEncodeErrors = 0;
57+
return 0;
58+
}
59+
60+
61+
/* --- _PyArgv ---------------------------------------------------- */
62+
63+
_PyInitError
64+
_PyArgv_Decode(const _PyArgv *args, wchar_t*** argv_p)
65+
{
66+
wchar_t** argv;
67+
if (args->use_bytes_argv) {
68+
/* +1 for a the NULL terminator */
69+
size_t size = sizeof(wchar_t*) * (args->argc + 1);
70+
argv = (wchar_t **)PyMem_RawMalloc(size);
71+
if (argv == NULL) {
72+
return _Py_INIT_NO_MEMORY();
73+
}
74+
75+
for (int i = 0; i < args->argc; i++) {
76+
size_t len;
77+
wchar_t *arg = Py_DecodeLocale(args->bytes_argv[i], &len);
78+
if (arg == NULL) {
79+
_Py_wstrlist_clear(i, argv);
80+
return DECODE_LOCALE_ERR("command line arguments",
81+
(Py_ssize_t)len);
82+
}
83+
argv[i] = arg;
84+
}
85+
argv[args->argc] = NULL;
86+
}
87+
else {
88+
argv = args->wchar_argv;
89+
}
90+
*argv_p = argv;
91+
return _Py_INIT_OK();
92+
}

0 commit comments

Comments
 (0)