cpython/Python/preconfig.c

300 lines
6.7 KiB
C

#include "Python.h"
#include "pycore_coreconfig.h"
#include "pycore_getopt.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();
}
/* --- _PyPreCmdline ------------------------------------------------- */
typedef struct {
const _PyArgv *args;
int argc;
wchar_t **argv;
} _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;
}
/* --- _PyPreConfig ----------------------------------------------- */
void
_PyPreConfig_Clear(_PyPreConfig *config)
{
}
int
_PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2)
{
_PyPreConfig_Clear(config);
#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
COPY_ATTR(isolated);
COPY_ATTR(use_environment);
#undef COPY_ATTR
return 0;
}
void
_PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
{
#define COPY_FLAG(ATTR, VALUE) \
if (config->ATTR == -1) { \
config->ATTR = VALUE; \
}
#define COPY_NOT_FLAG(ATTR, VALUE) \
if (config->ATTR == -1) { \
config->ATTR = !(VALUE); \
}
COPY_FLAG(isolated, Py_IsolatedFlag);
COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
#undef COPY_FLAG
#undef COPY_NOT_FLAG
}
void
_PyPreConfig_SetGlobalConfig(const _PyPreConfig *config)
{
#define COPY_FLAG(ATTR, VAR) \
if (config->ATTR != -1) { \
VAR = config->ATTR; \
}
#define COPY_NOT_FLAG(ATTR, VAR) \
if (config->ATTR != -1) { \
VAR = !config->ATTR; \
}
COPY_FLAG(isolated, Py_IsolatedFlag);
COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
#undef COPY_FLAG
#undef COPY_NOT_FLAG
}
_PyInitError
_PyPreConfig_Read(_PyPreConfig *config)
{
_PyPreConfig_GetGlobalConfig(config);
if (config->isolated > 0) {
config->use_environment = 0;
}
/* Default values */
if (config->use_environment < 0) {
config->use_environment = 0;
}
assert(config->isolated >= 0);
assert(config->use_environment >= 0);
return _Py_INIT_OK();
}
int
_PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict)
{
#define SET_ITEM(KEY, EXPR) \
do { \
PyObject *obj = (EXPR); \
if (obj == NULL) { \
goto fail; \
} \
int res = PyDict_SetItemString(dict, (KEY), obj); \
Py_DECREF(obj); \
if (res < 0) { \
goto fail; \
} \
} while (0)
#define SET_ITEM_INT(ATTR) \
SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR))
SET_ITEM_INT(isolated);
SET_ITEM_INT(use_environment);
return 0;
fail:
return -1;
#undef SET_ITEM
#undef SET_ITEM_INT
}
/* Parse the command line arguments */
static _PyInitError
preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline)
{
_PyOS_ResetGetOpt();
/* Don't log parsing errors into stderr here: _PyCoreConfig_ReadFromArgv()
is responsible for that */
_PyOS_opterr = 0;
do {
int longindex = -1;
int c = _PyOS_GetOpt(cmdline->args->argc, cmdline->argv, &longindex);
if (c == EOF || c == 'c' || c == 'm') {
break;
}
switch (c) {
case 'E':
config->use_environment = 0;
break;
case 'I':
config->isolated++;
break;
default:
/* ignore other argument:
handled by _PyCoreConfig_ReadFromArgv() */
break;
}
} while (1);
return _Py_INIT_OK();
}
_PyInitError
_PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args)
{
_PyInitError err;
_PyPreCmdline cmdline;
memset(&cmdline, 0, sizeof(cmdline));
cmdline.args = args;
err = _PyArgv_Decode(cmdline.args, &cmdline.argv);
if (_Py_INIT_FAILED(err)) {
goto done;
}
err = preconfig_parse_cmdline(config, &cmdline);
if (_Py_INIT_FAILED(err)) {
goto done;
}
err = _PyPreConfig_Read(config);
if (_Py_INIT_FAILED(err)) {
goto done;
}
err = _Py_INIT_OK();
done:
precmdline_clear(&cmdline);
return err;
}
void
_PyPreConfig_Write(const _PyPreConfig *config)
{
}