+\r
+/* Return the initial module search path. */\r
+/* Used by DOS, OS/2, Windows 3.1, Windows 95/98, Windows NT. */\r
+\r
+/* ----------------------------------------------------------------\r
+ PATH RULES FOR WINDOWS:\r
+ This describes how sys.path is formed on Windows. It describes the\r
+ functionality, not the implementation (ie, the order in which these\r
+ are actually fetched is different)\r
+\r
+ * Python always adds an empty entry at the start, which corresponds\r
+ to the current directory.\r
+\r
+ * If the PYTHONPATH env. var. exists, its entries are added next.\r
+\r
+ * We look in the registry for "application paths" - that is, sub-keys\r
+ under the main PythonPath registry key. These are added next (the\r
+ order of sub-key processing is undefined).\r
+ HKEY_CURRENT_USER is searched and added first.\r
+ HKEY_LOCAL_MACHINE is searched and added next.\r
+ (Note that all known installers only use HKLM, so HKCU is typically\r
+ empty)\r
+\r
+ * We attempt to locate the "Python Home" - if the PYTHONHOME env var\r
+ is set, we believe it. Otherwise, we use the path of our host .EXE's\r
+ to try and locate our "landmark" (lib\\os.py) and deduce our home.\r
+ - If we DO have a Python Home: The relevant sub-directories (Lib,\r
+ plat-win, lib-tk, etc) are based on the Python Home\r
+ - If we DO NOT have a Python Home, the core Python Path is\r
+ loaded from the registry. This is the main PythonPath key,\r
+ and both HKLM and HKCU are combined to form the path)\r
+\r
+ * Iff - we can not locate the Python Home, have not had a PYTHONPATH\r
+ specified, and can't locate any Registry entries (ie, we have _nothing_\r
+ we can assume is a good path), a default path with relative entries is\r
+ used (eg. .\Lib;.\plat-win, etc)\r
+\r
+\r
+ The end result of all this is:\r
+ * When running python.exe, or any other .exe in the main Python directory\r
+ (either an installed version, or directly from the PCbuild directory),\r
+ the core path is deduced, and the core paths in the registry are\r
+ ignored. Other "application paths" in the registry are always read.\r
+\r
+ * When Python is hosted in another exe (different directory, embedded via\r
+ COM, etc), the Python Home will not be deduced, so the core path from\r
+ the registry is used. Other "application paths" in the registry are\r
+ always read.\r
+\r
+ * If Python can't find its home and there is no registry (eg, frozen\r
+ exe, some very strange installation setup) you get a path with\r
+ some default, but relative, paths.\r
+\r
+ ---------------------------------------------------------------- */\r
+\r
+\r
+#include "Python.h"\r
+#include "osdefs.h"\r
+\r
+#ifdef MS_WINDOWS\r
+#include <windows.h>\r
+#include <tchar.h>\r
+#endif\r
+\r
+#ifdef HAVE_SYS_TYPES_H\r
+#include <sys/types.h>\r
+#endif /* HAVE_SYS_TYPES_H */\r
+\r
+#ifdef HAVE_SYS_STAT_H\r
+#include <sys/stat.h>\r
+#endif /* HAVE_SYS_STAT_H */\r
+\r
+#include <string.h>\r
+\r
+/* Search in some common locations for the associated Python libraries.\r
+ *\r
+ * Py_GetPath() tries to return a sensible Python module search path.\r
+ *\r
+ * The approach is an adaptation for Windows of the strategy used in\r
+ * ../Modules/getpath.c; it uses the Windows Registry as one of its\r
+ * information sources.\r
+ */\r
+\r
+#ifndef LANDMARK\r
+#define LANDMARK "lib\\os.py"\r
+#endif\r
+\r
+static char prefix[MAXPATHLEN+1];\r
+static char progpath[MAXPATHLEN+1];\r
+static char dllpath[MAXPATHLEN+1];\r
+static char *module_search_path = NULL;\r
+\r
+\r
+static int\r
+is_sep(char ch) /* determine if "ch" is a separator character */\r
+{\r
+#ifdef ALTSEP\r
+ return ch == SEP || ch == ALTSEP;\r
+#else\r
+ return ch == SEP;\r
+#endif\r
+}\r
+\r
+/* assumes 'dir' null terminated in bounds. Never writes\r
+ beyond existing terminator.\r
+*/\r
+static void\r
+reduce(char *dir)\r
+{\r
+ size_t i = strlen(dir);\r
+ while (i > 0 && !is_sep(dir[i]))\r
+ --i;\r
+ dir[i] = '\0';\r
+}\r
+\r
+\r
+static int\r
+exists(char *filename)\r
+{\r
+ struct stat buf;\r
+ return stat(filename, &buf) == 0;\r
+}\r
+\r
+/* Assumes 'filename' MAXPATHLEN+1 bytes long -\r
+ may extend 'filename' by one character.\r
+*/\r
+static int\r
+ismodule(char *filename) /* Is module -- check for .pyc/.pyo too */\r
+{\r
+ if (exists(filename))\r
+ return 1;\r
+\r
+ /* Check for the compiled version of prefix. */\r
+ if (strlen(filename) < MAXPATHLEN) {\r
+ strcat(filename, Py_OptimizeFlag ? "o" : "c");\r
+ if (exists(filename))\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+/* Add a path component, by appending stuff to buffer.\r
+ buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a\r
+ NUL-terminated string with no more than MAXPATHLEN characters (not counting\r
+ the trailing NUL). It's a fatal error if it contains a string longer than\r
+ that (callers must be careful!). If these requirements are met, it's\r
+ guaranteed that buffer will still be a NUL-terminated string with no more\r
+ than MAXPATHLEN characters at exit. If stuff is too long, only as much of\r
+ stuff as fits will be appended.\r
+*/\r
+static void\r
+join(char *buffer, char *stuff)\r
+{\r
+ size_t n, k;\r
+ if (is_sep(stuff[0]))\r
+ n = 0;\r
+ else {\r
+ n = strlen(buffer);\r
+ if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN)\r
+ buffer[n++] = SEP;\r
+ }\r
+ if (n > MAXPATHLEN)\r
+ Py_FatalError("buffer overflow in getpathp.c's joinpath()");\r
+ k = strlen(stuff);\r
+ if (n + k > MAXPATHLEN)\r
+ k = MAXPATHLEN - n;\r
+ strncpy(buffer+n, stuff, k);\r
+ buffer[n+k] = '\0';\r
+}\r
+\r
+/* gotlandmark only called by search_for_prefix, which ensures\r
+ 'prefix' is null terminated in bounds. join() ensures\r
+ 'landmark' can not overflow prefix if too long.\r
+*/\r
+static int\r
+gotlandmark(char *landmark)\r
+{\r
+ int ok;\r
+ Py_ssize_t n;\r
+\r
+ n = strlen(prefix);\r
+ join(prefix, landmark);\r
+ ok = ismodule(prefix);\r
+ prefix[n] = '\0';\r
+ return ok;\r
+}\r
+\r
+/* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd.\r
+ assumption provided by only caller, calculate_path() */\r
+static int\r
+search_for_prefix(char *argv0_path, char *landmark)\r
+{\r
+ /* Search from argv0_path, until landmark is found */\r
+ strcpy(prefix, argv0_path);\r
+ do {\r
+ if (gotlandmark(landmark))\r
+ return 1;\r
+ reduce(prefix);\r
+ } while (prefix[0]);\r
+ return 0;\r
+}\r
+\r
+#ifdef MS_WINDOWS\r
+#ifdef Py_ENABLE_SHARED\r
+\r
+/* a string loaded from the DLL at startup.*/\r
+extern const char *PyWin_DLLVersionString;\r
+\r
+\r
+/* Load a PYTHONPATH value from the registry.\r
+ Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER.\r
+\r
+ Works in both Unicode and 8bit environments. Only uses the\r
+ Ex family of functions so it also works with Windows CE.\r
+\r
+ Returns NULL, or a pointer that should be freed.\r
+\r
+ XXX - this code is pretty strange, as it used to also\r
+ work on Win16, where the buffer sizes werent available\r
+ in advance. It could be simplied now Win16/Win32s is dead!\r
+*/\r
+\r
+static char *\r
+getpythonregpath(HKEY keyBase, int skipcore)\r
+{\r
+ HKEY newKey = 0;\r
+ DWORD dataSize = 0;\r
+ DWORD numKeys = 0;\r
+ LONG rc;\r
+ char *retval = NULL;\r
+ TCHAR *dataBuf = NULL;\r
+ static const TCHAR keyPrefix[] = _T("Software\\Python\\PythonCore\\");\r
+ static const TCHAR keySuffix[] = _T("\\PythonPath");\r
+ size_t versionLen;\r
+ DWORD index;\r
+ TCHAR *keyBuf = NULL;\r
+ TCHAR *keyBufPtr;\r
+ TCHAR **ppPaths = NULL;\r
+\r
+ /* Tried to use sysget("winver") but here is too early :-( */\r
+ versionLen = _tcslen(PyWin_DLLVersionString);\r
+ /* Space for all the chars, plus one \0 */\r
+ keyBuf = keyBufPtr = malloc(sizeof(keyPrefix) +\r
+ sizeof(TCHAR)*(versionLen-1) +\r
+ sizeof(keySuffix));\r
+ if (keyBuf==NULL) goto done;\r
+\r
+ memcpy(keyBufPtr, keyPrefix, sizeof(keyPrefix)-sizeof(TCHAR));\r
+ keyBufPtr += sizeof(keyPrefix)/sizeof(TCHAR) - 1;\r
+ memcpy(keyBufPtr, PyWin_DLLVersionString, versionLen * sizeof(TCHAR));\r
+ keyBufPtr += versionLen;\r
+ /* NULL comes with this one! */\r
+ memcpy(keyBufPtr, keySuffix, sizeof(keySuffix));\r
+ /* Open the root Python key */\r
+ rc=RegOpenKeyEx(keyBase,\r
+ keyBuf, /* subkey */\r
+ 0, /* reserved */\r
+ KEY_READ,\r
+ &newKey);\r
+ if (rc!=ERROR_SUCCESS) goto done;\r
+ /* Find out how big our core buffer is, and how many subkeys we have */\r
+ rc = RegQueryInfoKey(newKey, NULL, NULL, NULL, &numKeys, NULL, NULL,\r
+ NULL, NULL, &dataSize, NULL, NULL);\r
+ if (rc!=ERROR_SUCCESS) goto done;\r
+ if (skipcore) dataSize = 0; /* Only count core ones if we want them! */\r
+ /* Allocate a temp array of char buffers, so we only need to loop\r
+ reading the registry once\r
+ */\r
+ ppPaths = malloc( sizeof(TCHAR *) * numKeys );\r
+ if (ppPaths==NULL) goto done;\r
+ memset(ppPaths, 0, sizeof(TCHAR *) * numKeys);\r
+ /* Loop over all subkeys, allocating a temp sub-buffer. */\r
+ for(index=0;index<numKeys;index++) {\r
+ TCHAR keyBuf[MAX_PATH+1];\r
+ HKEY subKey = 0;\r
+ DWORD reqdSize = MAX_PATH+1;\r
+ /* Get the sub-key name */\r
+ DWORD rc = RegEnumKeyEx(newKey, index, keyBuf, &reqdSize,\r
+ NULL, NULL, NULL, NULL );\r
+ if (rc!=ERROR_SUCCESS) goto done;\r
+ /* Open the sub-key */\r
+ rc=RegOpenKeyEx(newKey,\r
+ keyBuf, /* subkey */\r
+ 0, /* reserved */\r
+ KEY_READ,\r
+ &subKey);\r
+ if (rc!=ERROR_SUCCESS) goto done;\r
+ /* Find the value of the buffer size, malloc, then read it */\r
+ RegQueryValueEx(subKey, NULL, 0, NULL, NULL, &reqdSize);\r
+ if (reqdSize) {\r
+ ppPaths[index] = malloc(reqdSize);\r
+ if (ppPaths[index]) {\r
+ RegQueryValueEx(subKey, NULL, 0, NULL,\r
+ (LPBYTE)ppPaths[index],\r
+ &reqdSize);\r
+ dataSize += reqdSize + 1; /* 1 for the ";" */\r
+ }\r
+ }\r
+ RegCloseKey(subKey);\r
+ }\r
+\r
+ /* return null if no path to return */\r
+ if (dataSize == 0) goto done;\r
+\r
+ /* original datasize from RegQueryInfo doesn't include the \0 */\r
+ dataBuf = malloc((dataSize+1) * sizeof(TCHAR));\r
+ if (dataBuf) {\r
+ TCHAR *szCur = dataBuf;\r
+ DWORD reqdSize = dataSize;\r
+ /* Copy our collected strings */\r
+ for (index=0;index<numKeys;index++) {\r
+ if (index > 0) {\r
+ *(szCur++) = _T(';');\r
+ dataSize--;\r
+ }\r
+ if (ppPaths[index]) {\r
+ Py_ssize_t len = _tcslen(ppPaths[index]);\r
+ _tcsncpy(szCur, ppPaths[index], len);\r
+ szCur += len;\r
+ assert(dataSize > (DWORD)len);\r
+ dataSize -= (DWORD)len;\r
+ }\r
+ }\r
+ if (skipcore)\r
+ *szCur = '\0';\r
+ else {\r
+ /* If we have no values, we dont need a ';' */\r
+ if (numKeys) {\r
+ *(szCur++) = _T(';');\r
+ dataSize--;\r
+ }\r
+ /* Now append the core path entries -\r
+ this will include the NULL\r
+ */\r
+ rc = RegQueryValueEx(newKey, NULL, 0, NULL,\r
+ (LPBYTE)szCur, &dataSize);\r
+ }\r
+ /* And set the result - caller must free\r
+ If MBCS, it is fine as is. If Unicode, allocate new\r
+ buffer and convert.\r
+ */\r
+#ifdef UNICODE\r
+ retval = (char *)malloc(reqdSize+1);\r
+ if (retval)\r
+ WideCharToMultiByte(CP_ACP, 0,\r
+ dataBuf, -1, /* source */\r
+ retval, reqdSize+1, /* dest */\r
+ NULL, NULL);\r
+ free(dataBuf);\r
+#else\r
+ retval = dataBuf;\r
+#endif\r
+ }\r
+done:\r
+ /* Loop freeing my temp buffers */\r
+ if (ppPaths) {\r
+ for(index=0;index<numKeys;index++)\r
+ if (ppPaths[index]) free(ppPaths[index]);\r
+ free(ppPaths);\r
+ }\r
+ if (newKey)\r
+ RegCloseKey(newKey);\r
+ if (keyBuf)\r
+ free(keyBuf);\r
+ return retval;\r
+}\r
+#endif /* Py_ENABLE_SHARED */\r
+#endif /* MS_WINDOWS */\r
+\r
+static void\r
+get_progpath(void)\r
+{\r
+ extern char *Py_GetProgramName(void);\r
+ char *path = getenv("PATH");\r
+ char *prog = Py_GetProgramName();\r
+\r
+#ifdef MS_WINDOWS\r
+ extern HANDLE PyWin_DLLhModule;\r
+#ifdef UNICODE\r
+ WCHAR wprogpath[MAXPATHLEN+1];\r
+ /* Windows documents that GetModuleFileName() will "truncate",\r
+ but makes no mention of the null terminator. Play it safe.\r
+ PLUS Windows itself defines MAX_PATH as the same, but anyway...\r
+ */\r
+#ifdef Py_ENABLE_SHARED\r
+ wprogpath[MAXPATHLEN]=_T('\0');\r
+ if (PyWin_DLLhModule &&\r
+ GetModuleFileName(PyWin_DLLhModule, wprogpath, MAXPATHLEN)) {\r
+ WideCharToMultiByte(CP_ACP, 0,\r
+ wprogpath, -1,\r
+ dllpath, MAXPATHLEN+1,\r
+ NULL, NULL);\r
+ }\r
+#else\r
+ dllpath[0] = 0;\r
+#endif\r
+ wprogpath[MAXPATHLEN]=_T('\0');\r
+ if (GetModuleFileName(NULL, wprogpath, MAXPATHLEN)) {\r
+ WideCharToMultiByte(CP_ACP, 0,\r
+ wprogpath, -1,\r
+ progpath, MAXPATHLEN+1,\r
+ NULL, NULL);\r
+ return;\r
+ }\r
+#else\r
+ /* static init of progpath ensures final char remains \0 */\r
+#ifdef Py_ENABLE_SHARED\r
+ if (PyWin_DLLhModule)\r
+ if (!GetModuleFileName(PyWin_DLLhModule, dllpath, MAXPATHLEN))\r
+ dllpath[0] = 0;\r
+#else\r
+ dllpath[0] = 0;\r
+#endif\r
+ if (GetModuleFileName(NULL, progpath, MAXPATHLEN))\r
+ return;\r
+#endif\r
+#endif\r
+ if (prog == NULL || *prog == '\0')\r
+ prog = "python";\r
+\r
+ /* If there is no slash in the argv0 path, then we have to\r
+ * assume python is on the user's $PATH, since there's no\r
+ * other way to find a directory to start the search from. If\r
+ * $PATH isn't exported, you lose.\r
+ */\r
+#ifdef ALTSEP\r
+ if (strchr(prog, SEP) || strchr(prog, ALTSEP))\r
+#else\r
+ if (strchr(prog, SEP))\r
+#endif\r
+ strncpy(progpath, prog, MAXPATHLEN);\r
+ else if (path) {\r
+ while (1) {\r
+ char *delim = strchr(path, DELIM);\r
+\r
+ if (delim) {\r
+ size_t len = delim - path;\r
+ /* ensure we can't overwrite buffer */\r
+ len = MIN(MAXPATHLEN,len);\r
+ strncpy(progpath, path, len);\r
+ *(progpath + len) = '\0';\r
+ }\r
+ else\r
+ strncpy(progpath, path, MAXPATHLEN);\r
+\r
+ /* join() is safe for MAXPATHLEN+1 size buffer */\r
+ join(progpath, prog);\r
+ if (exists(progpath))\r
+ break;\r
+\r
+ if (!delim) {\r
+ progpath[0] = '\0';\r
+ break;\r
+ }\r
+ path = delim + 1;\r
+ }\r
+ }\r
+ else\r
+ progpath[0] = '\0';\r
+}\r
+\r
+static void\r
+calculate_path(void)\r
+{\r
+ char argv0_path[MAXPATHLEN+1];\r
+ char *buf;\r
+ size_t bufsz;\r
+ char *pythonhome = Py_GetPythonHome();\r
+ char *envpath = Py_GETENV("PYTHONPATH");\r
+\r
+#ifdef MS_WINDOWS\r
+ int skiphome, skipdefault;\r
+ char *machinepath = NULL;\r
+ char *userpath = NULL;\r
+ char zip_path[MAXPATHLEN+1];\r
+ size_t len;\r
+#endif\r
+\r
+ get_progpath();\r
+ /* progpath guaranteed \0 terminated in MAXPATH+1 bytes. */\r
+ strcpy(argv0_path, progpath);\r
+ reduce(argv0_path);\r
+ if (pythonhome == NULL || *pythonhome == '\0') {\r
+ if (search_for_prefix(argv0_path, LANDMARK))\r
+ pythonhome = prefix;\r
+ else\r
+ pythonhome = NULL;\r
+ }\r
+ else\r
+ strncpy(prefix, pythonhome, MAXPATHLEN);\r
+\r
+ if (envpath && *envpath == '\0')\r
+ envpath = NULL;\r
+\r
+\r
+#ifdef MS_WINDOWS\r
+ /* Calculate zip archive path */\r
+ if (dllpath[0]) /* use name of python DLL */\r
+ strncpy(zip_path, dllpath, MAXPATHLEN);\r
+ else /* use name of executable program */\r
+ strncpy(zip_path, progpath, MAXPATHLEN);\r
+ zip_path[MAXPATHLEN] = '\0';\r
+ len = strlen(zip_path);\r
+ if (len > 4) {\r
+ zip_path[len-3] = 'z'; /* change ending to "zip" */\r
+ zip_path[len-2] = 'i';\r
+ zip_path[len-1] = 'p';\r
+ }\r
+ else {\r
+ zip_path[0] = 0;\r
+ }\r
+\r
+ skiphome = pythonhome==NULL ? 0 : 1;\r
+#ifdef Py_ENABLE_SHARED\r
+ machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome);\r
+ userpath = getpythonregpath(HKEY_CURRENT_USER, skiphome);\r
+#endif\r
+ /* We only use the default relative PYTHONPATH if we havent\r
+ anything better to use! */\r
+ skipdefault = envpath!=NULL || pythonhome!=NULL || \\r
+ machinepath!=NULL || userpath!=NULL;\r
+#endif\r
+\r
+ /* We need to construct a path from the following parts.\r
+ (1) the PYTHONPATH environment variable, if set;\r
+ (2) for Win32, the zip archive file path;\r
+ (3) for Win32, the machinepath and userpath, if set;\r
+ (4) the PYTHONPATH config macro, with the leading "."\r
+ of each component replaced with pythonhome, if set;\r
+ (5) the directory containing the executable (argv0_path).\r
+ The length calculation calculates #4 first.\r
+ Extra rules:\r
+ - If PYTHONHOME is set (in any way) item (3) is ignored.\r
+ - If registry values are used, (4) and (5) are ignored.\r
+ */\r
+\r
+ /* Calculate size of return buffer */\r
+ if (pythonhome != NULL) {\r
+ char *p;\r
+ bufsz = 1;\r
+ for (p = PYTHONPATH; *p; p++) {\r
+ if (*p == DELIM)\r
+ bufsz++; /* number of DELIM plus one */\r
+ }\r
+ bufsz *= strlen(pythonhome);\r
+ }\r
+ else\r
+ bufsz = 0;\r
+ bufsz += strlen(PYTHONPATH) + 1;\r
+ bufsz += strlen(argv0_path) + 1;\r
+#ifdef MS_WINDOWS\r
+ if (userpath)\r
+ bufsz += strlen(userpath) + 1;\r
+ if (machinepath)\r
+ bufsz += strlen(machinepath) + 1;\r
+ bufsz += strlen(zip_path) + 1;\r
+#endif\r
+ if (envpath != NULL)\r
+ bufsz += strlen(envpath) + 1;\r
+\r
+ module_search_path = buf = malloc(bufsz);\r
+ if (buf == NULL) {\r
+ /* We can't exit, so print a warning and limp along */\r
+ fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");\r
+ if (envpath) {\r
+ fprintf(stderr, "Using environment $PYTHONPATH.\n");\r
+ module_search_path = envpath;\r
+ }\r
+ else {\r
+ fprintf(stderr, "Using default static path.\n");\r
+ module_search_path = PYTHONPATH;\r
+ }\r
+#ifdef MS_WINDOWS\r
+ if (machinepath)\r
+ free(machinepath);\r
+ if (userpath)\r
+ free(userpath);\r
+#endif /* MS_WINDOWS */\r
+ return;\r
+ }\r
+\r
+ if (envpath) {\r
+ strcpy(buf, envpath);\r
+ buf = strchr(buf, '\0');\r
+ *buf++ = DELIM;\r
+ }\r
+#ifdef MS_WINDOWS\r
+ if (zip_path[0]) {\r
+ strcpy(buf, zip_path);\r
+ buf = strchr(buf, '\0');\r
+ *buf++ = DELIM;\r
+ }\r
+ if (userpath) {\r
+ strcpy(buf, userpath);\r
+ buf = strchr(buf, '\0');\r
+ *buf++ = DELIM;\r
+ free(userpath);\r
+ }\r
+ if (machinepath) {\r
+ strcpy(buf, machinepath);\r
+ buf = strchr(buf, '\0');\r
+ *buf++ = DELIM;\r
+ free(machinepath);\r
+ }\r
+ if (pythonhome == NULL) {\r
+ if (!skipdefault) {\r
+ strcpy(buf, PYTHONPATH);\r
+ buf = strchr(buf, '\0');\r
+ }\r
+ }\r
+#else\r
+ if (pythonhome == NULL) {\r
+ strcpy(buf, PYTHONPATH);\r
+ buf = strchr(buf, '\0');\r
+ }\r
+#endif /* MS_WINDOWS */\r
+ else {\r
+ char *p = PYTHONPATH;\r
+ char *q;\r
+ size_t n;\r
+ for (;;) {\r
+ q = strchr(p, DELIM);\r
+ if (q == NULL)\r
+ n = strlen(p);\r
+ else\r
+ n = q-p;\r
+ if (p[0] == '.' && is_sep(p[1])) {\r
+ strcpy(buf, pythonhome);\r
+ buf = strchr(buf, '\0');\r
+ p++;\r
+ n--;\r
+ }\r
+ strncpy(buf, p, n);\r
+ buf += n;\r
+ if (q == NULL)\r
+ break;\r
+ *buf++ = DELIM;\r
+ p = q+1;\r
+ }\r
+ }\r
+ if (argv0_path) {\r
+ *buf++ = DELIM;\r
+ strcpy(buf, argv0_path);\r
+ buf = strchr(buf, '\0');\r
+ }\r
+ *buf = '\0';\r
+ /* Now to pull one last hack/trick. If sys.prefix is\r
+ empty, then try and find it somewhere on the paths\r
+ we calculated. We scan backwards, as our general policy\r
+ is that Python core directories are at the *end* of\r
+ sys.path. We assume that our "lib" directory is\r
+ on the path, and that our 'prefix' directory is\r
+ the parent of that.\r
+ */\r
+ if (*prefix=='\0') {\r
+ char lookBuf[MAXPATHLEN+1];\r
+ char *look = buf - 1; /* 'buf' is at the end of the buffer */\r
+ while (1) {\r
+ Py_ssize_t nchars;\r
+ char *lookEnd = look;\r
+ /* 'look' will end up one character before the\r
+ start of the path in question - even if this\r
+ is one character before the start of the buffer\r
+ */\r
+ while (look >= module_search_path && *look != DELIM)\r
+ look--;\r
+ nchars = lookEnd-look;\r
+ strncpy(lookBuf, look+1, nchars);\r
+ lookBuf[nchars] = '\0';\r
+ /* Up one level to the parent */\r
+ reduce(lookBuf);\r
+ if (search_for_prefix(lookBuf, LANDMARK)) {\r
+ break;\r
+ }\r
+ /* If we are out of paths to search - give up */\r
+ if (look < module_search_path)\r
+ break;\r
+ look--;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/* External interface */\r
+\r
+char *\r
+Py_GetPath(void)\r
+{\r
+ if (!module_search_path)\r
+ calculate_path();\r
+ return module_search_path;\r
+}\r
+\r
+char *\r
+Py_GetPrefix(void)\r
+{\r
+ if (!module_search_path)\r
+ calculate_path();\r
+ return prefix;\r
+}\r
+\r
+char *\r
+Py_GetExecPrefix(void)\r
+{\r
+ return Py_GetPrefix();\r
+}\r
+\r
+char *\r
+Py_GetProgramFullPath(void)\r
+{\r
+ if (!module_search_path)\r
+ calculate_path();\r
+ return progpath;\r
+}\r