Attached patch fixes PR libfortran/23262 (and 23264): we need to switch
I/ to binary-mode (instead of text-mode) on mingw32. With text-mode,
the I/ 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 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/ on mingw32.
K for 4.0 and mainline?
FX
Index: libgfortran/acinclude.m4
RCS file: /,v
retrieving revision 1.6
diff -p -u -r1.6 acinclude.m4
libgfortran/acinclude.m427 Aug 2005 16:01:51 -00001.6
libgfortran/acinclude.m43 Sep 2005 17:07:26 -0000
@@ -183,3 +183,50 @@ esac])])
if test x"$have_unlink_open_file" = xyes; then
AC_DEFINE(HAVE_UNLINKPEN_FILE, 1, [Define if target can unlink open files.])
fi])
+
+dnl Check whether CRLF is the line terminator
+AC_DEFUN([LIBGFR_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 BINARY
+ exit(1);
+#else
+ int fd, bytes;
+ char buff[5];
+
+ fd = open ("foo", WRNLY | CREAT | TRUNC, S_IRWXU);
+ if (fd < 0)
+ exit(1);
+ if (write (fd, "\n", 1) < 0)
+ perror ("write");
+
+ close (fd);
+
+ if ((fd = open ("foo", RDNLY | 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: /,v
retrieving revision 1.32
diff -p -u -r1.32 configure.ac
libgfortran/configure.ac2 Sep 2005 20:24:49 -00001.32
libgfortran/configure.ac3 Sep 2005 17:07:27 -0000
@@ -261,6 +261,12 @@ LIBGFR_CHECK_ATTRIBUTE_ALIAS
# Various other checks on target
LIBGFR_CHECK_UNLINKPEN_FILE
+# Check whether line terminator is LF or CRLF
+LIBGFR_CHECK_CRLF
+
AC_CACHE_SAVE
if test ${multilib} = yes; then
Index: libgfortran/io/transfer.c
RCS file: /,v
retrieving revision 1.54
diff -p -u -r1.54 transfer.c
libgfortran/io/transfer.c17 Aug 2005 02:48:57 -00001.54
libgfortran/io/transfer.c3 Sep 2005 17:07:27 -0000
@@ -1412,13 +1412,24 @@ next_record_w (void)
break;
case FRMATTED_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: /,v
retrieving revision 1.36
diff -p -u -r1.36 unix.c
libgfortran/io/unix.c2 Sep 2005 20:24:49 -00001.36
libgfortran/io/unix.c3 Sep 2005 17:07:27 -0000
@@ -1000,7 +1000,12 @@ tempfile (void)
if (mktemp (template))
do
+#ifdef HAVE_CRLF
+ fd = open (template, RDWR | CREAT | EXCL | BINARY,
+ S_IREAD | S_IWRITE);
+#else
fd = open (template, RDWR | CREAT | 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 |= LARGEFILE; */
+
+#ifdef HAVE_CRLF
+ crflag |= BINARY;
+#endif
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IRTH | S_IWTH;
fd = open (path, rwflag | crflag, mode);
2005-09-03 Francois-Xavier Coudert <coudert (AT) clipper (DOT) ens.fr>
* acinclude.m4 (LIBGFR_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): files with
BINARY on systems with CRLF.