Blame 0320-MINGW-implement-exec-prefix.patch

ddb6764
diff -rupN Python-2.7.13/PC/getpathp.c Python-2.7.13-new/PC/getpathp.c
ddb6764
--- Python-2.7.13/PC/getpathp.c	2017-01-21 01:46:05.996613000 +0100
ddb6764
+++ Python-2.7.13-new/PC/getpathp.c	2017-01-21 01:46:06.854603840 +0100
ddb6764
@@ -98,10 +98,17 @@ static char *lib_python = "lib\\python"
ddb6764
 
ddb6764
 #  define USE_POSIX_PREFIX
ddb6764
 
ddb6764
+#  ifdef Py_ENABLE_SHARED
ddb6764
+#    define USE_EXEC_PREFIX
ddb6764
+#  endif
ddb6764
+
ddb6764
 #endif
ddb6764
 
ddb6764
 
ddb6764
 static char prefix[MAXPATHLEN+1];
ddb6764
+#ifdef USE_EXEC_PREFIX
ddb6764
+static char exec_prefix[MAXPATHLEN+1];
ddb6764
+#endif
ddb6764
 static char progpath[MAXPATHLEN+1];
ddb6764
 static char dllpath[MAXPATHLEN+1];
ddb6764
 static char *module_search_path = NULL;
