mirror of https://github.com/python/cpython
300 lines
6.7 KiB
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)
|
|
{
|
|
}
|