diff --git a/mingw-w64-bison/002-add-relocation-support.patch b/mingw-w64-bison/002-add-relocation-support.patch new file mode 100644 index 0000000000..e07b157f7f --- /dev/null +++ b/mingw-w64-bison/002-add-relocation-support.patch @@ -0,0 +1,359 @@ +diff -urN bison-3.0.2.orig/src/files.c bison-3.0.2/src/files.c +--- bison-3.0.2.orig/src/files.c 2014-08-03 21:05:59.361540700 +0100 ++++ bison-3.0.2/src/files.c 2014-08-03 21:07:19.351115800 +0100 +@@ -18,6 +18,7 @@ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + ++ + #include + #include "system.h" + +@@ -34,6 +35,22 @@ + #include "getargs.h" + #include "gram.h" + ++/* If you don't define this, then get_executable_path() ++ can only use argv[0] which will often not work well */ ++#define IMPLEMENT_SYS_GET_EXECUTABLE_PATH ++ ++#if defined(IMPLEMENT_SYS_GET_EXECUTABLE_PATH) ++#if defined(__linux__) || defined(__CYGWIN__) || defined(__MSYS__) ++/* Nothing needed, unistd.h is enough. */ ++#elif defined(__APPLE__) ++#include ++#elif defined(_WIN32) ++#define WIN32_LEAN_AND_MEAN ++#include ++#include ++#endif ++#endif /* defined(IMPLEMENT_SYS_GET_EXECUTABLE_PATH) */ ++ + /* Initializing some values below (such SPEC_NAME_PREFIX to 'yy') is + tempting, but don't do that: for the time being our handling of the + %directive vs --option leaves precedence to the options by deciding +@@ -425,3 +442,277 @@ + } + free (generated_files); + } ++ ++char * ++malloc_copy_string (char const * original) ++{ ++ char * result = (char *) malloc (sizeof(char*) * strlen(original)+1); ++ if (result != NULL) ++ { ++ strcpy (result, original); ++ } ++ return result; ++} ++ ++static char * ++sanitise_path(char * path) ++{ ++ size_t path_size = strlen(path); ++ ++ /* Replace any '\' with '/' */ ++ char * path_p = path; ++ while ((path_p = strchr(path_p, '\\')) != NULL) ++ { ++ *path_p = '/'; ++ } ++ /* Replace any '//' with '/' */ ++ path_p = path; ++ while ((path_p = strstr(path_p, "//")) != NULL) ++ { ++ memmove(path_p, path_p + 1, path_size--); ++ } ++ return path; ++} ++ ++void ++simplify_path (char * path) ++{ ++ ssize_t n_toks = 1; /* in-case we need an empty initial token. */ ++ ssize_t i, j; ++ size_t tok_size; ++ size_t in_size = strlen (path); ++ int it_ended_with_a_slash = (path[in_size - 1] == '/') ? 1 : 0; ++ char * result = path; ++ char * result_p = sanitise_path(result); ++ ++ do ++ { ++ ++n_toks; ++ ++result_p; ++ } while ((result_p = strchr(result_p, '/')) != NULL); ++ ++ result_p = result; ++ char const ** toks = (char const **) alloca (sizeof(char const*) * n_toks); ++ n_toks = 0; ++ do ++ { ++ if (result_p > result) ++ { ++ *result_p++ = '\0'; ++ } ++ else if (*result_p == '/') ++ { ++ /* A leading / creates an empty initial token. */ ++ toks[n_toks++] = result_p; ++ *result_p++ = '\0'; ++ } ++ toks[n_toks++] = result_p; ++ } while ((result_p = strchr(result_p, '/')) != NULL); ++ ++ /* Remove all non-leading '.' and any '..' we can match ++ with an earlier forward path (i.e. neither '.' nor '..') */ ++ for (i = 1; i < n_toks; ++i) ++ { ++ int removals[2] = { -1, -1 }; ++ if ( strcmp (toks[i], "." ) == 0) ++ { ++ removals[0] = i; ++ } ++ else if ( strcmp (toks[i], ".." ) == 0) ++ { ++ /* Search backwards for a forward path to collapse. ++ If none are found then the .. also stays. */ ++ for (j = i - 1; j > -1; --j) ++ { ++ if ( strcmp (toks[j], "." ) ++ && strcmp (toks[j], ".." ) ) ++ { ++ removals[0] = j; ++ removals[1] = i; ++ break; ++ } ++ } ++ } ++ for (j = 0; j < 2; ++j) ++ { ++ if (removals[j] >= 0) /* Can become -2 */ ++ { ++ --n_toks; ++ memmove (&toks[removals[j]], &toks[removals[j]+1], (n_toks - removals[j])*sizeof(char*)); ++ --i; ++ if (!j) ++ { ++ --removals[1]; ++ } ++ } ++ } ++ } ++ result_p = result; ++ for (i = 0; i < n_toks; ++i) ++ { ++ tok_size = strlen(toks[i]); ++ memcpy (result_p, toks[i], tok_size); ++ result_p += tok_size; ++ if ((!i || tok_size) && ((i < n_toks - 1) || it_ended_with_a_slash == 1)) ++ { ++ *result_p = '/'; ++ ++result_p; ++ } ++ } ++ *result_p = '\0'; ++} ++ ++char * ++get_relative_path (char const * from, char const * to) ++{ ++ size_t from_size = strlen (from); ++ size_t to_size = strlen (to); ++ size_t max_size = (from_size + to_size) * 2 + 4; ++ char * common_part = (char *) alloca (max_size); ++ char * result = (char *) alloca (max_size); ++ size_t count; ++ ++ /* If either alloca failed, no from was given, from is not absolute ++ or either to or from contains '.' then return a copy of to; it's ++ the best we can do in this instance (though we could call a path ++ normalization function for some of these conditions). ++ */ ++ if (common_part == NULL ++ || result == NULL ++ || from == NULL ++ || from[0] != '/' ++ || strchr(to, '.') != NULL ++ || strchr(from, '.') != NULL) ++ { ++ return malloc_copy_string (to); ++ } ++ ++ printf ("source : %s\n", from); ++ printf ("target : %s\n", to); ++ ++ result[0] = '\0'; ++ ++ size_t match_size_dirsep = 0; /* The match size up to the last /. Always wind back to this - 1 */ ++ size_t match_size = 0; /* The running (and final) match size. */ ++ size_t largest_size = (from_size > to_size) ? from_size : to_size; ++ int to_final_is_slash = (to[to_size-1] == '/') ? 1 : 0; ++ char from_c; ++ char to_c; ++ for (match_size = 0; match_size < largest_size; ++match_size) ++ { ++ /* To simplify the logic, always pretend the strings end with '/' */ ++ from_c = (match_size < from_size) ? from[match_size] : '/'; ++ to_c = (match_size < to_size) ? to[match_size] : '/'; ++ ++ if (from_c != to_c) ++ { ++ if (from_c != '\0' || to_c != '\0') ++ { ++ match_size = match_size_dirsep; ++ } ++ break; ++ } ++ else if (from_c == '/') ++ { ++ match_size_dirsep = match_size; ++ } ++ } ++ strncpy (common_part, from, match_size); ++ common_part[match_size] = '\0'; ++ from += match_size; ++ to += match_size; ++ size_t ndotdots = 0; ++ char const* from_last = from + strlen(from) - 1; ++ while ((from = strchr(from, '/')) && from != from_last) ++ { ++ ++ndotdots; ++ ++from; ++ } ++ for (count = 0; count < ndotdots; ++count) ++ { ++ strcat(result, "../"); ++ } ++ if (strlen(to) > 0) ++ { ++ strcat(result, to+1); ++ } ++ /* Make sure that if to ends with '/' result does the same, and ++ vice-versa. */ ++ size_t size_result = strlen(result); ++ if ((to_final_is_slash == 1) ++ && (!size_result || result[size_result-1] != '/')) ++ { ++ strcat (result, "/"); ++ } ++ else if (!to_final_is_slash ++ && size_result && result[size_result-1] == '/') ++ { ++ result[size_result-1] = '\0'; ++ } ++ ++ return malloc_copy_string (result); ++} ++ ++int ++get_executable_path(char const * argv0, char * result, ssize_t max_size) ++{ ++ char * system_result = (char *) alloca (max_size); ++ ssize_t system_result_size = -1; ++ ssize_t result_size = -1; ++ ++ if (system_result != NULL) ++ { ++#if defined(IMPLEMENT_SYS_GET_EXECUTABLE_PATH) ++#if defined(__linux__) || defined(__CYGWIN__) || defined(__MSYS__) ++ system_result_size = readlink("/proc/self/exe", system_result, max_size); ++#elif defined(__APPLE__) ++ uint32_t bufsize = (uint32_t)max_size; ++ if (_NSGetExecutablePath(system_result, &bufsize) == 0) ++ { ++ system_result_size = (ssize_t)bufsize; ++ } ++#elif defined(_WIN32) ++ unsigned long bufsize = (unsigned long)max_size; ++ system_result_size = GetModuleFileNameA(NULL, system_result, bufsize); ++ if (system_result_size == 0 || system_result_size == bufsize) ++ { ++ /* Error, possibly not enough space. */ ++ system_result_size = -1; ++ } ++ else ++ { ++ /* Early conversion to unix slashes instead of more changes ++ everywhere else .. */ ++ char * winslash; ++ system_result[system_result_size] = '\0'; ++ while ((winslash = strchr (system_result, '\\')) != NULL) ++ { ++ *winslash = '/'; ++ } ++ } ++#else ++#warning "Don't know how to get executable path on this system" ++#endif ++#endif ++ } ++ /* Use argv0 as a default in-case of failure */ ++ if (system_result_size != -1) ++ { ++ strncpy (result, system_result, system_result_size); ++ result[system_result_size] = '\0'; ++ } ++ else ++ { ++ if (argv0 != NULL) ++ { ++ strncpy (result, argv0, max_size); ++ result[max_size-1] = '\0'; ++ } ++ else ++ { ++ result[0] = '\0'; ++ } ++ } ++ result_size = strlen (result); ++ return result_size; ++} +diff -urN bison-3.0.2.orig/src/files.h bison-3.0.2/src/files.h +--- bison-3.0.2.orig/src/files.h 2014-08-03 21:05:59.367541000 +0100 ++++ bison-3.0.2/src/files.h 2014-08-03 21:06:17.520579300 +0100 +@@ -77,4 +77,20 @@ + void xfclose (FILE *ptr); + FILE *xfdopen (int fd, char const *mode); + ++/* These functions are used to support relocation. On MSYS2, the native ++ bison port needs this. */ ++ ++/* Returns the malloc'ed string. Caller should free using free(void*) */ ++extern char * malloc_copy_string (char const * original); ++ ++/* Uses a host OS specific function to determine the path of the executable, ++ if IMPLEMENT_SYS_GET_EXECUTABLE_PATH is defined, otherwise uses argv0. */ ++extern int get_executable_path(char const * argv0, char * result, ssize_t max_size); ++ ++/* Where possible, removes occourances of '.' and 'path/..' */ ++extern void simplify_path (char * path); ++ ++/* mallocs and returns the path to get from from to to. Caller should free using free(void*) */ ++extern char * get_relative_path (char const * from, char const * to); ++ + #endif /* !FILES_H_ */ +diff -urN bison-3.0.2.orig/src/output.c bison-3.0.2/src/output.c +--- bison-3.0.2.orig/src/output.c 2014-08-03 21:05:59.363540800 +0100 ++++ bison-3.0.2/src/output.c 2014-08-03 21:06:17.521579400 +0100 +@@ -716,5 +716,18 @@ + pkgdatadir (void) + { + char const *cp = getenv ("BISON_PKGDATADIR"); +- return cp ? cp : PKGDATADIR; ++ if (cp) ++ return cp; ++ ++ /* Relocation support. */ ++ char exe_path[PATH_MAX]; ++ get_executable_path (NULL, &exe_path[0], sizeof(exe_path)/sizeof(exe_path[0])); ++ if (strrchr (exe_path, '/') != NULL) ++ { ++ strrchr (exe_path, '/')[1] = '\0'; ++ } ++ char * rel_to_datadir = get_relative_path (BINDIR, PKGDATADIR); ++ strcat (exe_path, rel_to_datadir); ++ simplify_path (&exe_path[0]); ++ return malloc_copy_string (exe_path); + } diff --git a/mingw-w64-bison/PKGBUILD b/mingw-w64-bison/PKGBUILD index 420423b1b4..65a5592ab9 100644 --- a/mingw-w64-bison/PKGBUILD +++ b/mingw-w64-bison/PKGBUILD @@ -1,4 +1,5 @@ # Maintainer: Alexey Pavlov +# Contributor: Ray Donnelly _realname=bison pkgname="${MINGW_PACKAGE_PREFIX}-${_realname}" @@ -9,33 +10,36 @@ arch=('any') license=('GPL3') url="http://www.gnu.org/software/bison/bison.html" depends=("${MINGW_PACKAGE_PREFIX}-m4") -source=(http://ftp.gnu.org/gnu/bison/${_realname}-${pkgver}.tar.xz{,.sig} - 001-use-gnu_printf.patch) +source=(http://ftp.gnu.org/gnu/bison/${_realname}-${pkgver}.tar.xz + 001-use-gnu_printf.patch + 002-add-relocation-support.patch) md5sums=('146be9ff9fbd27497f0bf2286a5a2082' - 'SKIP' - '817bbd1f0de3d7f2ab1287b67b267895') + '817bbd1f0de3d7f2ab1287b67b267895' + '14236b43f975e1e51e054267304e34b1') prepare() { cd ${srcdir}/${_realname}-${pkgver} patch -p1 -i ${srcdir}/001-use-gnu_printf.patch - + patch -p1 -i ${srcdir}/002-add-relocation-support.patch + #autoreconf -vfi } build() { cd ${srcdir}/${_realname}-${pkgver} - ./configure \ - --prefix=${MINGW_PREFIX} \ - --build=${MINGW_CHOST} \ - --host=${MINGW_CHOST} \ - --target=${MINGW_CHOST} + M4=$(cygpath -wm ${MINGW_PREFIX})/bin/m4.exe \ + ./configure \ + --prefix=${MINGW_PREFIX} \ + --build=${MINGW_CHOST} \ + --host=${MINGW_CHOST} \ + --target=${MINGW_CHOST} make } check() { cd ${srcdir}/${_realname}-${pkgver} - make check + make -j1 check } package() {