]> granicus.if.org Git - python/commitdiff
Change command line processing API to use wchar_t.
authorMartin v. Löwis <martin@v.loewis.de>
Sat, 5 Apr 2008 20:41:37 +0000 (20:41 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Sat, 5 Apr 2008 20:41:37 +0000 (20:41 +0000)
Fixes #2128.

21 files changed:
Doc/c-api/init.rst
Doc/c-api/sys.rst
Doc/c-api/unicode.rst
Doc/c-api/veryhigh.rst
Include/osdefs.h
Include/pygetopt.h
Include/pythonrun.h
Include/sysmodule.h
Misc/NEWS
Modules/_tkinter.c
Modules/getpath.c
Modules/main.c
Modules/python.c
Objects/unicodeobject.c
PC/WinMain.c
PC/getpathp.c
PC/pyconfig.h
Python/frozenmain.c
Python/getopt.c
Python/pythonrun.c
Python/sysmodule.c

index dac37e1767cd1f726ed0a5ddd33b29c4eac84e37..53fc735ab21db896ee26fae6a3b1ac55b9deef8c 100644 (file)
@@ -161,7 +161,7 @@ Initialization, Finalization, and Threads
    haven't been explicitly destroyed at that point.
 
 
-.. cfunction:: void Py_SetProgramName(char *name)
+.. cfunction:: void Py_SetProgramName(wchar_t *name)
 
    .. index::
       single: Py_Initialize()
@@ -170,11 +170,12 @@ Initialization, Finalization, and Threads
 
    This function should be called before :cfunc:`Py_Initialize` is called for
    the first time, if it is called at all.  It tells the interpreter the value
-   of the ``argv[0]`` argument to the :cfunc:`main` function of the program.
+   of the ``argv[0]`` argument to the :cfunc:`main` function of the program
+   (converted to wide characters).
    This is used by :cfunc:`Py_GetPath` and some other functions below to find
    the Python run-time libraries relative to the interpreter executable.  The
    default value is ``'python'``.  The argument should point to a
-   zero-terminated character string in static storage whose contents will not
+   zero-terminated wide character string in static storage whose contents will not
    change for the duration of the program's execution.  No code in the Python
    interpreter will change the contents of this storage.
 
@@ -188,7 +189,7 @@ Initialization, Finalization, and Threads
    value.
 
 
-.. cfunction:: char* Py_GetPrefix()
+.. cfunction:: wchar_t* Py_GetPrefix()
 
    Return the *prefix* for installed platform-independent files. This is derived
    through a number of complicated rules from the program name set with
@@ -201,7 +202,7 @@ Initialization, Finalization, and Threads
    It is only useful on Unix.  See also the next function.
 
 
-.. cfunction:: char* Py_GetExecPrefix()
+.. cfunction:: wchar_t* Py_GetExecPrefix()
 
    Return the *exec-prefix* for installed platform-*dependent* files.  This is
    derived through a number of complicated rules from the program name set with
@@ -236,7 +237,7 @@ Initialization, Finalization, and Threads
    platform.
 
 
-.. cfunction:: char* Py_GetProgramFullPath()
+.. cfunction:: wchar_t* Py_GetProgramFullPath()
 
    .. index::
       single: Py_SetProgramName()
@@ -249,7 +250,7 @@ Initialization, Finalization, and Threads
    to Python code as ``sys.executable``.
 
 
-.. cfunction:: char* Py_GetPath()
+.. cfunction:: wchar_t* Py_GetPath()
 
    .. index::
       triple: module; search; path
@@ -342,7 +343,7 @@ Initialization, Finalization, and Threads
    ``sys.version``.
 
 
-.. cfunction:: void PySys_SetArgv(int argc, char **argv)
+.. cfunction:: void PySys_SetArgv(int argc, wchar_t **argv)
 
    .. index::
       single: main()
index 7696811a78dc6e80500ce026ea606e0822c57a35..2a98c9d0e1256384ebe3d8379a5d50b2ca9d48ef 100644 (file)
@@ -84,11 +84,11 @@ accessible to C code.  They all work with the current interpreter thread's
 
    Reset :data:`sys.warnoptions` to an empty list.
 
-.. cfunction:: void PySys_AddWarnOption(char *s)
+.. cfunction:: void PySys_AddWarnOption(wchar_t *s)
 
    Append *s* to :data:`sys.warnoptions`.
 
-.. cfunction:: void PySys_SetPath(char *path)
+.. cfunction:: void PySys_SetPath(wchar_t *path)
 
    Set :data:`sys.path` to a list object of paths found in *path* which should
    be a list of paths separated with the platform's search path delimiter
index 448cf6895cc8e8ea063da0aefad82443729a6376..17c25d577fd8e10a897c23fe58c362f94be539ea 100644 (file)
@@ -336,6 +336,8 @@ the system's :ctype:`wchar_t`.
 .. cfunction:: PyObject* PyUnicode_FromWideChar(const wchar_t *w, Py_ssize_t size)
 
    Create a Unicode object from the :ctype:`wchar_t` buffer *w* of the given size.
+   Passing -1 as the size indicates that the function must itself compute the length,
+   using wcslen.
    Return *NULL* on failure.
 
 
index 6a3f91d098038b52691046720030564edbd6ee86..2378c76633490bc1b34b20f92fe169c40539d1d5 100644 (file)
@@ -25,16 +25,18 @@ are only passed to these functions if it is certain that they were created by
 the same library that the Python runtime is using.
 
 
-.. cfunction:: int Py_Main(int argc, char **argv)
-
-   The main program for the standard interpreter.  This is made available for
-   programs which embed Python.  The *argc* and *argv* parameters should be
-   prepared exactly as those which are passed to a C program's :cfunc:`main`
-   function.  It is important to note that the argument list may be modified (but
-   the contents of the strings pointed to by the argument list are not). The return
-   value will be the integer passed to the :func:`sys.exit` function, ``1`` if the
-   interpreter exits due to an exception, or ``2`` if the parameter list does not
-   represent a valid Python command line.
+.. cfunction:: int Py_Main(int argc, wchar_t **argv)
+
+   The main program for the standard interpreter.  This is made
+   available for programs which embed Python.  The *argc* and *argv*
+   parameters should be prepared exactly as those which are passed to
+   a C program's :cfunc:`main` function (converted to wchar_t
+   according to the user's locale).  It is important to note that the
+   argument list may be modified (but the contents of the strings
+   pointed to by the argument list are not). The return value will be
+   the integer passed to the :func:`sys.exit` function, ``1`` if the
+   interpreter exits due to an exception, or ``2`` if the parameter
+   list does not represent a valid Python command line.
 
 
 .. cfunction:: int PyRun_AnyFile(FILE *fp, const char *filename)
index d0305e9c7bde0a156a4b3ed4fbf6d38e0fc2c968..90b430a635b76a4ed9319afbb6968f4eb132374d 100644 (file)
@@ -12,20 +12,20 @@ extern "C" {
 #if defined(MS_WINDOWS) || defined(__BORLANDC__) || defined(__WATCOMC__) || defined(__DJGPP__) || defined(PYOS_OS2)
 #if defined(PYOS_OS2) && defined(PYCC_GCC)
 #define MAXPATHLEN 260
-#define SEP '/'
-#define ALTSEP '\\'
+#define SEP L'/'
+#define ALTSEP L'\\'
 #else
-#define SEP '\\'
-#define ALTSEP '/'
+#define SEP L'\\'
+#define ALTSEP L'/'
 #define MAXPATHLEN 256
 #endif
-#define DELIM ';'
+#define DELIM L';'
 #endif
 #endif
 
 /* Filename separator */
 #ifndef SEP
-#define SEP '/'
+#define SEP L'/'
 #endif
 
 /* Max pathname length */
@@ -39,7 +39,7 @@ extern "C" {
 
 /* Search path entry delimiter */
 #ifndef DELIM
-#define DELIM ':'
+#define DELIM L':'
 #endif
 
 #ifdef __cplusplus
index 80908bea982d371838825aa2ef185326887f60e7..19e3fd1d301ec3f8d985ef9cbc24f93a8572062c 100644 (file)
@@ -7,9 +7,9 @@ extern "C" {
 
 PyAPI_DATA(int) _PyOS_opterr;
 PyAPI_DATA(int) _PyOS_optind;
-PyAPI_DATA(char *) _PyOS_optarg;
+PyAPI_DATA(wchar_t *) _PyOS_optarg;
 
-PyAPI_FUNC(int) _PyOS_GetOpt(int argc, char **argv, char *optstring);
+PyAPI_FUNC(int) _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring);
 
 #ifdef __cplusplus
 }
index 510fd76e26bb23ad63391d190b7bcc90681c6eb3..e5baf946041af19f89db3c4bfb0bb7c3f0a0c397 100644 (file)
@@ -17,11 +17,11 @@ typedef struct {
        int cf_flags;  /* bitmask of CO_xxx flags relevant to future */
 } PyCompilerFlags;
 
-PyAPI_FUNC(void) Py_SetProgramName(char *);
-PyAPI_FUNC(char *) Py_GetProgramName(void);
+PyAPI_FUNC(void) Py_SetProgramName(wchar_t *);
+PyAPI_FUNC(wchar_t *) Py_GetProgramName(void);
 
-PyAPI_FUNC(void) Py_SetPythonHome(char *);
-PyAPI_FUNC(char *) Py_GetPythonHome(void);
+PyAPI_FUNC(void) Py_SetPythonHome(wchar_t *);
+PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void);
 
 PyAPI_FUNC(void) Py_Initialize(void);
 PyAPI_FUNC(void) Py_InitializeEx(int);
@@ -81,7 +81,7 @@ PyAPI_FUNC(void) Py_Exit(int);
 PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *);
 
 /* Bootstrap */
