summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2006-03-31 00:32:32 +0000
committerMark Mitchell <mark@codesourcery.com>2006-03-31 00:32:32 +0000
commit63220e96dbd88d990724bf25e44474cf6ce89438 (patch)
tree311f4589b702cadac3352508005d7ce190e2f86a
parentd13c4ccf32682c37bf444779d49bdbf1a382f160 (diff)
downloadbinutils-redhat-63220e96dbd88d990724bf25e44474cf6ce89438.tar.gz
* libiberty/configure.ac: Add cygpath for mingw hosts.
* libiberty.configure: Rebuilt. * libiberty/Makefile.in: Add cygpath. * libiberty/cygpath.c: New.
-rw-r--r--libiberty/Makefile.in10
-rwxr-xr-xlibiberty/configure14
-rw-r--r--libiberty/configure.ac7
-rw-r--r--libiberty/cygpath.c270
4 files changed, 299 insertions, 2 deletions
diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in
index dcd5ebd86d..77848ad592 100644
--- a/libiberty/Makefile.in
+++ b/libiberty/Makefile.in
@@ -129,7 +129,7 @@ COMPILE.c = $(CC) -c @DEFS@ $(LIBCFLAGS) -I. -I$(INCDIR) $(HDEFINES) @ac_libiber
CFILES = alloca.c argv.c asprintf.c atexit.c \
basename.c bcmp.c bcopy.c bsearch.c bzero.c \
calloc.c choose-temp.c clock.c concat.c cp-demangle.c \
- cp-demint.c cplus-dem.c \
+ cp-demint.c cplus-dem.c cygpath.c \
dyn-string.c \
fdmatch.c ffs.c fibheap.c floatformat.c fnmatch.c \
fopen_unlocked.c \
@@ -186,7 +186,7 @@ REQUIRED_OFILES = ./regex.o ./cplus-dem.o ./cp-demangle.o ./md5.o \
# maint-missing" and "make check".
CONFIGURED_OFILES = ./asprintf.o ./atexit.o \
./basename.o ./bcmp.o ./bcopy.o ./bsearch.o ./bzero.o \
- ./calloc.o ./clock.o ./copysign.o \
+ ./calloc.o ./clock.o ./copysign.o ./cygpath.o \
./_doprnt.o \
./ffs.o \
./getcwd.o ./getpagesize.o ./gettimeofday.o \
@@ -548,6 +548,12 @@ $(CONFIGURED_OFILES): stamp-picdir
else true; fi
$(COMPILE.c) $(srcdir)/cplus-dem.c $(OUTPUT_OPTION)
+./cygpath.o: $(srcdir)/cygpath.c $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/cygpath.c -o pic/$@; \
+ else true; fi
+ $(COMPILE.c) $(srcdir)/cygpath.c $(OUTPUT_OPTION)
+
./dyn-string.o: $(srcdir)/dyn-string.c config.h $(INCDIR)/ansidecl.h \
$(INCDIR)/dyn-string.h $(INCDIR)/libiberty.h
if [ x"$(PICFLAG)" != x ]; then \
diff --git a/libiberty/configure b/libiberty/configure
index 59633d520f..8a866d89f8 100755
--- a/libiberty/configure
+++ b/libiberty/configure
@@ -8205,6 +8205,20 @@ case "${host}" in
esac
+# On MinGW, add support for Cygwin paths.
+case "${host}" in
+ *-*-mingw*)
+ case $LIBOBJS in
+ "cygpath.$ac_objext" | \
+ *" cygpath.$ac_objext" | \
+ "cygpath.$ac_objext "* | \
+ *" cygpath.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS cygpath.$ac_objext" ;;
+esac
+
+ ;;
+esac
+
if test x$gcc_no_link = xyes; then
if test "x${ac_cv_func_mmap_fixed_mapped+set}" != xset; then
ac_cv_func_mmap_fixed_mapped=no
diff --git a/libiberty/configure.ac b/libiberty/configure.ac
index a57685a14e..9c1eed9bbe 100644
--- a/libiberty/configure.ac
+++ b/libiberty/configure.ac
@@ -618,6 +618,13 @@ case "${host}" in
esac
AC_SUBST(pexecute)
+# On MinGW, add support for Cygwin paths.
+case "${host}" in
+ *-*-mingw*)
+ AC_LIBOBJ([cygpath])
+ ;;
+esac
+
libiberty_AC_FUNC_STRNCMP
# Install a library built with a cross compiler in $(tooldir) rather
diff --git a/libiberty/cygpath.c b/libiberty/cygpath.c
new file mode 100644
index 0000000000..2e7b4c9c96
--- /dev/null
+++ b/libiberty/cygpath.c
@@ -0,0 +1,270 @@
+/* Support Cygwin paths under MinGW.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by CodeSourcery.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or modify it
+under the terms of the GNU Library General Public License as published
+by the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If not, write
+to the Free Software Foundation, Inc., 51 Franklin Street - Fifth
+Floor, Boston, MA 02110-1301, USA. */
+
+#include <windows.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <io.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "libiberty.h"
+
+/* If non-zero, we have attempted to use cygpath. CYGPATH_PEX may
+ still be NULL, if cygpath is unavailable. */
+static int cygpath_initialized;
+
+/* If non-NULL, an instance of cygpath connected via a pipe. */
+static struct pex_obj *cygpath_pex;
+
+/* The input to cygpath. */
+static FILE *cygpath_in;
+
+/* The output from cygpath. */
+static FILE *cygpath_out;
+
+/* CYG_PATH is a pointer to a Cygwin path. This function converts the
+ Cygwin path to a Windows path, storing the result in
+ WIN32_PATH. Returns true if the conversion was successful; false
+ otherwise. */
+static bool
+cygpath (const char *cyg_path, char win32_path[MAX_PATH + 1])
+{
+ bool ok;
+
+ if (!cygpath_initialized)
+ {
+ const char *argv[] = { "cygpath", "-w", "-f", "-", NULL };
+ const char *cygpath_path;
+ int err;
+
+ /* If we are unable to invoke cygpath, we do not want to try
+ again. So, we set the initialized flag at this point; if
+ errors occur during the invocation, it will remain set. */
+ cygpath_initialized = 1;
+ /* Check to see if the user wants cygpath support. */
+ cygpath_path = getenv ("CYGPATH");
+ if (!cygpath_path)
+ /* The user doesn't need to support Cygwin paths. */
+ goto error;
+ /* If the environment variable is set to a non-empty string, use
+ that string as the path to cygpath. */
+ if (cygpath_path[0] != '\0')
+ argv[0] = cygpath_path;
+ /* Create the pex object. */
+ cygpath_pex = pex_init (PEX_SEARCH | PEX_USE_PIPES,
+ "cygpath", NULL);
+ if (!cygpath_pex)
+ goto error;
+ /* Get the FILE we will use to write to the child. */
+ cygpath_in = pex_write_input (cygpath_pex, /*binary=*/0);
+ if (!cygpath_in)
+ goto error;
+ /* Start the child process. */
+ if (pex_run (cygpath_pex, PEX_SEARCH | PEX_USE_PIPES,
+ argv[0], (char**) argv,
+ NULL, NULL,
+ &err) != NULL)
+ goto error;
+ /* Get the FILE we will use to read from the child. */
+ cygpath_out = pex_read_output (cygpath_pex, /*binary=*/1);
+ if (!cygpath_out)
+ goto error;
+ }
+ else if (!cygpath_pex)
+ /* We previously tried to use cygpath, but something went wrong. */
+ return false;
+
+ /* Write CYG_PATH to the child, on a line by itself. */
+ if (fprintf (cygpath_in, "%s\n", cyg_path) < 0)
+ goto error;
+ /* Flush the output. (We cannot set the stream into line-buffered
+ mode with setvbuf because Windows treats _IOLBF as a synonym for
+ _IOFBF.) */
+ fflush (cygpath_in);
+ /* Read the output. */
+ ok = true;
+ while (1)
+ {
+ size_t pathlen;
+ if (!fgets (win32_path, MAX_PATH, cygpath_out))
+ goto error;
+ pathlen = strlen (win32_path);
+ if (pathlen == 0 && ok)
+ /* This isn't a well-formed response from cygpath. */
+ goto error;
+ if (win32_path[pathlen - 1] == '\n')
+ {
+ win32_path[pathlen - 1] = '\0';
+ break;
+ }
+ /* We didn't reach the end of the line. There's no point in
+ trying to use this output, since we know the length of
+ paths are limited to MAX_PATH characters, but we read the
+ entire line so that we are still in sync with
+ cygpath. */
+ ok = false;
+ }
+
+ return ok;
+
+ error:
+
+ /* Free resources. */
+ if (cygpath_out)
+ {
+ fclose (cygpath_out);
+ cygpath_out = NULL;
+ }
+ if (cygpath_in)
+ {
+ fclose (cygpath_in);
+ cygpath_in = NULL;
+ }
+ if (cygpath_pex)
+ {
+ pex_free (cygpath_pex);
+ cygpath_pex = NULL;
+ }
+
+ return false;
+}
+
+/* Returns the handle for the MVCRT DLL, or NULL if it is not
+ available. */
+static HANDLE
+msvcrt_dll (void)
+{
+ static HANDLE dll = INVALID_HANDLE_VALUE;
+
+ /* After we call LoadLibrary, DLL will be either a valid handle or
+ NULL, so this check ensures that we only try to load the library
+ once. */
+ if (dll == INVALID_HANDLE_VALUE)
+ dll = LoadLibrary ("msvcrt.dll");
+
+ return dll;
+}
+
+/* Call the underlying MSVCRT fopen with PATH and MODE, and return
+ what it returns. */
+static FILE *
+msvcrt_fopen (const char *path, const char *mode)
+{
+ typedef FILE *(fopen_type)(const char *path,
+ const char *mode);
+
+ static fopen_type *f = NULL;
+
+ /* Get the address of "fopen". */
+ if (!f)
+ {
+ HANDLE dll = msvcrt_dll ();
+ if (!dll)
+ {
+ errno = ENOSYS;
+ return NULL;
+ }
+ f = (fopen_type *) GetProcAddress (dll, "fopen");
+ if (!f)
+ {
+ errno = ENOSYS;
+ return NULL;
+ }
+ }
+
+ /* Call fopen. */
+ return (*f)(path, mode);
+}
+
+FILE *
+fopen (const char *path, const char *mode)
+{
+ FILE *f;
+ char win32_path[MAX_PATH + 1];
+
+ /* Assume PATH is a Windows path. */
+ f = msvcrt_fopen (path, mode);
+ if (f || errno != ENOENT)
+ return f;
+ /* Perhaps it is a Cygwin path? */
+ if (cygpath (path, win32_path))
+ f = msvcrt_fopen (win32_path, mode);
+ return f;
+}
+
+int
+open (const char *path, int oflag, ...)
+{
+ int fd;
+ char win32_path[MAX_PATH + 1];
+ int pmode = 0;
+
+ if ((oflag & _O_CREAT))
+ {
+ va_list ap;
+ va_start (ap, oflag);
+ pmode = va_arg (ap, int);
+ va_end (ap);
+ }
+
+ /* Assume PATH is a Windows path. */
+ fd = _open (path, oflag, pmode);
+ if (fd != -1 || errno != ENOENT)
+ return fd;
+ /* Perhaps it is a Cygwin path? */
+ if (cygpath (path, win32_path))
+ fd = _open (win32_path, oflag, pmode);
+ return fd;
+}
+
+int
+stat (const char *path, struct stat *buffer)
+{
+ int r;
+ char win32_path[MAX_PATH + 1];
+
+ /* Assume PATH is a Windows path. */
+ r = _stat (path, (struct _stat *) buffer);
+ if (r != -1 || errno != ENOENT)
+ return r;
+ /* Perhaps it is a Cygwin path? */
+ if (cygpath (path, win32_path))
+ r = _stat (win32_path, (struct _stat *) buffer);
+ return r;
+}
+
+int
+access (const char *path, int mode)
+{
+ int r;
+ char win32_path[MAX_PATH + 1];
+
+ /* Assume PATH is a Windows path. */
+ r = _access (path, mode);
+ if (r != -1 || errno != ENOENT)
+ return r;
+ /* Perhaps it is a Cygwin path? */
+ if (cygpath (path, win32_path))
+ r = _access (win32_path, mode);
+ return r;
+}