This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gfortran,patch] Fix PR libfortran/23262 (on mingw32)
- From: FX Coudert <fxcoudert at gmail dot com>
- To: gfortran <fortran at gcc dot gnu dot org>, patch <gcc-patches at gcc dot gnu dot org>
- Date: Sat, 03 Sep 2005 21:20:49 +0200
- Subject: [gfortran,patch] Fix PR libfortran/23262 (on mingw32)
Attached patch fixes PR libfortran/23262 (and 23264): we need to switch
I/O to binary-mode (instead of text-mode) on mingw32. With text-mode,
the I/O library makes magical things with newlines, but it makes it
impossible to use lseek and ftruncate. So, we need not to use them, and
take care ourselves of outputting the right newline characters.
The patch adds a configure test (compile-test, with target-based guess
for cross-compilers) to know whether target is a system with CRLF line
terminator (and has O_BINARY open() flag available). This case, AFAIK,
does arise only for mingw32.
This does not change things on platforms other than mingw32, but it
definetely improve I/O on mingw32.
OK for 4.0 and mainline?
FX
Index: libgfortran/acinclude.m4
===================================================================
RCS file: /cvsroot/gcc/gcc/libgfortran/acinclude.m4,v
retrieving revision 1.6
diff -p -u -r1.6 acinclude.m4
--- libgfortran/acinclude.m4 27 Aug 2005 16:01:51 -0000 1.6
+++ libgfortran/acinclude.m4 3 Sep 2005 17:07:26 -0000
@@ -183,3 +183,50 @@ esac])])
if test x"$have_unlink_open_file" = xyes; then
AC_DEFINE(HAVE_UNLINK_OPEN_FILE, 1, [Define if target can unlink open files.])
fi])
+
+dnl Check whether CRLF is the line terminator
+AC_DEFUN([LIBGFOR_CHECK_CRLF], [
+ AC_CACHE_CHECK([whether the target has CRLF as line terminator],
+ have_crlf, [
+ AC_TRY_RUN([
+/* This test program should exit with status 0 if system uses a CRLF as
+ line terminator, and status 1 otherwise.
+ Since it is used to check for mingw systems, and should return 0 in any
+ other case, in case of a failure we will not use CRLF. */
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+int main ()
+{
+#ifndef O_BINARY
+ exit(1);
+#else
+ int fd, bytes;
+ char buff[5];
+
+ fd = open ("foo", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
+ if (fd < 0)
+ exit(1);
+ if (write (fd, "\n", 1) < 0)
+ perror ("write");
+
+ close (fd);
+
+ if ((fd = open ("foo", O_RDONLY | O_BINARY, S_IRWXU)) < 0)
+ exit(1);
+ bytes = read (fd, buff, 5);
+ if (bytes == 2 && buff[0] == '\r' && buff[1] == '\n')
+ exit(0);
+ else
+ exit(1);
+#endif
+}], have_crlf=yes, have_crlf=no, [
+case "${target}" in
+ *mingw*) have_crlf=yes ;;
+ *) have_crlf=no;;
+esac])])
+if test x"$have_crlf" = xyes; then
+ AC_DEFINE(HAVE_CRLF, 1, [Define if CRLF is line terminator.])
+fi])
Index: libgfortran/configure.ac
===================================================================
RCS file: /cvsroot/gcc/gcc/libgfortran/configure.ac,v
retrieving revision 1.32
diff -p -u -r1.32 configure.ac
--- libgfortran/configure.ac 2 Sep 2005 20:24:49 -0000 1.32
+++ libgfortran/configure.ac 3 Sep 2005 17:07:27 -0000
@@ -261,6 +261,12 @@ LIBGFOR_CHECK_ATTRIBUTE_ALIAS
# Various other checks on target
LIBGFOR_CHECK_UNLINK_OPEN_FILE
+# Check whether line terminator is LF or CRLF
+LIBGFOR_CHECK_CRLF
+
AC_CACHE_SAVE
if test ${multilib} = yes; then
Index: libgfortran/io/transfer.c
===================================================================
RCS file: /cvsroot/gcc/gcc/libgfortran/io/transfer.c,v
retrieving revision 1.54
diff -p -u -r1.54 transfer.c
--- libgfortran/io/transfer.c 17 Aug 2005 02:48:57 -0000 1.54
+++ libgfortran/io/transfer.c 3 Sep 2005 17:07:27 -0000
@@ -1412,13 +1412,24 @@ next_record_w (void)
break;
case FORMATTED_SEQUENTIAL:
+#ifdef HAVE_CRLF
+ length = 2;
+#else
length = 1;
+#endif
p = salloc_w (current_unit->s, &length);
if (!is_internal_unit())
{
if (p)
- *p = '\n'; /* No CR for internal writes. */
+ { /* No new line for internal writes. */
+#ifdef HAVE_CRLF
+ p[0] = '\r';
+ p[1] = '\n';
+#else
+ *p = '\n';
+#endif
+ }
else
goto io_error;
}
Index: libgfortran/io/unix.c
===================================================================
RCS file: /cvsroot/gcc/gcc/libgfortran/io/unix.c,v
retrieving revision 1.36
diff -p -u -r1.36 unix.c
--- libgfortran/io/unix.c 2 Sep 2005 20:24:49 -0000 1.36
+++ libgfortran/io/unix.c 3 Sep 2005 17:07:27 -0000
@@ -1000,7 +1000,12 @@ tempfile (void)
if (mktemp (template))
do
+#ifdef HAVE_CRLF
+ fd = open (template, O_RDWR | O_CREAT | O_EXCL | O_BINARY,
+ S_IREAD | S_IWRITE);
+#else
fd = open (template, O_RDWR | O_CREAT | O_EXCL, S_IREAD | S_IWRITE);
+#endif
while (!(fd == -1 && errno == EEXIST) && mktemp (template));
else
fd = -1;
@@ -1084,6 +1089,10 @@ regular_file (unit_flags *flags)
}
/* rwflag |= O_LARGEFILE; */
+
+#ifdef HAVE_CRLF
+ crflag |= O_BINARY;
+#endif
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
fd = open (path, rwflag | crflag, mode);
2005-09-03 Francois-Xavier Coudert <coudert@clipper.ens.fr>
* acinclude.m4 (LIBGFOR_CHECK_CRLF): New check.
* configure.ac: Use new check.
* configure.in: Regenerate.
* config.h.in: Regenerate.
* configure: Regenerate.
* io/transfer.c (next_record_w): Add case for CRLF as line
terminator.
* io/unix.c (tempfile, regular_file): Open files with
O_BINARY on systems with CRLF.