-PyAPI_FUNC(int) Py_Main(int argc, char **argv);
+PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv);
 
 /* Use macros for a bunch of old variants */
 #define PyRun_String(str, s, g, l) PyRun_StringFlags(str, s, g, l, NULL)
@@ -103,10 +103,10 @@ PyAPI_FUNC(int) Py_Main(int argc, char **argv);
         PyRun_FileExFlags(fp, p, s, g, l, 0, flags)
 
 /* In getpath.c */
-PyAPI_FUNC(char *) Py_GetProgramFullPath(void);
-PyAPI_FUNC(char *) Py_GetPrefix(void);
-PyAPI_FUNC(char *) Py_GetExecPrefix(void);
-PyAPI_FUNC(char *) Py_GetPath(void);
+PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void);
+PyAPI_FUNC(wchar_t *) Py_GetPrefix(void);
+PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
+PyAPI_FUNC(wchar_t *) Py_GetPath(void);
 
 /* In their own files */
 PyAPI_FUNC(const char *) Py_GetVersion(void);
index 8ea7eb1d040793484c8009c2bf6b58a2e1c35947..9ba39df90fb6f61c6876ce1251fc6a05c8b0a49b 100644 (file)
@@ -9,8 +9,8 @@ extern "C" {
 
 PyAPI_FUNC(PyObject *) PySys_GetObject(const char *);
 PyAPI_FUNC(int) PySys_SetObject(const char *, PyObject *);
-PyAPI_FUNC(void) PySys_SetArgv(int, char **);
-PyAPI_FUNC(void) PySys_SetPath(const char *);
+PyAPI_FUNC(void) PySys_SetArgv(int, wchar_t **);
+PyAPI_FUNC(void) PySys_SetPath(const wchar_t *);
 
 PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...)
                        Py_GCC_ATTRIBUTE((format(printf, 1, 2)));
@@ -21,7 +21,7 @@ PyAPI_DATA(PyObject *) _PySys_TraceFunc, *_PySys_ProfileFunc;
 PyAPI_DATA(int) _PySys_CheckInterval;
 
 PyAPI_FUNC(void) PySys_ResetWarnOptions(void);
-PyAPI_FUNC(void) PySys_AddWarnOption(const char *);
+PyAPI_FUNC(void) PySys_AddWarnOption(const wchar_t *);
 
 #ifdef __cplusplus
 }
index 84800a15aad398290adedee38886fc05e47e91a7..30d1d39b7447005e00ebc38be972b3f11d70418d 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,10 @@ What's New in Python 3.0a5?
 Core and Builtins
 -----------------
 
+- The command line processing was converted to pass Unicode strings
+  through as unmodified as possible; as a consequence, the C API
+  related to command line arguments was changed to use wchar_t.
+
 Extension Modules
 -----------------
 
index d45e2d4000cd0730116ac6563d8a87e3d08019b0..33efaffa6e4275ac8691845daefd7b150773b867 100644 (file)
@@ -3012,7 +3012,7 @@ ins_string(PyObject *d, char *name, char *val)
 PyMODINIT_FUNC
 init_tkinter(void)
 {
-       PyObject *m, *d;
+       PyObject *m, *d, *uexe, *cexe;
 
        Py_TYPE(&Tkapp_Type) = &PyType_Type;
 
@@ -3065,7 +3065,16 @@ init_tkinter(void)
 
        /* This helps the dynamic loader; in Unicode aware Tcl versions
           it also helps Tcl find its encodings. */
-       Tcl_FindExecutable(Py_GetProgramName());
+       uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
+       if (uexe) {
+               cexe = PyUnicode_AsEncodedString(uexe, 
+                                                Py_FileSystemDefaultEncoding, 
+                                                NULL);
+               if (cexe)
+                       Tcl_FindExecutable(PyString_AsString(cexe));
+               Py_XDECREF(cexe);
+               Py_DECREF(uexe);
+       }
 
        if (PyErr_Occurred())
                return;
index 09fbe1017b18742def1ca40561e1e44df7d88ad6..f752a7ff97c72e6a92241474479739fe21a2b5c5 100644 (file)
 #endif
 
 #ifndef LANDMARK
-#define LANDMARK "os.py"
+#define LANDMARK L"os.py"
 #endif
 
-static char prefix[MAXPATHLEN+1];
-static char exec_prefix[MAXPATHLEN+1];
-static char progpath[MAXPATHLEN+1];
-static char *module_search_path = NULL;
-static char lib_python[] = "lib/python" VERSION;
+static wchar_t prefix[MAXPATHLEN+1];
+static wchar_t exec_prefix[MAXPATHLEN+1];
+static wchar_t progpath[MAXPATHLEN+1];
+static wchar_t *module_search_path = NULL;
+static wchar_t lib_python[] = L"lib/python" VERSION;
+
+/* In principle, this should use HAVE__WSTAT, and _wstat
+   should be detected by autoconf. However, no current
+   POSIX system provides that function, so testing for
+   it is pointless. */
+#ifndef MS_WINDOWS
+static int
+_wstat(const wchar_t* path, struct stat *buf)
+{
+    char fname[PATH_MAX];
+    size_t res = wcstombs(fname, path, sizeof(fname));
+    if (res == (size_t)-1) {
+       errno = EINVAL;
+       return -1;
+    }
+    return stat(fname, buf);
+}
+#endif
+
+#ifndef MS_WINDOWS
+static wchar_t*
+_wgetcwd(wchar_t *buf, size_t size)
+{
+    char fname[PATH_MAX];
+    if (getcwd(fname, PATH_MAX) == NULL)
+       return NULL;
+    if (mbstowcs(buf, fname, size) >= size) {
+       errno = ERANGE;
+       return NULL;
+    }
+    return buf;
+}
+#endif
+
+#ifdef HAVE_READLINK
+int 
+_Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz)
+{
+    char cbuf[PATH_MAX];
+    char cpath[PATH_MAX];
+    int res;
+    size_t r1 = wcstombs(cpath, path, PATH_MAX);
+    if (r1 == (size_t)-1 || r1 >= PATH_MAX) {
+       errno = EINVAL;
+       return -1;
+    }
+    res = (int)readlink(cpath, cbuf, PATH_MAX);
+    if (res == -1)
+       return -1;
+    if (res == PATH_MAX) {
+       errno = EINVAL;
+       return -1;
+    }
+    r1 = mbstowcs(buf, cbuf, bufsiz);
+    if (r1 == -1) {
+       errno = EINVAL;
+       return -1;
+    }
+    return (int)r1;
+    
+}
+#endif
 
 static void
