diff options
author | Martin v. Löwis <martin@v.loewis.de> | 2008-04-05 20:41:37 (GMT) |
---|---|---|
committer | Martin v. Löwis <martin@v.loewis.de> | 2008-04-05 20:41:37 (GMT) |
commit | 790465fd90e8a72590386465f518db9e67ab843f (patch) | |
tree | 62e3e47f6f97120dfdfc94a87dc1a06414d95a13 /Python | |
parent | b9279bc88f867d9d3b6606502a678b137329b54d (diff) | |
download | cpython-790465fd90e8a72590386465f518db9e67ab843f.zip cpython-790465fd90e8a72590386465f518db9e67ab843f.tar.gz cpython-790465fd90e8a72590386465f518db9e67ab843f.tar.bz2 |
Change command line processing API to use wchar_t.
Fixes #2128.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/frozenmain.c | 39 | ||||
-rw-r--r-- | Python/getopt.c | 39 | ||||
-rw-r--r-- | Python/pythonrun.c | 30 | ||||
-rw-r--r-- | Python/sysmodule.c | 108 |
4 files changed, 144 insertions, 72 deletions
diff --git a/Python/frozenmain.c b/Python/frozenmain.c index 397f046..88c3465 100644 --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -2,6 +2,7 @@ /* Python interpreter main program for frozen scripts */ #include "Python.h" +#include <locale.h> #ifdef MS_WINDOWS extern void PyWinFreeze_ExeInit(void); @@ -15,9 +16,13 @@ int Py_FrozenMain(int argc, char **argv) { char *p; - int n, sts; + int i, n, sts; int inspect = 0; int unbuffered = 0; + char *oldloc; + wchar_t **argv_copy = PyMem_Malloc(sizeof(wchar_t*)*argc); + /* We need a second copies, as Python might modify the first one. */ + wchar_t **argv_copy2 = PyMem_Malloc(sizeof(wchar_t*)*argc); Py_FrozenFlag = 1; /* Suppress errors from getpath.c */ @@ -32,10 +37,33 @@ Py_FrozenMain(int argc, char **argv) setbuf(stderr, (char *)NULL); } + if (!argv_copy) { + fprintf(stderr, "out of memory"); + return 1; + } + + oldloc = setlocale(LC_ALL, NULL); + setlocale(LC_ALL, ""); + for (i = 0; i < argc; i++) { + size_t argsize = mbstowcs(NULL, argv[i], 0); + if (argsize == (size_t)-1) { + fprintf(stderr, "Could not convert argument %d to string", i); + return 1; + } + argv_copy[i] = PyMem_Malloc((argsize+1)*sizeof(wchar_t)); + argv_copy2[i] = argv_copy[i]; + if (!argv_copy[i]) { + fprintf(stderr, "out of memory"); + return 1; + } + mbstowcs(argv_copy[i], argv[i], argsize+1); + } + setlocale(LC_ALL, oldloc); + #ifdef MS_WINDOWS PyInitFrozenExtensions(); #endif /* MS_WINDOWS */ - Py_SetProgramName(argv[0]); + Py_SetProgramName(argv_copy[0]); Py_Initialize(); #ifdef MS_WINDOWS PyWinFreeze_ExeInit(); @@ -45,7 +73,7 @@ Py_FrozenMain(int argc, char **argv) fprintf(stderr, "Python %s\n%s\n", Py_GetVersion(), Py_GetCopyright()); - PySys_SetArgv(argc, argv); + PySys_SetArgv(argc, argv_copy); n = PyImport_ImportFrozenModule("__main__"); if (n == 0) @@ -64,5 +92,10 @@ Py_FrozenMain(int argc, char **argv) PyWinFreeze_ExeTerm(); #endif Py_Finalize(); + for (i = 0; i < argc; i++) { + PyMem_Free(argv_copy2[i]); + } + PyMem_Free(argv_copy); + PyMem_Free(argv_copy2); return sts; } diff --git a/Python/getopt.c b/Python/getopt.c index 659efcf..7c1d605 100644 --- a/Python/getopt.c +++ b/Python/getopt.c @@ -27,8 +27,11 @@ /* Modified to support --help and --version, as well as /? on Windows * by Georg Brandl. */ +#include <Python.h> #include <stdio.h> #include <string.h> +#include <wchar.h> +#include <pygetopt.h> #ifdef __cplusplus extern "C" { @@ -36,40 +39,40 @@ extern "C" { int _PyOS_opterr = 1; /* generate error messages */ int _PyOS_optind = 1; /* index into argv array */ -char *_PyOS_optarg = NULL; /* optional argument */ +wchar_t *_PyOS_optarg = NULL; /* optional argument */ -int _PyOS_GetOpt(int argc, char **argv, char *optstring) +int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring) { - static char *opt_ptr = ""; - char *ptr; - int option; + static wchar_t *opt_ptr = L""; + wchar_t *ptr; + wchar_t option; if (*opt_ptr == '\0') { if (_PyOS_optind >= argc) return -1; #ifdef MS_WINDOWS - else if (strcmp(argv[_PyOS_optind], "/?") == 0) { + else if (wcscmp(argv[_PyOS_optind], L"/?") == 0) { ++_PyOS_optind; return 'h'; } #endif - else if (argv[_PyOS_optind][0] != '-' || - argv[_PyOS_optind][1] == '\0' /* lone dash */ ) + else if (argv[_PyOS_optind][0] != L'-' || + argv[_PyOS_optind][1] == L'\0' /* lone dash */ ) return -1; - else if (strcmp(argv[_PyOS_optind], "--") == 0) { + else if (wcscmp(argv[_PyOS_optind], L"--") == 0) { ++_PyOS_optind; return -1; } - else if (strcmp(argv[_PyOS_optind], "--help") == 0) { + else if (wcscmp(argv[_PyOS_optind], L"--help") == 0) { ++_PyOS_optind; return 'h'; } - else if (strcmp(argv[_PyOS_optind], "--version") == 0) { + else if (wcscmp(argv[_PyOS_optind], L"--version") == 0) { ++_PyOS_optind; return 'V'; } @@ -78,27 +81,27 @@ int _PyOS_GetOpt(int argc, char **argv, char *optstring) opt_ptr = &argv[_PyOS_optind++][1]; } - if ( (option = *opt_ptr++) == '\0') + if ( (option = *opt_ptr++) == L'\0') return -1; - if ((ptr = strchr(optstring, option)) == NULL) { + if ((ptr = wcschr(optstring, option)) == NULL) { if (_PyOS_opterr) - fprintf(stderr, "Unknown option: -%c\n", option); + fprintf(stderr, "Unknown option: -%c\n", (char)option); return '_'; } - if (*(ptr + 1) == ':') { - if (*opt_ptr != '\0') { + if (*(ptr + 1) == L':') { + if (*opt_ptr != L'\0') { _PyOS_optarg = opt_ptr; - opt_ptr = ""; + opt_ptr = L""; } else { if (_PyOS_optind >= argc) { if (_PyOS_opterr) fprintf(stderr, - "Argument expected for the -%c option\n", option); + "Argument expected for the -%c option\n", (char)option); return '_'; } diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 3207fb8..124eaf0 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -17,6 +17,7 @@ #include "ast.h" #include "eval.h" #include "marshal.h" +#include "osdefs.h" #ifdef HAVE_SIGNAL_H #include <signal.h> @@ -30,6 +31,7 @@ #ifdef MS_WINDOWS #undef BYTE #include "windows.h" +#define PATH_MAX MAXPATHLEN #endif #ifndef Py_REF_DEBUG @@ -44,7 +46,7 @@ extern "C" { #endif -extern char *Py_GetPath(void); +extern wchar_t *Py_GetPath(void); extern grammar _PyParser_Grammar; /* From graminit.c */ @@ -646,35 +648,43 @@ Py_EndInterpreter(PyThreadState *tstate) PyInterpreterState_Delete(interp); } -static char *progname = "python"; +static wchar_t *progname = L"python"; void -Py_SetProgramName(char *pn) +Py_SetProgramName(wchar_t *pn) { if (pn && *pn) progname = pn; } -char * +wchar_t * Py_GetProgramName(void) { return progname; } -static char *default_home = NULL; +static wchar_t *default_home = NULL; +static wchar_t env_home[PATH_MAX+1]; void -Py_SetPythonHome(char *home) +Py_SetPythonHome(wchar_t *home) { default_home = home; } -char * +wchar_t * Py_GetPythonHome(void) { - char *home = default_home; - if (home == NULL && !Py_IgnoreEnvironmentFlag) - home = Py_GETENV("PYTHONHOME"); + wchar_t *home = default_home; + if (home == NULL && !Py_IgnoreEnvironmentFlag) { + char* chome = Py_GETENV("PYTHONHOME"); + if (chome) { + size_t r = mbstowcs(env_home, chome, PATH_MAX+1); + if (r != (size_t)-1 && r <= PATH_MAX) + home = env_home; + } + + } return home; } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index aceb2a3..81adf5d 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -882,7 +882,7 @@ PySys_ResetWarnOptions(void) } void -PySys_AddWarnOption(const char *s) +PySys_AddWarnOption(const wchar_t *s) { PyObject *str; @@ -892,7 +892,7 @@ PySys_AddWarnOption(const char *s) if (warnoptions == NULL) return; } - str = PyUnicode_FromString(s); + str = PyUnicode_FromWideChar(s, -1); if (str != NULL) { PyList_Append(warnoptions, str); Py_DECREF(str); @@ -1222,12 +1222,12 @@ _PySys_Init(void) SET_SYS_FROM_STRING("platform", PyUnicode_FromString(Py_GetPlatform())); SET_SYS_FROM_STRING("executable", - PyUnicode_DecodeFSDefault( - Py_GetProgramFullPath())); + PyUnicode_FromWideChar( + Py_GetProgramFullPath(), -1)); SET_SYS_FROM_STRING("prefix", - PyUnicode_DecodeFSDefault(Py_GetPrefix())); + PyUnicode_FromWideChar(Py_GetPrefix(), -1)); SET_SYS_FROM_STRING("exec_prefix", - PyUnicode_DecodeFSDefault(Py_GetExecPrefix())); + PyUnicode_FromWideChar(Py_GetExecPrefix(), -1)); SET_SYS_FROM_STRING("maxsize", PyLong_FromSsize_t(PY_SSIZE_T_MAX)); SET_SYS_FROM_STRING("float_info", @@ -1280,15 +1280,15 @@ _PySys_Init(void) } static PyObject * -makepathobject(const char *path, int delim) +makepathobject(const wchar_t *path, wchar_t delim) { int i, n; - const char *p; + const wchar_t *p; PyObject *v, *w; n = 1; p = path; - while ((p = strchr(p, delim)) != NULL) { + while ((p = wcschr(p, delim)) != NULL) { n++; p++; } @@ -1296,10 +1296,10 @@ makepathobject(const char *path, int delim) if (v == NULL) return NULL; for (i = 0; ; i++) { - p = strchr(path, delim); + p = wcschr(path, delim); if (p == NULL) - p = strchr(path, '\0'); /* End of string */ - w = PyUnicode_DecodeFSDefaultAndSize(path, (Py_ssize_t) (p - path)); + p = wcschr(path, L'\0'); /* End of string */ + w = PyUnicode_FromWideChar(path, (Py_ssize_t)(p - path)); if (w == NULL) { Py_DECREF(v); return NULL; @@ -1313,7 +1313,7 @@ makepathobject(const char *path, int delim) } void -PySys_SetPath(const char *path) +PySys_SetPath(const wchar_t *path) { PyObject *v; if ((v = makepathobject(path, DELIM)) == NULL) @@ -1324,12 +1324,12 @@ PySys_SetPath(const char *path) } static PyObject * -makeargvobject(int argc, char **argv) +makeargvobject(int argc, wchar_t **argv) { PyObject *av; if (argc <= 0 || argv == NULL) { /* Ensure at least one (empty) argument is seen */ - static char *empty_argv[1] = {""}; + static wchar_t *empty_argv[1] = {L""}; argv = empty_argv; argc = 1; } @@ -1351,7 +1351,7 @@ makeargvobject(int argc, char **argv) } else v = PyUnicode_FromString(argv[i]); #else - PyObject *v = PyUnicode_FromString(argv[i]); + PyObject *v = PyUnicode_FromWideChar(argv[i], -1); #endif if (v == NULL) { Py_DECREF(av); @@ -1364,13 +1364,38 @@ makeargvobject(int argc, char **argv) return av; } +#ifdef HAVE_REALPATH +static wchar_t* +_wrealpath(const wchar_t *path, wchar_t *resolved_path) +{ + char cpath[PATH_MAX]; + char cresolved_path[PATH_MAX]; + char *res; + size_t r; + r = wcstombs(cpath, path, PATH_MAX); + if (r == (size_t)-1 || r >= PATH_MAX) { + errno = EINVAL; + return NULL; + } + res = realpath(cpath, cresolved_path); + if (res == NULL) + return NULL; + r = mbstowcs(resolved_path, cresolved_path, PATH_MAX); + if (r == (size_t)-1 || r >= PATH_MAX) { + errno = EINVAL; + return NULL; + } + return resolved_path; +} +#endif + void -PySys_SetArgv(int argc, char **argv) +PySys_SetArgv(int argc, wchar_t **argv) { #if defined(HAVE_REALPATH) - char fullpath[MAXPATHLEN]; + wchar_t fullpath[MAXPATHLEN]; #elif defined(MS_WINDOWS) - char fullpath[MAX_PATH]; + wchar_t fullpath[MAX_PATH]; #endif PyObject *av = makeargvobject(argc, argv); PyObject *path = PySys_GetObject("path"); @@ -1379,53 +1404,54 @@ PySys_SetArgv(int argc, char **argv) if (PySys_SetObject("argv", av) != 0) Py_FatalError("can't assign sys.argv"); if (path != NULL) { - char *argv0 = argv[0]; - char *p = NULL; + wchar_t *argv0 = argv[0]; + wchar_t *p = NULL; Py_ssize_t n = 0; PyObject *a; + extern int _Py_wreadlink(const wchar_t *, wchar_t *, size_t); #ifdef HAVE_READLINK - char link[MAXPATHLEN+1]; - char argv0copy[2*MAXPATHLEN+1]; + wchar_t link[MAXPATHLEN+1]; + wchar_t argv0copy[2*MAXPATHLEN+1]; int nr = 0; - if (argc > 0 && argv0 != NULL && strcmp(argv0, "-c") != 0) - nr = readlink(argv0, link, MAXPATHLEN); + if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) + nr = _Py_wreadlink(argv0, link, MAXPATHLEN); if (nr > 0) { /* It's a symlink */ link[nr] = '\0'; if (link[0] == SEP) argv0 = link; /* Link to absolute path */ - else if (strchr(link, SEP) == NULL) + else if (wcschr(link, SEP) == NULL) ; /* Link without path */ else { /* Must join(dirname(argv0), link) */ - char *q = strrchr(argv0, SEP); + wchar_t *q = wcsrchr(argv0, SEP); if (q == NULL) argv0 = link; /* argv0 without path */ else { /* Must make a copy */ - strcpy(argv0copy, argv0); - q = strrchr(argv0copy, SEP); - strcpy(q+1, link); + wcscpy(argv0copy, argv0); + q = wcsrchr(argv0copy, SEP); + wcscpy(q+1, link); argv0 = argv0copy; } } } #endif /* HAVE_READLINK */ #if SEP == '\\' /* Special case for MS filename syntax */ - if (argc > 0 && argv0 != NULL && strcmp(argv0, "-c") != 0) { - char *q; + if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) { + wchar_t *q; #ifdef MS_WINDOWS - char *ptemp; - if (GetFullPathName(argv0, - sizeof(fullpath), + wchar_t *ptemp; + if (GetFullPathNameW(argv0, + sizeof(fullpath)/sizeof(fullpath[0]), fullpath, &ptemp)) { argv0 = fullpath; } #endif - p = strrchr(argv0, SEP); + p = wcsrchr(argv0, SEP); /* Test for alternate separator */ - q = strrchr(p ? p : argv0, '/'); + q = wcsrchr(p ? p : argv0, '/'); if (q != NULL) p = q; if (p != NULL) { @@ -1435,13 +1461,13 @@ PySys_SetArgv(int argc, char **argv) } } #else /* All other filename syntaxes */ - if (argc > 0 && argv0 != NULL && strcmp(argv0, "-c") != 0) { + if (argc > 0 && argv0 != NULL && wcscmp(argv0, L"-c") != 0) { #if defined(HAVE_REALPATH) - if (realpath(argv0, fullpath)) { + if (_wrealpath(argv0, fullpath)) { argv0 = fullpath; } #endif - p = strrchr(argv0, SEP); + p = wcsrchr(argv0, SEP); } if (p != NULL) { n = p + 1 - argv0; @@ -1451,7 +1477,7 @@ PySys_SetArgv(int argc, char **argv) #endif /* Unix */ } #endif /* All others */ - a = PyUnicode_FromStringAndSize(argv0, n); + a = PyUnicode_FromWideChar(argv0, n); if (a == NULL) Py_FatalError("no mem for sys.path insertion"); if (PyList_Insert(path, 0, a) < 0) |