This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]