-reduce(char *dir)
+reduce(wchar_t *dir)
 {
-    size_t i = strlen(dir);
+    size_t i = wcslen(dir);
     while (i > 0 && dir[i] != SEP)
         --i;
     dir[i] = '\0';
@@ -142,10 +204,10 @@ reduce(char *dir)
 
 
 static int
-isfile(char *filename)          /* Is file, not directory */
+isfile(wchar_t *filename)          /* Is file, not directory */
 {
     struct stat buf;
-    if (stat(filename, &buf) != 0)
+    if (_wstat(filename, &buf) != 0)
         return 0;
     if (!S_ISREG(buf.st_mode))
         return 0;
@@ -154,14 +216,14 @@ isfile(char *filename)          /* Is file, not directory */
 
 
 static int
-ismodule(char *filename)        /* Is module -- check for .pyc/.pyo too */
+ismodule(wchar_t *filename)        /* Is module -- check for .pyc/.pyo too */
 {
     if (isfile(filename))
         return 1;
 
     /* Check for the compiled version of prefix. */
-    if (strlen(filename) < MAXPATHLEN) {
-        strcat(filename, Py_OptimizeFlag ? "o" : "c");
+    if (wcslen(filename) < MAXPATHLEN) {
+        wcscat(filename, Py_OptimizeFlag ? L"o" : L"c");
         if (isfile(filename))
             return 1;
     }
@@ -170,10 +232,10 @@ ismodule(char *filename)        /* Is module -- check for .pyc/.pyo too */
 
 
 static int
-isxfile(char *filename)         /* Is executable file */
+isxfile(wchar_t *filename)         /* Is executable file */
 {
     struct stat buf;
-    if (stat(filename, &buf) != 0)
+    if (_wstat(filename, &buf) != 0)
         return 0;
     if (!S_ISREG(buf.st_mode))
         return 0;
@@ -184,10 +246,10 @@ isxfile(char *filename)         /* Is executable file */
 
 
 static int
-isdir(char *filename)                   /* Is directory */
+isdir(wchar_t *filename)                   /* Is directory */
 {
     struct stat buf;
-    if (stat(filename, &buf) != 0)
+    if (_wstat(filename, &buf) != 0)
         return 0;
     if (!S_ISDIR(buf.st_mode))
         return 0;
@@ -205,34 +267,34 @@ isdir(char *filename)                   /* Is directory */
    stuff as fits will be appended.
 */
 static void
-joinpath(char *buffer, char *stuff)
+joinpath(wchar_t *buffer, wchar_t *stuff)
 {
     size_t n, k;
     if (stuff[0] == SEP)
         n = 0;
     else {
-        n = strlen(buffer);
+        n = wcslen(buffer);
         if (n > 0 && buffer[n-1] != SEP && n < MAXPATHLEN)
             buffer[n++] = SEP;
     }
     if (n > MAXPATHLEN)
        Py_FatalError("buffer overflow in getpath.c's joinpath()");
-    k = strlen(stuff);
+    k = wcslen(stuff);
     if (n + k > MAXPATHLEN)
         k = MAXPATHLEN - n;
-    strncpy(buffer+n, stuff, k);
+    wcsncpy(buffer+n, stuff, k);
     buffer[n+k] = '\0';
 }
 
 /* copy_absolute requires that path be allocated at least
    MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes. */
 static void
-copy_absolute(char *path, char *p)
+copy_absolute(wchar_t *path, wchar_t *p)
 {
     if (p[0] == SEP)
-        strcpy(path, p);
+        wcscpy(path, p);
     else {
-        getcwd(path, MAXPATHLEN);
+        _wgetcwd(path, MAXPATHLEN);
         if (p[0] == '.' && p[1] == SEP)
             p += 2;
         joinpath(path, p);
@@ -241,46 +303,46 @@ copy_absolute(char *path, char *p)
 
 /* absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes. */
 static void
-absolutize(char *path)
+absolutize(wchar_t *path)
 {
-    char buffer[MAXPATHLEN + 1];
+    wchar_t buffer[MAXPATHLEN + 1];
 
     if (path[0] == SEP)
         return;
     copy_absolute(buffer, path);
-    strcpy(path, buffer);
+    wcscpy(path, buffer);
 }
 
 /* search_for_prefix requires that argv0_path be no more than MAXPATHLEN
    bytes long.
 */
 static int
-search_for_prefix(char *argv0_path, char *home)
+search_for_prefix(wchar_t *argv0_path, wchar_t *home)
 {
     size_t n;
-    char *vpath;
+    wchar_t *vpath;
 
     /* If PYTHONHOME is set, we believe it unconditionally */
     if (home) {
-        char *delim;
-        strncpy(prefix, home, MAXPATHLEN);
-        delim = strchr(prefix, DELIM);
+        wchar_t *delim;
+        wcsncpy(prefix, home, MAXPATHLEN);
+        delim = wcschr(prefix, DELIM);
         if (delim)
-            *delim = '\0';
+            *delim = L'\0';
         joinpath(prefix, lib_python);
         joinpath(prefix, LANDMARK);
         return 1;
     }
 
     /* Check to see if argv[0] is in the build directory */
-    strcpy(prefix, argv0_path);
-    joinpath(prefix, "Modules/Setup");
+    wcscpy(prefix, argv0_path);
+    joinpath(prefix, L"Modules/Setup");
     if (isfile(prefix)) {
         /* Check VPATH to see if argv0_path is in the build directory. */
-        vpath = VPATH;
-        strcpy(prefix, argv0_path);
+        vpath = L"" VPATH;
+        wcscpy(prefix, argv0_path);
         joinpath(prefix, vpath);
-        joinpath(prefix, "Lib");
+        joinpath(prefix, L"Lib");
         joinpath(prefix, LANDMARK);
         if (ismodule(prefix))
             return -1;
@@ -289,17 +351,17 @@ search_for_prefix(char *argv0_path, char *home)
     /* Search from argv0_path, until root is found */
     copy_absolute(prefix, argv0_path);
     do {
-        n = strlen(prefix);
+        n = wcslen(prefix);
         joinpath(prefix, lib_python);
         joinpath(prefix, LANDMARK);
         if (ismodule(prefix))
             return 1;
-        prefix[n] = '\0';
+        prefix[n] = L'\0';
         reduce(prefix);
     } while (prefix[0]);
 
     /* Look at configure's PREFIX */
-    strncpy(prefix, PREFIX, MAXPATHLEN);
+    wcsncpy(prefix, L"" PREFIX, MAXPATHLEN);
     joinpath(prefix, lib_python);
     joinpath(prefix, LANDMARK);
     if (ismodule(prefix))
@@ -314,26 +376,26 @@ search_for_prefix(char *argv0_path, char *home)
    MAXPATHLEN bytes long.
 */
 static int
-search_for_exec_prefix(char *argv0_path, char *home)
+search_for_exec_prefix(wchar_t *argv0_path, wchar_t *home)
 {
     size_t n;
 
     /* If PYTHONHOME is set, we believe it unconditionally */
     if (home) {
-        char *delim;
-        delim = strchr(home, DELIM);
+        wchar_t *delim;
+        delim = wcschr(home, DELIM);
         if (delim)
-            strncpy(exec_prefix, delim+1, MAXPATHLEN);
+            wcsncpy(exec_prefix, delim+1, MAXPATHLEN);
         else
-            strncpy(exec_prefix, home, MAXPATHLEN);
+            wcsncpy(exec_prefix, home, MAXPATHLEN);
         joinpath(exec_prefix, lib_python);
-        joinpath(exec_prefix, "lib-dynload");
+        joinpath(exec_prefix, L"lib-dynload");
         return 1;
     }
 
     /* Check to see if argv[0] is in the build directory */
-    strcpy(exec_prefix, argv0_path);
-    joinpath(exec_prefix, "Modules/Setup");
+    wcscpy(exec_prefix, argv0_path);
+    joinpath(exec_prefix, L"Modules/Setup");
     if (isfile(exec_prefix)) {
         reduce(exec_prefix);
         return -1;
@@ -342,19 +404,19 @@ search_for_exec_prefix(char *argv0_path, char *home)
     /* Search from argv0_path, until root is found */
     copy_absolute(exec_prefix, argv0_path);
     do {
-        n = strlen(exec_prefix);
+        n = wcslen(exec_prefix);
         joinpath(exec_prefix, lib_python);
-        joinpath(exec_prefix, "lib-dynload");
+        joinpath(exec_prefix, L"lib-dynload");
         if (isdir(exec_prefix))
             return 1;
-        exec_prefix[n] = '\0';
+        exec_prefix[n] = L'\0';
         reduce(exec_prefix);
     } while (exec_prefix[0]);
 
     /* Look at configure's EXEC_PREFIX */
-    strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN);
+    wcsncpy(exec_prefix, L"" EXEC_PREFIX, MAXPATHLEN);
     joinpath(exec_prefix, lib_python);
-    joinpath(exec_prefix, "lib-dynload");
+    joinpath(exec_prefix, L"lib-dynload");
     if (isdir(exec_prefix))
         return 1;
 
@@ -366,22 +428,25 @@ search_for_exec_prefix(char *argv0_path, char *home)
 static void
 calculate_path(void)
 {
-    extern char *Py_GetProgramName(void);
-
-    static char delimiter[2] = {DELIM, '\0'};
-    static char separator[2] = {SEP, '\0'};
-    char *pythonpath = PYTHONPATH;
-    char *rtpypath = Py_GETENV("PYTHONPATH");
-    char *home = Py_GetPythonHome();
-    char *path = getenv("PATH");
-    char *prog = Py_GetProgramName();
-    char argv0_path[MAXPATHLEN+1];
-    char zip_path[MAXPATHLEN+1];
+    extern wchar_t *Py_GetProgramName(void);
+
+    static wchar_t delimiter[2] = {DELIM, '\0'};
+    static wchar_t separator[2] = {SEP, '\0'};
+    wchar_t *pythonpath = L"" PYTHONPATH;
+    char *_rtpypath = Py_GETENV("PYTHONPATH"); /* XXX use wide version on Windows */
+    wchar_t rtpypath[MAXPATHLEN+1];
+    wchar_t *home = Py_GetPythonHome();
+    char *_path = getenv("PATH");
+    wchar_t wpath[MAXPATHLEN+1];
+    wchar_t *path = NULL;
+    wchar_t *prog = Py_GetProgramName();
+    wchar_t argv0_path[MAXPATHLEN+1];
+    wchar_t zip_path[MAXPATHLEN+1];
     int pfound, efound; /* 1 if found; -1 if found build directory */
-    char *buf;
+    wchar_t *buf;
     size_t bufsz;
     size_t prefixsz;
-    char *defpath = pythonpath;
+    wchar_t *defpath = pythonpath;
 #ifdef WITH_NEXT_FRAMEWORK
     NSModule pythonModule;
 #endif
@@ -393,13 +458,22 @@ calculate_path(void)
 #endif
 #endif
 
+    if (_path) {
+           size_t r = mbstowcs(wpath, _path, MAXPATHLEN+1);
+           path = wpath;
+           if (r == (size_t)-1 || r > MAXPATHLEN) {
+                   /* Could not convert PATH, or it's too long. */
+                   path = NULL;
+           }
+    }
+
        /* If there is no slash in the argv0 path, then we have to
         * assume python is on the user's $PATH, since there's no
         * other way to find a directory to start the search from.  If
         * $PATH isn't exported, you lose.
         */
-       if (strchr(prog, SEP))
-               strncpy(progpath, prog, MAXPATHLEN);
+       if (wcschr(prog, SEP))
+               wcsncpy(progpath, prog, MAXPATHLEN);
 #ifdef __APPLE__
      /* On Mac OS X, if a script uses an interpreter of the form
       * "#!/opt/python2.3/bin/python", the kernel only passes "python"
@@ -416,24 +490,24 @@ calculate_path(void)
 #endif /* __APPLE__ */
        else if (path) {
                while (1) {
-                       char *delim = strchr(path, DELIM);
+                       wchar_t *delim = wcschr(path, DELIM);
 
                        if (delim) {
                                size_t len = delim - path;
                                if (len > MAXPATHLEN)
                                        len = MAXPATHLEN;
-                               strncpy(progpath, path, len);
+                               wcsncpy(progpath, path, len);
                                *(progpath + len) = '\0';
                        }
                        else
-                               strncpy(progpath, path, MAXPATHLEN);
+                               wcsncpy(progpath, path, MAXPATHLEN);
 
                        joinpath(progpath, prog);
                        if (isxfile(progpath))
                                break;
 
                        if (!delim) {
-                               progpath[0] = '\0';
+                               progpath[0] = L'\0';
                                break;
                        }
                        path = delim + 1;
@@ -443,7 +517,7 @@ calculate_path(void)
                progpath[0] = '\0';
        if (progpath[0] != SEP)
                absolutize(progpath);
-       strncpy(argv0_path, progpath, MAXPATHLEN);
+       wcsncpy(argv0_path, progpath, MAXPATHLEN);
        argv0_path[MAXPATHLEN] = '\0';
 
 #ifdef WITH_NEXT_FRAMEWORK
@@ -454,7 +528,7 @@ calculate_path(void)
        */
     pythonModule = NSModuleForSymbol(NSLookupAndBindSymbol("_Py_Initialize"));
     /* Use dylib functions to find out where the framework was loaded from */
-    buf = (char *)NSLibraryNameForModule(pythonModule);
+    buf = (wchar_t *)NSLibraryNameForModule(pythonModule);
     if (buf != NULL) {
         /* We're in a framework. */
         /* See if we might be in the build directory. The framework in the
@@ -464,39 +538,39 @@ calculate_path(void)
         ** be running the interpreter in the build directory, so we use the
         ** build-directory-specific logic to find Lib and such.
         */
-        strncpy(argv0_path, buf, MAXPATHLEN);
+        wcsncpy(argv0_path, buf, MAXPATHLEN);
         reduce(argv0_path);
         joinpath(argv0_path, lib_python);
         joinpath(argv0_path, LANDMARK);
         if (!ismodule(argv0_path)) {
                 /* We are in the build directory so use the name of the
                    executable - we know that the absolute path is passed */
-                strncpy(argv0_path, prog, MAXPATHLEN);
+                wcsncpy(argv0_path, prog, MAXPATHLEN);
         }
         else {
                 /* Use the location of the library as the progpath */
-                strncpy(argv0_path, buf, MAXPATHLEN);
+                wcsncpy(argv0_path, buf, MAXPATHLEN);
         }
     }
 #endif
 
 #if HAVE_READLINK
     {
-        char tmpbuffer[MAXPATHLEN+1];
-        int linklen = readlink(progpath, tmpbuffer, MAXPATHLEN);
+        wchar_t tmpbuffer[MAXPATHLEN+1];
+        int linklen = _Py_wreadlink(progpath, tmpbuffer, MAXPATHLEN);
         while (linklen != -1) {
             /* It's not null terminated! */
             tmpbuffer[linklen] = '\0';
             if (tmpbuffer[0] == SEP)
                 /* tmpbuffer should never be longer than MAXPATHLEN,
                    but extra check does not hurt */
-                strncpy(argv0_path, tmpbuffer, MAXPATHLEN);
+                wcsncpy(argv0_path, tmpbuffer, MAXPATHLEN);
             else {
                 /* Interpret relative to progpath */
                 reduce(argv0_path);
                 joinpath(argv0_path, tmpbuffer);
             }
-            linklen = readlink(argv0_path, tmpbuffer, MAXPATHLEN);
+            linklen = _Py_wreadlink(argv0_path, tmpbuffer, MAXPATHLEN);
         }
     }
 #endif /* HAVE_READLINK */
@@ -510,22 +584,22 @@ calculate_path(void)
         if (!Py_FrozenFlag)
             fprintf(stderr,
                 "Could not find platform independent libraries <prefix>\n");
-        strncpy(prefix, PREFIX, MAXPATHLEN);
+        wcsncpy(prefix, L"" PREFIX, MAXPATHLEN);
         joinpath(prefix, lib_python);
     }
     else
         reduce(prefix);
 
-    strncpy(zip_path, prefix, MAXPATHLEN);
-    zip_path[MAXPATHLEN] = '\0';
+    wcsncpy(zip_path, prefix, MAXPATHLEN);
+    zip_path[MAXPATHLEN] = L'\0';
     if (pfound > 0) { /* Use the reduced prefix returned by Py_GetPrefix() */
         reduce(zip_path);
         reduce(zip_path);
     }
     else
-        strncpy(zip_path, PREFIX, MAXPATHLEN);
-    joinpath(zip_path, "lib/python00.zip");
-    bufsz = strlen(zip_path);  /* Replace "00" with version */
+        wcsncpy(zip_path, L"" PREFIX, MAXPATHLEN);
+    joinpath(zip_path, L"lib/python00.zip");
+    bufsz = wcslen(zip_path);  /* Replace "00" with version */
     zip_path[bufsz - 6] = VERSION[0];
     zip_path[bufsz - 5] = VERSION[2];
 
@@ -533,8 +607,8 @@ calculate_path(void)
         if (!Py_FrozenFlag)
             fprintf(stderr,
                 "Could not find platform dependent libraries <exec_prefix>\n");
-        strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN);
-        joinpath(exec_prefix, "lib/lib-dynload");
+        wcsncpy(exec_prefix, L"" EXEC_PREFIX, MAXPATHLEN);
+        joinpath(exec_prefix, L"lib/lib-dynload");
     }
     /* If we found EXEC_PREFIX do *not* reduce it!  (Yet.) */
 
@@ -546,13 +620,19 @@ calculate_path(void)
      */
     bufsz = 0;
 
-    if (rtpypath)
-        bufsz += strlen(rtpypath) + 1;
+    if (_rtpypath) {
+       size_t s = mbstowcs(rtpypath, _rtpypath, sizeof(rtpypath)/sizeof(wchar_t));
+       if (s == (size_t)-1 || s >=sizeof(rtpypath))
+           /* XXX deal with errors more gracefully */
+           _rtpypath = NULL;
+       if (_rtpypath)
+           bufsz += wcslen(rtpypath) + 1;
+    }
 
-    prefixsz = strlen(prefix) + 1;
+    prefixsz = wcslen(prefix) + 1;
 
     while (1) {
-        char *delim = strchr(defpath, DELIM);
+        wchar_t *delim = wcschr(defpath, DELIM);
 
         if (defpath[0] != SEP)
             /* Paths are relative to prefix */
@@ -561,65 +641,65 @@ calculate_path(void)
         if (delim)
             bufsz += delim - defpath + 1;
         else {
-            bufsz += strlen(defpath) + 1;
+            bufsz += wcslen(defpath) + 1;
             break;
         }
         defpath = delim + 1;
     }
 
-    bufsz += strlen(zip_path) + 1;
-    bufsz += strlen(exec_prefix) + 1;
+    bufsz += wcslen(zip_path) + 1;
+    bufsz += wcslen(exec_prefix) + 1;
 
     /* This is the only malloc call in this file */
-    buf = (char *)PyMem_Malloc(bufsz);
+    buf = (wchar_t *)PyMem_Malloc(bufsz*sizeof(wchar_t));
 
     if (buf == NULL) {
         /* We can't exit, so print a warning and limp along */
         fprintf(stderr, "Not enough memory for dynamic PYTHONPATH.\n");
         fprintf(stderr, "Using default static PYTHONPATH.\n");
-        module_search_path = PYTHONPATH;
+        module_search_path = L"" PYTHONPATH;
     }
     else {
         /* Run-time value of $PYTHONPATH goes first */
-        if (rtpypath) {
-            strcpy(buf, rtpypath);
-            strcat(buf, delimiter);
+        if (_rtpypath) {
+            wcscpy(buf, rtpypath);
+            wcscat(buf, delimiter);
         }
         else
             buf[0] = '\0';
 
         /* Next is the default zip path */
-        strcat(buf, zip_path);
-        strcat(buf, delimiter);
+        wcscat(buf, zip_path);
+        wcscat(buf, delimiter);
 
         /* Next goes merge of compile-time $PYTHONPATH with
          * dynamically located prefix.
          */
         defpath = pythonpath;
         while (1) {
-            char *delim = strchr(defpath, DELIM);
+            wchar_t *delim = wcschr(defpath, DELIM);
 
             if (defpath[0] != SEP) {
-                strcat(buf, prefix);
-                strcat(buf, separator);
+                wcscat(buf, prefix);
+                wcscat(buf, separator);
             }
 
             if (delim) {
                 size_t len = delim - defpath + 1;
-                size_t end = strlen(buf) + len;
-                strncat(buf, defpath, len);
+                size_t end = wcslen(buf) + len;
+                wcsncat(buf, defpath, len);
                 *(buf + end) = '\0';
             }
             else {
-                strcat(buf, defpath);
+                wcscat(buf, defpath);
                 break;
             }
             defpath = delim + 1;
         }
-        strcat(buf, delimiter);
+        wcscat(buf, delimiter);
 
         /* Finally, on goes the directory for dynamic-load modules */
-        strcat(buf, exec_prefix);
+        wcscat(buf, exec_prefix);
 
         /* And publish the results */
         module_search_path = buf;
@@ -636,26 +716,26 @@ calculate_path(void)
        /* The prefix is the root directory, but reduce() chopped
         * off the "/". */
        if (!prefix[0])
-               strcpy(prefix, separator);
+               wcscpy(prefix, separator);
     }
     else
-        strncpy(prefix, PREFIX, MAXPATHLEN);
+        wcsncpy(prefix, L"" PREFIX, MAXPATHLEN);
 
     if (efound > 0) {
         reduce(exec_prefix);
         reduce(exec_prefix);
         reduce(exec_prefix);
        if (!exec_prefix[0])
-               strcpy(exec_prefix, separator);
+               wcscpy(exec_prefix, separator);
     }
     else
-        strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN);
+        wcsncpy(exec_prefix, L"" EXEC_PREFIX, MAXPATHLEN);
 }
 
 
 /* External interface */
 
-char *
+wchar_t *
 Py_GetPath(void)
 {
     if (!module_search_path)
@@ -663,7 +743,7 @@ Py_GetPath(void)
     return module_search_path;
 }
 
-char *
+wchar_t *
 Py_GetPrefix(void)
 {
     if (!module_search_path)
@@ -671,7 +751,7 @@ Py_GetPrefix(void)
     return prefix;
 }
 
-char *
+wchar_t *
 Py_GetExecPrefix(void)
 {
     if (!module_search_path)
@@ -679,7 +759,7 @@ Py_GetExecPrefix(void)
     return exec_prefix;
 }
 
-char *
+wchar_t *
 Py_GetProgramFullPath(void)
 {
     if (!module_search_path)
index 9f0b01c99bc9f37795543e798a7ba420a6c84f85..81a3d46d3f3543af0ce409e762c8c0ddcd2a575f 100644 (file)
@@ -12,6 +12,7 @@
 #include <windows.h>
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
+#define PATH_MAX MAXPATHLEN
 #endif
 #endif
 
@@ -40,17 +41,17 @@ extern "C" {
 #endif
 
 /* For Py_GetArgcArgv(); set by main() */
-static char **orig_argv;
+static wchar_t **orig_argv;
 static int  orig_argc;
 
 /* command line options */
-#define BASE_OPTS "bBc:dEhim:OStuvVW:xX?"
+#define BASE_OPTS L"bBc:dEhim:OStuvVW:xX?"
 
 #define PROGRAM_OPTS BASE_OPTS
 
 /* Short usage message (with %s for argv0) */
 static char *usage_line =
-"usage: %s [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
+"usage: %ls [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
 
 /* Long usage message, split into parts < 512 bytes */
 static char *usage_1 = "\
@@ -96,9 +97,30 @@ PYTHONHOME   : alternate <prefix> directory (or <prefix>%c<exec_prefix>).\n\
 PYTHONCASEOK : ignore case in 'import' statements (Windows).\n\
 ";
 
+#ifndef MS_WINDOWS
+static FILE*
+_wfopen(const wchar_t *path, const wchar_t *mode)
+{
+       char cpath[PATH_MAX];
+       char cmode[10];
+       size_t r;
+       r = wcstombs(cpath, path, PATH_MAX);
+       if (r == (size_t)-1 || r >= PATH_MAX) {
+               errno = EINVAL;
+               return NULL;
+       }
+       r = wcstombs(cmode, mode, 10);
+       if (r == (size_t)-1 || r >= 10) {
+               errno = EINVAL;
+               return NULL;
+       }
+       return fopen(cpath, cmode);
+}
+#endif
+
 
 static int
-usage(int exitcode, char* program)
+usage(int exitcode, wchar_t* program)
 {
        FILE *f = exitcode ? stderr : stdout;
 
@@ -187,11 +209,11 @@ static int RunModule(char *module, int set_argv0)
        return 0;
 }
 
-static int RunMainFromImporter(char *filename)
+static int RunMainFromImporter(wchar_t *filename)
 {
        PyObject *argv0 = NULL, *importer = NULL;
 
-       if ((argv0 = PyUnicode_DecodeFSDefault(filename)) &&
+       if ((argv0 = PyUnicode_FromWideChar(filename,wcslen(filename))) &&
            (importer = PyImport_GetImporter(argv0)) &&
            (importer->ob_type != &PyNullImporter_Type))
        {
@@ -249,12 +271,12 @@ WaitForThreadShutdown(void)
 /* Main program */
 
 int
-Py_Main(int argc, char **argv)
+Py_Main(int argc, wchar_t **argv)
 {
        int c;
        int sts;
        char *command = NULL;
-       char *filename = NULL;
+       wchar_t *filename = NULL;
        char *module = NULL;
        FILE *fp = stdin;
        char *p;
@@ -275,14 +297,19 @@ Py_Main(int argc, char **argv)
 
        while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
                if (c == 'c') {
+                       size_t r1 = wcslen(_PyOS_optarg) + 2;
+                       size_t r2;
                        /* -c is the last option; following arguments
                           that look like options are left for the
                           command to interpret. */
-                       command = (char *)malloc(strlen(_PyOS_optarg) + 2);
+                       command = (char *)malloc(r1);
                        if (command == NULL)
                                Py_FatalError(
                                   "not enough memory to copy -c argument");
-                       strcpy(command, _PyOS_optarg);
+                       r2 = wcstombs(command, _PyOS_optarg, r1);
+                       if (r2 > r1-2)
+                               Py_FatalError(
+                                   "not enough memory to copy -c argument");
                        strcat(command, "\n");
                        break;
                }
@@ -291,11 +318,16 @@ Py_Main(int argc, char **argv)
                        /* -m is the last option; following arguments
                           that look like options are left for the
                           module to interpret. */
-                       module = (char *)malloc(strlen(_PyOS_optarg) + 2);
+                       size_t r1 = wcslen(_PyOS_optarg) + 1;
+                       size_t r2;
+                       module = (char *)malloc(r1);
                        if (module == NULL)
                                Py_FatalError(
                                   "not enough memory to copy -m argument");
-                       strcpy(module, _PyOS_optarg);
+                       r2 = wcstombs(module, _PyOS_optarg, r1);
+                       if (r2 >= r1)
+                               Py_FatalError(
+                                  "not enough memory to copy -m argument");
                        break;
                }
 
@@ -355,7 +387,7 @@ Py_Main(int argc, char **argv)
                        version++;
                        break;
 
-               case 'W':
+               case 'W': 
                        PySys_AddWarnOption(_PyOS_optarg);
                        break;
 
@@ -384,7 +416,7 @@ Py_Main(int argc, char **argv)
                unbuffered = 1;
 
        if (command == NULL && module == NULL && _PyOS_optind < argc &&
-           strcmp(argv[_PyOS_optind], "-") != 0)
+           wcscmp(argv[_PyOS_optind], L"-") != 0)
        {
 #ifdef __VMS
                filename = decc$translate_vms(argv[_PyOS_optind]);
@@ -462,14 +494,14 @@ Py_Main(int argc, char **argv)
        if (command != NULL) {
                /* Backup _PyOS_optind and force sys.argv[0] = '-c' */
                _PyOS_optind--;
-               argv[_PyOS_optind] = "-c";
+               argv[_PyOS_optind] = L"-c";
        }
 
        if (module != NULL) {
                /* Backup _PyOS_optind and force sys.argv[0] = '-c'
                   so that PySys_SetArgv correctly sets sys.path[0] to ''*/
                _PyOS_optind--;
-               argv[_PyOS_optind] = "-c";
+               argv[_PyOS_optind] = L"-c";
        }
 
        PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
@@ -506,8 +538,8 @@ Py_Main(int argc, char **argv)
                }
 
                if (sts==-1 && filename!=NULL) {
-                       if ((fp = fopen(filename, "r")) == NULL) {
-                               fprintf(stderr, "%s: can't open file '%s': [Errno %d] %s\n",
+                       if ((fp = _wfopen(filename, L"r")) == NULL) {
+                               fprintf(stderr, "%s: can't open file '%ls': [Errno %d] %s\n",
                                        argv[0], filename, errno, strerror(errno));
 
                                return 2;
@@ -528,7 +560,7 @@ Py_Main(int argc, char **argv)
                                struct stat sb;
                                if (fstat(fileno(fp), &sb) == 0 &&
                                    S_ISDIR(sb.st_mode)) {
-                                       fprintf(stderr, "%s: '%s' is a directory, cannot continue\n", argv[0], filename);
+                                       fprintf(stderr, "%ls: '%ls' is a directory, cannot continue\n", argv[0], filename);
                                        fclose(fp);
                                        return 1;
                                }
@@ -536,9 +568,17 @@ Py_Main(int argc, char **argv)
                }
 
                if (sts==-1) {
+                       char cfilename[PATH_MAX];
+                       char *p_cfilename = "<stdin>";
+                       if (filename) {
+                               size_t r = wcstombs(cfilename, filename, PATH_MAX);
+                               p_cfilename = cfilename;
+                               if (r == (size_t)-1 || r >= PATH_MAX)
+                                       p_cfilename = "<decoding error>";
+                       }
                        sts = PyRun_AnyFileExFlags(
                                fp,
-                               filename == NULL ? "<stdin>" : filename,
+                               p_cfilename,
                                filename != NULL, &cf) != 0;
                }
                
@@ -589,7 +629,7 @@ Py_Main(int argc, char **argv)
    This is rare, but it is needed by the secureware extension. */
 
 void
-Py_GetArgcArgv(int *argc, char ***argv)
+Py_GetArgcArgv(int *argc, wchar_t ***argv)
 {
        *argc = orig_argc;
        *argv = orig_argv;
index 2739b8b11098ee799ff86b1a3d6c3f51ab8fc899..c1de64a2a4dd9c9f75bad638d0c5e375e1a14e3a 100644 (file)
@@ -1,14 +1,27 @@
 /* Minimal main program -- everything is loaded from the library */
 
 #include "Python.h"
+#include <locale.h>
 
 #ifdef __FreeBSD__
 #include <floatingpoint.h>
 #endif
 
+#ifdef MS_WINDOWS
+int
+wmain(int argc, wchar_t **argv)
+{
+       return Py_Main(argc, argv);
+}
+#else
 int
 main(int argc, char **argv)
 {
+       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);
+       int i, res;
+       char *oldloc;
        /* 754 requires that FP exceptions run in "no stop" mode by default,
         * and until C vendors implement C99's ways to control FP exceptions,
         * Python requires non-stop mode.  Alas, some platforms enable FP
@@ -20,5 +33,33 @@ main(int argc, char **argv)
        m = fpgetmask();
        fpsetmask(m & ~FP_X_OFL);
 #endif
-       return Py_Main(argc, argv);
+       if (!argv_copy || !argv_copy2) {
+               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);
+       res = Py_Main(argc, argv_copy);
+       for (i = 0; i < argc; i++) {
+               PyMem_Free(argv_copy2[i]);
+       }
+       PyMem_Free(argv_copy);
+       PyMem_Free(argv_copy2);
+       return res;
 }
+#endif
index 60cbffa59f43cf0d694e91c67d40a064bbca1fb7..29ca08c4bfc6a1ddaf8a12b4e47af8ae520cc80b 100644 (file)
@@ -553,10 +553,16 @@ PyObject *PyUnicode_FromWideChar(register const wchar_t *w,
     PyUnicodeObject *unicode;
 
     if (w == NULL) {
+        if (size == 0)
+            return PyUnicode_FromStringAndSize(NULL, 0);
        PyErr_BadInternalCall();
        return NULL;
     }
 
+    if (size == -1) {
+        size = wcslen(w);
+    }
+
     unicode = _PyUnicode_New(size);
     if (!unicode)
         return NULL;
index 2cdd0cb695d4f46add384e3f13042e4c929808b4..c334a03d2ebe3da4ab6b55a1539ce7d34cd6fa2f 100644 (file)
@@ -12,5 +12,5 @@ int WINAPI WinMain(
     int nCmdShow              /* show state of window */
 )
 {
-    return Py_Main(__argc, __argv);
+    return Py_Main(__argc, __wargv);
 }
index e62b936f2d360c86b7206bfcb512d2229f22dce3..3a250be612b9181af4c840aca57276f2153ab91e 100644 (file)
 
 #include "Python.h"
 #include "osdefs.h"
+#include <wchar.h>
 
 #ifdef MS_WINDOWS
 #include <windows.h>
-#include <tchar.h>
 #endif
 
 #ifdef HAVE_SYS_TYPES_H
  */
 
 #ifndef LANDMARK
-#define LANDMARK "lib\\os.py"
+#define LANDMARK L"lib\\os.py"
 #endif
 
-static char prefix[MAXPATHLEN+1];
-static char progpath[MAXPATHLEN+1];
-static char dllpath[MAXPATHLEN+1];
-static char *module_search_path = NULL;
+static wchar_t prefix[MAXPATHLEN+1];
+static wchar_t progpath[MAXPATHLEN+1];
+static wchar_t dllpath[MAXPATHLEN+1];
+static wchar_t *module_search_path = NULL;
 
 
 static int
-is_sep(char ch)        /* determine if "ch" is a separator character */
+is_sep(wchar_t ch)     /* determine if "ch" is a separator character */
 {
 #ifdef ALTSEP
        return ch == SEP || ch == ALTSEP;
@@ -105,9 +105,9 @@ is_sep(char ch)     /* determine if "ch" is a separator character */
    beyond existing terminator.
 */
 static void
-reduce(char *dir)
+reduce(wchar_t *dir)
 {
-       size_t i = strlen(dir);
+       size_t i = wcslen(dir);
        while (i > 0 && !is_sep(dir[i]))
                --i;
        dir[i] = '\0';
@@ -115,24 +115,24 @@ reduce(char *dir)
        
 
 static int
-exists(char *filename)
+exists(wchar_t *filename)
 {
-       struct stat buf;
-       return stat(filename, &buf) == 0;
+       struct _stat64 buf;
+       return _wstat64(filename, &buf) == 0;
 }
 
 /* Assumes 'filename' MAXPATHLEN+1 bytes long - 
    may extend 'filename' by one character.
 */
 static int
-ismodule(char *filename)       /* Is module -- check for .pyc/.pyo too */
+ismodule(wchar_t *filename)    /* Is module -- check for .pyc/.pyo too */
 {
        if (exists(filename))
                return 1;
 
        /* Check for the compiled version of prefix. */
-       if (strlen(filename) < MAXPATHLEN) {
-               strcat(filename, Py_OptimizeFlag ? "o" : "c");
+       if (wcslen(filename) < MAXPATHLEN) {
+               wcscat(filename, Py_OptimizeFlag ? L"o" : L"c");
                if (exists(filename))
                        return 1;
        }
@@ -149,22 +149,22 @@ ismodule(char *filename)  /* Is module -- check for .pyc/.pyo too */
    stuff as fits will be appended.
 */
 static void
-join(char *buffer, char *stuff)
+join(wchar_t *buffer, wchar_t *stuff)
 {
        size_t n, k;
        if (is_sep(stuff[0]))
                n = 0;
        else {
-               n = strlen(buffer);
+               n = wcslen(buffer);
                if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN)
                        buffer[n++] = SEP;
        }
        if (n > MAXPATHLEN)
                Py_FatalError("buffer overflow in getpathp.c's joinpath()");
-       k = strlen(stuff);
+       k = wcslen(stuff);
        if (n + k > MAXPATHLEN)
                k = MAXPATHLEN - n;
-       strncpy(buffer+n, stuff, k);
+       wcsncpy(buffer+n, stuff, k);
        buffer[n+k] = '\0';
 }
 
@@ -173,12 +173,12 @@ join(char *buffer, char *stuff)
    'landmark' can not overflow prefix if too long.
 */
 static int
-gotlandmark(char *landmark)
+gotlandmark(wchar_t *landmark)
 {
        int ok;
        Py_ssize_t n;
 
-       n = strlen(prefix);
+       n = wcslen(prefix);
        join(prefix, landmark);
        ok = ismodule(prefix);
        prefix[n] = '\0';
@@ -188,10 +188,10 @@ gotlandmark(char *landmark)
 /* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd. 
    assumption provided by only caller, calculate_path() */
 static int
-search_for_prefix(char *argv0_path, char *landmark)
+search_for_prefix(wchar_t *argv0_path, wchar_t *landmark)
 {
        /* Search from argv0_path, until landmark is found */
-       strcpy(prefix, argv0_path);
+       wcscpy(prefix, argv0_path);
        do {
                if (gotlandmark(landmark))
                        return 1;
@@ -219,39 +219,39 @@ extern const char *PyWin_DLLVersionString;
    in advance.  It could be simplied now Win16/Win32s is dead!
 */
 
-static char *
+static wchar_t *
 getpythonregpath(HKEY keyBase, int skipcore)
 {
        HKEY newKey = 0;
        DWORD dataSize = 0;
        DWORD numKeys = 0;
        LONG rc;
-       char *retval = NULL;
-       TCHAR *dataBuf = NULL;
-       static const TCHAR keyPrefix[] = _T("Software\\Python\\PythonCore\\");
-       static const TCHAR keySuffix[] = _T("\\PythonPath");
+       wchar_t *retval = NULL;
+       WCHAR *dataBuf = NULL;
+       static const WCHAR keyPrefix[] = L"Software\\Python\\PythonCore\\";
+       static const WCHAR keySuffix[] = L"\\PythonPath";
        size_t versionLen;
        DWORD index;
-       TCHAR *keyBuf = NULL;
-       TCHAR *keyBufPtr;
-       TCHAR **ppPaths = NULL;
-
+       WCHAR *keyBuf = NULL;
+       WCHAR *keyBufPtr;
+       WCHAR **ppPaths = NULL;
+       
        /* Tried to use sysget("winver") but here is too early :-( */
-       versionLen = _tcslen(PyWin_DLLVersionString);
+       versionLen = strlen(PyWin_DLLVersionString);
        /* Space for all the chars, plus one \0 */
        keyBuf = keyBufPtr = malloc(sizeof(keyPrefix) + 
-                                   sizeof(TCHAR)*(versionLen-1) + 
+                                   sizeof(WCHAR)*(versionLen-1) + 
                                    sizeof(keySuffix));
        if (keyBuf==NULL) goto done;
 
-       memcpy(keyBufPtr, keyPrefix, sizeof(keyPrefix)-sizeof(TCHAR));
-       keyBufPtr += sizeof(keyPrefix)/sizeof(TCHAR) - 1;
-       memcpy(keyBufPtr, PyWin_DLLVersionString, versionLen * sizeof(TCHAR));
+       memcpy(keyBufPtr, keyPrefix, sizeof(keyPrefix)-sizeof(WCHAR));
+       keyBufPtr += sizeof(keyPrefix)/sizeof(WCHAR) - 1;
+       mbstowcs(keyBufPtr, PyWin_DLLVersionString, versionLen);
        keyBufPtr += versionLen;
        /* NULL comes with this one! */
        memcpy(keyBufPtr, keySuffix, sizeof(keySuffix));
        /* Open the root Python key */
-       rc=RegOpenKeyEx(keyBase,
+       rc=RegOpenKeyExW(keyBase,
                        keyBuf, /* subkey */
                        0, /* reserved */
                        KEY_READ,
@@ -265,31 +265,31 @@ getpythonregpath(HKEY keyBase, int skipcore)
        /* Allocate a temp array of char buffers, so we only need to loop 
           reading the registry once
        */
-       ppPaths = malloc( sizeof(TCHAR *) * numKeys );
+       ppPaths = malloc( sizeof(WCHAR *) * numKeys );
        if (ppPaths==NULL) goto done;
-       memset(ppPaths, 0, sizeof(TCHAR *) * numKeys);
+       memset(ppPaths, 0, sizeof(WCHAR *) * numKeys);
        /* Loop over all subkeys, allocating a temp sub-buffer. */
        for(index=0;index<numKeys;index++) {
-               TCHAR keyBuf[MAX_PATH+1];
+               WCHAR keyBuf[MAX_PATH+1];
                HKEY subKey = 0;
                DWORD reqdSize = MAX_PATH+1;
                /* Get the sub-key name */
-               DWORD rc = RegEnumKeyEx(newKey, index, keyBuf, &reqdSize,
-                                       NULL, NULL, NULL, NULL );
+               DWORD rc = RegEnumKeyExW(newKey, index, keyBuf, &reqdSize,
+                                        NULL, NULL, NULL, NULL );
                if (rc!=ERROR_SUCCESS) goto done;
                /* Open the sub-key */
-               rc=RegOpenKeyEx(newKey,
+               rc=RegOpenKeyExW(newKey,
                                                keyBuf, /* subkey */
                                                0, /* reserved */
                                                KEY_READ,
                                                &subKey);
                if (rc!=ERROR_SUCCESS) goto done;
                /* Find the value of the buffer size, malloc, then read it */
-               RegQueryValueEx(subKey, NULL, 0, NULL, NULL, &reqdSize);
+               RegQueryValueExW(subKey, NULL, 0, NULL, NULL, &reqdSize);
                if (reqdSize) {
                        ppPaths[index] = malloc(reqdSize);
                        if (ppPaths[index]) {
-                               RegQueryValueEx(subKey, NULL, 0, NULL, 
+                               RegQueryValueExW(subKey, NULL, 0, NULL, 
                                                (LPBYTE)ppPaths[index], 
                                                &reqdSize);
                                dataSize += reqdSize + 1; /* 1 for the ";" */
@@ -302,19 +302,19 @@ getpythonregpath(HKEY keyBase, int skipcore)
        if (dataSize == 0) goto done;
 
        /* original datasize from RegQueryInfo doesn't include the \0 */
-       dataBuf = malloc((dataSize+1) * sizeof(TCHAR));
+       dataBuf = malloc((dataSize+1) * sizeof(WCHAR));
        if (dataBuf) {
-               TCHAR *szCur = dataBuf;
+               WCHAR *szCur = dataBuf;
                DWORD reqdSize = dataSize;
                /* Copy our collected strings */
                for (index=0;index<numKeys;index++) {
                        if (index > 0) {
-                               *(szCur++) = _T(';');
+                               *(szCur++) = L';';
                                dataSize--;
                        }
                        if (ppPaths[index]) {
-                               Py_ssize_t len = _tcslen(ppPaths[index]);
-                               _tcsncpy(szCur, ppPaths[index], len);
+                               Py_ssize_t len = wcslen(ppPaths[index]);
+                               wcsncpy(szCur, ppPaths[index], len);
                                szCur += len;
                                assert(dataSize > (DWORD)len);
                                dataSize -= (DWORD)len;
@@ -325,30 +325,17 @@ getpythonregpath(HKEY keyBase, int skipcore)
                else {
                        /* If we have no values, we dont need a ';' */
                        if (numKeys) {
-                               *(szCur++) = _T(';');
+                               *(szCur++) = L';';
                                dataSize--;
                        }
                        /* Now append the core path entries - 
                           this will include the NULL 
                        */
-                       rc = RegQueryValueEx(newKey, NULL, 0, NULL, 
-                                            (LPBYTE)szCur, &dataSize);
+                       rc = RegQueryValueExW(newKey, NULL, 0, NULL, 
+                                             (LPBYTE)szCur, &dataSize);
                }
-               /* And set the result - caller must free 
-                  If MBCS, it is fine as is.  If Unicode, allocate new
-                  buffer and convert.
-               */
-#ifdef UNICODE
-               retval = (char *)malloc(reqdSize+1);
-               if (retval)
-                       WideCharToMultiByte(CP_ACP, 0, 
-                                       dataBuf, -1, /* source */ 
-                                       retval, reqdSize+1, /* dest */
-                                       NULL, NULL);
-               free(dataBuf);
-#else
+               /* And set the result - caller must free */
                retval = dataBuf;
-#endif
        }
 done:
        /* Loop freeing my temp buffers */
@@ -368,45 +355,21 @@ done:
 static void
 get_progpath(void)
 {
-       extern char *Py_GetProgramName(void);
-       char *path = getenv("PATH");
-       char *prog = Py_GetProgramName();
+       extern wchar_t *Py_GetProgramName(void);
+       wchar_t *path = _wgetenv(L"PATH");
+       wchar_t *prog = Py_GetProgramName();
 
 #ifdef MS_WINDOWS
        extern HANDLE PyWin_DLLhModule;
-#ifdef UNICODE
-       WCHAR wprogpath[MAXPATHLEN+1];
-       /* Windows documents that GetModuleFileName() will "truncate",
-          but makes no mention of the null terminator.  Play it safe.
-          PLUS Windows itself defines MAX_PATH as the same, but anyway...
-       */
-       wprogpath[MAXPATHLEN]=_T('\0');
-       if (PyWin_DLLhModule &&
-           GetModuleFileName(PyWin_DLLhModule, wprogpath, MAXPATHLEN)) {
-               WideCharToMultiByte(CP_ACP, 0, 
-                                   wprogpath, -1, 
-                                   dllpath, MAXPATHLEN+1, 
-                                   NULL, NULL);
-       }
-       wprogpath[MAXPATHLEN]=_T('\0');
-       if (GetModuleFileName(NULL, wprogpath, MAXPATHLEN)) {
-               WideCharToMultiByte(CP_ACP, 0, 
-                                   wprogpath, -1, 
-                                   progpath, MAXPATHLEN+1, 
-                                   NULL, NULL);
-               return;
-       }
-#else
        /* static init of progpath ensures final char remains \0 */
        if (PyWin_DLLhModule)
-               if (!GetModuleFileName(PyWin_DLLhModule, dllpath, MAXPATHLEN))
+               if (!GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN))
                        dllpath[0] = 0;
-       if (GetModuleFileName(NULL, progpath, MAXPATHLEN))
+       if (GetModuleFileNameW(NULL, progpath, MAXPATHLEN))
                return;
-#endif
 #endif
        if (prog == NULL || *prog == '\0')
-               prog = "python";
+               prog = L"python";
 
        /* If there is no slash in the argv0 path, then we have to
         * assume python is on the user's $PATH, since there's no
@@ -414,24 +377,24 @@ get_progpath(void)
         * $PATH isn't exported, you lose.
         */
 #ifdef ALTSEP
-       if (strchr(prog, SEP) || strchr(prog, ALTSEP))
+       if (wcschr(prog, SEP) || wcschr(prog, ALTSEP))
 #else
-       if (strchr(prog, SEP))
+       if (wcschr(prog, SEP))
 #endif
-               strncpy(progpath, prog, MAXPATHLEN);
+               wcsncpy(progpath, prog, MAXPATHLEN);
        else if (path) {
                while (1) {
-                       char *delim = strchr(path, DELIM);
+                       wchar_t *delim = wcschr(path, DELIM);
 
                        if (delim) {
                                size_t len = delim - path;
                                /* ensure we can't overwrite buffer */
                                len = min(MAXPATHLEN,len);
-                               strncpy(progpath, path, len);
+                               wcsncpy(progpath, path, len);
                                *(progpath + len) = '\0';
                        }
                        else
-                               strncpy(progpath, path, MAXPATHLEN);
+                               wcsncpy(progpath, path, MAXPATHLEN);
 
                        /* join() is safe for MAXPATHLEN+1 size buffer */
                        join(progpath, prog);
@@ -452,23 +415,31 @@ get_progpath(void)
 static void
 calculate_path(void)
 {
-       char argv0_path[MAXPATHLEN+1];
-       char *buf;
+       wchar_t argv0_path[MAXPATHLEN+1];
+       wchar_t *buf;
        size_t bufsz;
-       char *pythonhome = Py_GetPythonHome();
-       char *envpath = Py_GETENV("PYTHONPATH");
+       wchar_t *pythonhome = Py_GetPythonHome();
+       char *_envpath = Py_GETENV("PYTHONPATH");
+       wchar_t wenvpath[MAXPATHLEN+1];
+       wchar_t *envpath = NULL;
 
 #ifdef MS_WINDOWS
        int skiphome, skipdefault;
-       char *machinepath = NULL;
-       char *userpath = NULL;
-       char zip_path[MAXPATHLEN+1];
+       wchar_t *machinepath = NULL;
+       wchar_t *userpath = NULL;
+       wchar_t zip_path[MAXPATHLEN+1];
        size_t len;
 #endif
+       if (_envpath) {
+               size_t r = mbstowcs(wenvpath, _envpath, MAXPATHLEN+1);
+               envpath = wenvpath;
+               if (r == (size_t)-1 || r >= MAXPATHLEN)
+                       envpath = NULL;
+       }
 
        get_progpath();
        /* progpath guaranteed \0 terminated in MAXPATH+1 bytes. */
-       strcpy(argv0_path, progpath);
+       wcscpy(argv0_path, progpath);
        reduce(argv0_path);
        if (pythonhome == NULL || *pythonhome == '\0') {
                if (search_for_prefix(argv0_path, LANDMARK))
@@ -477,7 +448,7 @@ calculate_path(void)
                        pythonhome = NULL;
        }
        else
-               strncpy(prefix, pythonhome, MAXPATHLEN);
+               wcsncpy(prefix, pythonhome, MAXPATHLEN);
 
        if (envpath && *envpath == '\0')
                envpath = NULL;
@@ -486,11 +457,11 @@ calculate_path(void)
 #ifdef MS_WINDOWS
        /* Calculate zip archive path */
        if (dllpath[0])         /* use name of python DLL */
-               strncpy(zip_path, dllpath, MAXPATHLEN);
+               wcsncpy(zip_path, dllpath, MAXPATHLEN);
        else                    /* use name of executable program */
-               strncpy(zip_path, progpath, MAXPATHLEN);
+               wcsncpy(zip_path, progpath, MAXPATHLEN);
        zip_path[MAXPATHLEN] = '\0';
-       len = strlen(zip_path);
+       len = wcslen(zip_path);
        if (len > 4) {
                zip_path[len-3] = 'z';  /* change ending to "zip" */
                zip_path[len-2] = 'i';
@@ -524,29 +495,29 @@ calculate_path(void)
 
        /* Calculate size of return buffer */
        if (pythonhome != NULL) {
-               char *p;
+               wchar_t *p;
                bufsz = 1;      
                for (p = PYTHONPATH; *p; p++) {
                        if (*p == DELIM)
                                bufsz++; /* number of DELIM plus one */
                }
-               bufsz *= strlen(pythonhome);
+               bufsz *= wcslen(pythonhome);
        }
        else
                bufsz = 0;
-       bufsz += strlen(PYTHONPATH) + 1;
-       bufsz += strlen(argv0_path) + 1;
+       bufsz += wcslen(PYTHONPATH) + 1;
+       bufsz += wcslen(argv0_path) + 1;
 #ifdef MS_WINDOWS
        if (userpath)
-               bufsz += strlen(userpath) + 1;
+               bufsz += wcslen(userpath) + 1;
        if (machinepath)
-               bufsz += strlen(machinepath) + 1;
-       bufsz += strlen(zip_path) + 1;
+               bufsz += wcslen(machinepath) + 1;
+       bufsz += wcslen(zip_path) + 1;
 #endif
        if (envpath != NULL)
-               bufsz += strlen(envpath) + 1;
+               bufsz += wcslen(envpath) + 1;
 
-       module_search_path = buf = malloc(bufsz);
+       module_search_path = buf = malloc(bufsz*sizeof(wchar_t));
        if (buf == NULL) {
                /* We can't exit, so print a warning and limp along */
                fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");
@@ -568,57 +539,57 @@ calculate_path(void)
        }
 
        if (envpath) {
-               strcpy(buf, envpath);
-               buf = strchr(buf, '\0');
+               wcscpy(buf, envpath);
+               buf = wcschr(buf, L'\0');
                *buf++ = DELIM;
        }
 #ifdef MS_WINDOWS
        if (zip_path[0]) {
-               strcpy(buf, zip_path);
-               buf = strchr(buf, '\0');
+               wcscpy(buf, zip_path);
+               buf = wcschr(buf, L'\0');
                *buf++ = DELIM;
        }
        if (userpath) {
-               strcpy(buf, userpath);
-               buf = strchr(buf, '\0');
+               wcscpy(buf, userpath);
+               buf = wcschr(buf, L'\0');
                *buf++ = DELIM;
                free(userpath);
        }
        if (machinepath) {
-               strcpy(buf, machinepath);
-               buf = strchr(buf, '\0');
+               wcscpy(buf, machinepath);
+               buf = wcschr(buf, L'\0');
                *buf++ = DELIM;
                free(machinepath);
        }
        if (pythonhome == NULL) {
                if (!skipdefault) {
-                       strcpy(buf, PYTHONPATH);
-                       buf = strchr(buf, '\0');
+                       wcscpy(buf, PYTHONPATH);
+                       buf = wcschr(buf, L'\0');
                }
        }
 #else
        if (pythonhome == NULL) {
-               strcpy(buf, PYTHONPATH);
-               buf = strchr(buf, '\0');
+               wcscpy(buf, PYTHONPATH);
+               buf = wcschr(buf, L'\0');
        }
 #endif /* MS_WINDOWS */
        else {
-               char *p = PYTHONPATH;
-               char *q;
+               wchar_t *p = PYTHONPATH;
+               wchar_t *q;
                size_t n;
                for (;;) {
-                       q = strchr(p, DELIM);
+                       q = wcschr(p, DELIM);
                        if (q == NULL)
-                               n = strlen(p);
+                               n = wcslen(p);
                        else
                                n = q-p;
                        if (p[0] == '.' && is_sep(p[1])) {
-                               strcpy(buf, pythonhome);
-                               buf = strchr(buf, '\0');
+                               wcscpy(buf, pythonhome);
+                               buf = wcschr(buf, L'\0');
                                p++;
                                n--;
                        }
-                       strncpy(buf, p, n);
+                       wcsncpy(buf, p, n);
                        buf += n;
                        if (q == NULL)
                                break;
@@ -628,10 +599,10 @@ calculate_path(void)
        }
        if (argv0_path) {
                *buf++ = DELIM;
-               strcpy(buf, argv0_path);
-               buf = strchr(buf, '\0');
+               wcscpy(buf, argv0_path);
+               buf = wcschr(buf, L'\0');
        }
-       *buf = '\0';
+       *buf = L'\0';
        /* Now to pull one last hack/trick.  If sys.prefix is
           empty, then try and find it somewhere on the paths
           we calculated.  We scan backwards, as our general policy
@@ -640,12 +611,12 @@ calculate_path(void)
           on the path, and that our 'prefix' directory is
           the parent of that.
        */
-       if (*prefix=='\0') {
-               char lookBuf[MAXPATHLEN+1];
-               char *look = buf - 1; /* 'buf' is at the end of the buffer */
+       if (*prefix==L'\0') {
+               wchar_t lookBuf[MAXPATHLEN+1];
+               wchar_t *look = buf - 1; /* 'buf' is at the end of the buffer */
                while (1) {
                        Py_ssize_t nchars;
-                       char *lookEnd = look;
+                       wchar_t *lookEnd = look;
                        /* 'look' will end up one character before the
                           start of the path in question - even if this
                           is one character before the start of the buffer
@@ -653,8 +624,8 @@ calculate_path(void)
                        while (look >= module_search_path && *look != DELIM)
                                look--;
                        nchars = lookEnd-look;
-                       strncpy(lookBuf, look+1, nchars);
-                       lookBuf[nchars] = '\0';
+                       wcsncpy(lookBuf, look+1, nchars);
+                       lookBuf[nchars] = L'\0';
                        /* Up one level to the parent */
                        reduce(lookBuf);
                        if (search_for_prefix(lookBuf, LANDMARK)) {
@@ -671,7 +642,7 @@ calculate_path(void)
 
 /* External interface */
 
-char *
+wchar_t *
 Py_GetPath(void)
 {
        if (!module_search_path)
@@ -679,7 +650,7 @@ Py_GetPath(void)
        return module_search_path;
 }
 
-char *
+wchar_t *
 Py_GetPrefix(void)
 {
        if (!module_search_path)
@@ -687,13 +658,13 @@ Py_GetPrefix(void)
        return prefix;
 }
 
-char *
+wchar_t *
 Py_GetExecPrefix(void)
 {
        return Py_GetPrefix();
 }
 
-char *
+wchar_t *
 Py_GetProgramFullPath(void)
 {
        if (!module_search_path)
index 53645a7b74010a6553bcd3fa38e1ca84f9d25180..4291192d70efdb542fcfe2b72ed13e404ef33f9a 100644 (file)
@@ -80,7 +80,7 @@ WIN32 is still required for the locale module.
 #define MS_WIN32 /* only support win32 and greater. */
 #define MS_WINDOWS
 #ifndef PYTHONPATH
-#      define PYTHONPATH ".\\DLLs;.\\lib;.\\lib\\plat-win;.\\lib\\lib-tk"
+#      define PYTHONPATH L".\\DLLs;.\\lib;.\\lib\\plat-win;.\\lib\\lib-tk"
 #endif
 #define NT_THREADS
 #define WITH_THREAD
index 397f0465ce641af03d2c03faabe8aa56df499d8f..88c34651dc16bc46366cd84543124c2910b383a6 100644 (file)
@@ -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;
 }
index 659efcfff812bc1db1734eac2767bf69a58f8086..7c1d60500607f98c9f04ff82cb66270ab9623b18 100644 (file)
 /* 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 '_';
                        }
 
index 3207fb8b8174465a02e5c482505690f3dd3ed42b..124eaf095d0da5664bf1045bc07cd0cc7a596acf 100644 (file)
@@ -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;
 }
 
index aceb2a37371bf45c63dd41e9ec67362ca22cbcc4..81adf5d69caad02c55d3c9baac97302b9fa073f8 100644 (file)
@@ -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)