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 /PC/getpathp.c | |
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 'PC/getpathp.c')
-rw-r--r-- | PC/getpathp.c | 285 |
1 files changed, 128 insertions, 157 deletions
diff --git a/PC/getpathp.c b/PC/getpathp.c index e62b936..3a250be 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -56,10 +56,10 @@ #include "Python.h" #include "osdefs.h" +#include <wchar.h> #ifdef MS_WINDOWS #include <windows.h> -#include <tchar.h> #endif #ifdef HAVE_SYS_TYPES_H @@ -82,17 +82,17 @@ */ #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) |