ddb6764
@@ -285,6 +292,82 @@ search_for_prefix(char *argv0_path, char
ddb6764
 /* a string loaded from the DLL at startup.*/
ddb6764
 extern const char *PyWin_DLLVersionString;
ddb6764
 
ddb6764
+#ifdef USE_EXEC_PREFIX
ddb6764
+
ddb6764
+/* based on getpath.c but with path relative to executabe */
ddb6764
+/* search_for exec_prefix requires that paths be no more than
ddb6764
+   MAXPATHLEN bytes long.
ddb6764
+   return: 1 if found; -1 if found build directory
ddb6764
+*/
ddb6764
+static int
ddb6764
+search_for_exec_prefix(char *argv0_path, char *home, char *_exec_prefix)
ddb6764
+{
ddb6764
+    size_t n;
ddb6764
+
ddb6764
+    /* If PYTHONHOME is set, we believe it unconditionally */
ddb6764
+    if (home) {
ddb6764
+        char *delim;
ddb6764
+        delim = srtchr(home, DELIM);
ddb6764
+        if (delim)
ddb6764
+            strncpy(exec_prefix, delim+1, MAXPATHLEN);
ddb6764
+        else
ddb6764
+            strncpy(exec_prefix, home, MAXPATHLEN);
ddb6764
+        join(exec_prefix, lib_python);
ddb6764
+        join(exec_prefix, "lib-dynload");
ddb6764
+        return 1;
ddb6764
+    }
ddb6764
+
ddb6764
+    /* Check to see if argv[0] is in the build directory. "pybuilddir.txt"
ddb6764
+       is written by setup.py and contains the relative path to the location
ddb6764
+       of shared library modules. */
ddb6764
+    strcpy(exec_prefix, argv0_path);
ddb6764
+    join(exec_prefix, "pybuilddir.txt");
ddb6764
+    if (exists(exec_prefix)) {
ddb6764
+        FILE *f = _Py_fopen(exec_prefix, "rb");
ddb6764
+        if (f == NULL)
ddb6764
+            errno = 0;
ddb6764
+        else {
ddb6764
+            char buf[MAXPATHLEN+1];
ddb6764
+            PyObject *decoded;
ddb6764
+            char rel_builddir_path[MAXPATHLEN+1];
ddb6764
+            n = fread(buf, 1, MAXPATHLEN, f);
ddb6764
+            buf[n] = '\0';
ddb6764
+            fclose(f);
ddb6764
+            decoded = PyUnicode_DecodeMBCS(buf, n, NULL);
ddb6764
+            if (decoded != NULL) {
ddb6764
+                Py_ssize_t k;
ddb6764
+                k = PyUnicode_AsWideChar(decoded,
ddb6764
+                                         rel_builddir_path, MAXPATHLEN);
ddb6764
+                Py_DECREF(decoded);
ddb6764
+                if (k >= 0) {
ddb6764
+                    rel_builddir_path[k] = L'\0';
ddb6764
+                    strcpy(exec_prefix, argv0_path);
ddb6764
+                    join(exec_prefix, rel_builddir_path);
ddb6764
+                    return -1;
ddb6764
+                }
ddb6764
+            }
ddb6764
+        }
ddb6764
+    }
ddb6764
+
ddb6764
+    /* Search from argv0_path, until root is found */
ddb6764
+    strcpy(exec_prefix, argv0_path);
ddb6764
+    do {
ddb6764
+        n = strlen(exec_prefix);
ddb6764
+        join(exec_prefix, lib_python);
ddb6764
+        join(exec_prefix, "lib-dynload");
ddb6764
+        if (exists(exec_prefix))
ddb6764
+            return 1;
ddb6764
+        exec_prefix[n] = '\0';
ddb6764
+        reduce(exec_prefix);
ddb6764
+    } while (exec_prefix[0]);
ddb6764
+
ddb6764
+    /* Configure exec_prefix is unused */
ddb6764
+    (void)_exec_prefix;
ddb6764
+
ddb6764
+    /* Fail */
ddb6764
+    return 0;
ddb6764
+}
ddb6764
+#endif /*def USE_EXEC_PREFIX*/
ddb6764
 
ddb6764
 /* Load a PYTHONPATH value from the registry.
ddb6764
    Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER.
ddb6764
@@ -549,6 +632,9 @@ calculate_path(void)
ddb6764
 #ifdef USE_POSIX_PREFIX
ddb6764
     int pfound;
ddb6764
 #endif
ddb6764
+#ifdef USE_EXEC_PREFIX
ddb6764
+    int efound;
ddb6764
+#endif
ddb6764
 
ddb6764
 #ifdef MS_WINDOWS
ddb6764
     int skiphome, skipdefault;
ddb6764
@@ -586,6 +672,16 @@ calculate_path(void)
ddb6764
     if (envpath && *envpath == '\0')
ddb6764
         envpath = NULL;
ddb6764
 
ddb6764
+#ifdef USE_EXEC_PREFIX
ddb6764
+    efound = search_for_exec_prefix(argv0_path, pythonhome, NULL);
ddb6764
+    if (!efound) {
ddb6764
+        strncpy(exec_prefix, argv0_path, MAXPATHLEN);
ddb6764
+        reduce(exec_prefix);
ddb6764
+        join(exec_prefix, lib_python);
ddb6764
+        join(exec_prefix, "lib-dynload");
ddb6764
+    }
ddb6764
+#endif
ddb6764
+
ddb6764
 #ifdef MS_WINDOWS
ddb6764
     /* Calculate zip archive path */
ddb6764
     if (dllpath[0])             /* use name of python DLL */
ddb6764
@@ -642,6 +738,9 @@ calculate_path(void)
ddb6764
 #ifdef USE_POSIX_PREFIX
ddb6764
     bufsz += strlen(prefix) + 1;
ddb6764
 #endif
ddb6764
+#ifdef USE_EXEC_PREFIX
ddb6764
+    bufsz +=strlen(exec_prefix) + 1;
ddb6764
+#endif
ddb6764
     bufsz += strlen(PYTHONPATH) + 1;
ddb6764
     bufsz += strlen(argv0_path) + 1;
ddb6764
 #ifdef MS_WINDOWS
ddb6764
@@ -691,6 +790,11 @@ calculate_path(void)
ddb6764
     buf = strchr(buf, '\0');
ddb6764
     *buf++ = DELIM;
ddb6764
 #endif
ddb6764
+#ifdef USE_EXEC_PREFIX
ddb6764
+    strcpy(buf, exec_prefix);
ddb6764
+    buf = strchr(buf, L'\0');
ddb6764
+    *buf++ = DELIM;
ddb6764
+#endif
ddb6764
     if (userpath) {
ddb6764
         strcpy(buf, userpath);
ddb6764
         buf = strchr(buf, '\0');
ddb6764
@@ -758,6 +862,17 @@ calculate_path(void)
ddb6764
         reduce(prefix);
ddb6764
         reduce(prefix);
ddb6764
     }
ddb6764
+    else
ddb6764
+        strcpy(prefix, argv0_path);
ddb6764
+#endif
ddb6764
+#ifdef USE_EXEC_PREFIX
ddb6764
+    if (efound > 0) {
ddb6764
+        reduce(exec_prefix);
ddb6764
+        reduce(exec_prefix);
ddb6764
+        reduce(exec_prefix);
ddb6764
+    }
ddb6764
+    else
ddb6764
+        strcpy(exec_prefix, argv0_path);
ddb6764
 #endif
ddb6764
     if (*prefix=='\0') {
ddb6764
         char lookBuf[MAXPATHLEN+1];
ddb6764
@@ -809,7 +924,13 @@ Py_GetPrefix(void)
ddb6764
 char *
ddb6764
 Py_GetExecPrefix(void)
ddb6764
 {
ddb6764
+#ifdef USE_EXEC_PREFIX
ddb6764
+    if (!module_search_path)
ddb6764
+        calculate_path();
ddb6764
+    return exec_prefix;
ddb6764
+#else
ddb6764
     return Py_GetPrefix();
ddb6764
+#endif
ddb6764
 }
ddb6764
 
ddb6764
 char *