bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

ftell on mingw


From: Eric Blake
Subject: ftell on mingw
Date: Sat, 29 Mar 2008 17:07:26 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080213 Thunderbird/2.0.0.12 Mnenhy/0.7.5.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

ftell failed to compile on mingw due to missing EOVERFLOW (I hadn't
noticed this, since M4 was using only ftello).  In the process of fixing
this, I also beefed up the ftell/o tests to check behavior after ungetc.
Mingw ftell is weird when used on text mode files with plain LF endings
(it subtracts 1 for each LF in the stripped readahead buffer, whether or
not it was CRLF prior to copying into the readahead buffer, such that it
can return negative results even though the file is seekable), so I also
had to make the test force binary mode.

Hmm - should we provide a gnulib <errno.h> that guarantees all of the
standard errors, rather than doing an ad-hoc definition of EOVERFLOW and
others in every place where they are used?  Or is it even possible, since
errno.h is not required to do anything more than macros, such that
include_next won't necessarily find the system <errno.h>?

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkfuy60ACgkQ84KuGfSFAYA7EgCfSrXMfD7rKjvt0BHqjRFGGcKl
YeUAn0APLk0TKqHhso3sQjpK27g2yrWd
=nUXF
-----END PGP SIGNATURE-----
>From 857523660ddabbf1e4bba1c6f5f322451991fa08 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Sat, 29 Mar 2008 16:55:56 -0600
Subject: [PATCH] Fix ftell on mingw.

* lib/ftell.c (EOVERFLOW): Define if the system lacks it.
* modules/ftell-tests (Depends-on): Add binary-io.
* modules/ftello-tests (Depends-on): Likewise.
* tests/test-ftell.c (main): Enhance test to cover behavior after
ungetc.  Enforce binary mode.
* tests/test-ftello.c (main): Likewise.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog            |    8 ++++
 lib/ftell.c          |    7 +++-
 modules/ftell-tests  |    1 +
 modules/ftello-tests |    1 +
 tests/test-ftell.c   |   74 +++++++++++++++++++++++++++++++++++++++--
 tests/test-ftello.c  |   89 +++++++++++++++++++++++++++++++++++++++++++++----
 6 files changed, 168 insertions(+), 12 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5b5933c..f6c7dc0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2008-03-29  Eric Blake  <address@hidden>
 
+       Fix ftell on mingw.
+       * lib/ftell.c (EOVERFLOW): Define if the system lacks it.
+       * modules/ftell-tests (Depends-on): Add binary-io.
+       * modules/ftello-tests (Depends-on): Likewise.
+       * tests/test-ftell.c (main): Enhance test to cover behavior after
+       ungetc.  Enforce binary mode.
+       * tests/test-ftello.c (main): Likewise.
+
        Pass test-freadseek on cygwin.
        * modules/freadseek (Depends-on): Use freadptr, not freadseek.
        * lib/freadseek.c (freadseek): Don't increment beyond bounds of
diff --git a/lib/ftell.c b/lib/ftell.c
index 84622d7..e586fdb 100644
--- a/lib/ftell.c
+++ b/lib/ftell.c
@@ -1,5 +1,5 @@
 /* An ftell() function that works around platform bugs.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -23,6 +23,11 @@
 /* Get off_t.  */
 #include <unistd.h>
 
+/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW.  */
+#ifndef EOVERFLOW
+# define EOVERFLOW E2BIG
+#endif
+
 long
 ftell (FILE *fp)
 {
diff --git a/modules/ftell-tests b/modules/ftell-tests
index 03fbf27..ad82ded 100644
--- a/modules/ftell-tests
+++ b/modules/ftell-tests
@@ -3,6 +3,7 @@ tests/test-ftell.c
 tests/test-ftell.sh
 
 Depends-on:
+binary-io
 
 configure.ac:
 
diff --git a/modules/ftello-tests b/modules/ftello-tests
index 9f0c6e2..48179bc 100644
--- a/modules/ftello-tests
+++ b/modules/ftello-tests
@@ -3,6 +3,7 @@ tests/test-ftello.c
 tests/test-ftello.sh
 
 Depends-on:
+binary-io
 
 configure.ac:
 
diff --git a/tests/test-ftell.c b/tests/test-ftell.c
index 05e393d..e25bc02 100644
--- a/tests/test-ftell.c
+++ b/tests/test-ftell.c
@@ -1,5 +1,5 @@
 /* Test of ftell() function.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -19,11 +19,79 @@
 #include <config.h>
 
 #include <stdio.h>
+#include <stdlib.h>
+
+#include "binary-io.h"
+
+#define ASSERT(expr) \
+  do                                                                        \
+    {                                                                       \
+      if (!(expr))                                                          \
+        {                                                                   \
+          fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+          abort ();                                                         \
+        }                                                                   \
+    }                                                                       \
+  while (0)
 
 int
 main (int argc, char **argv)
 {
+  int ch;
   /* Assume stdin is seekable iff argc > 1.  */
-  int expected = argc > 1 ? 0 : -1;
-  return ftell (stdin) != expected;
+  if (argc == 1)
+    {
+      ASSERT (ftell (stdin) == -1);
+      return 0;
+    }
+
+  /* mingw ftell is unreliable on text mode input.  */
+  SET_BINARY (0);
+
+  /* Simple tests.  */
+  ASSERT (ftell (stdin) == 0);
+
+  ch = fgetc (stdin);
+  ASSERT (ch == '#');
+  ASSERT (ftell (stdin) == 1);
+
+  /* Test ftell after ungetc of read input.  */
+  ch = ungetc ('#', stdin);
+  ASSERT (ch == '#');
+  ASSERT (ftell (stdin) == 0);
+
+  ch = fgetc (stdin);
+  ASSERT (ch == '#');
+  ASSERT (ftell (stdin) == 1);
+
+  /* Test ftell after fseek.  */
+  ASSERT (fseek (stdin, 2, SEEK_SET) == 0);
+  ASSERT (ftell (stdin) == 2);
+
+  /* Test ftell after random ungetc.  */
+  ch = fgetc (stdin);
+  ASSERT (ch == '/');
+  ch = ungetc ('@', stdin);
+  ASSERT (ch == '@');
+  ASSERT (ftell (stdin) == 2);
+
+  ch = fgetc (stdin);
+  ASSERT (ch == '@');
+  ASSERT (ftell (stdin) == 3);
+
+  /* Test ftell after ungetc without read.  */
+  ASSERT (fseek (stdin, 0, SEEK_CUR) == 0);
+  ASSERT (ftell (stdin) == 3);
+
+  ch = ungetc ('~', stdin);
+  ASSERT (ch == '~');
+  ASSERT (ftell (stdin) == 2);
+
+  /* Test ftell beyond end of file.  */
+  ASSERT (fseek (stdin, 0, SEEK_END) == 0);
+  ch = ftell (stdin);
+  ASSERT (fseek (stdin, 10, SEEK_END) == 0);
+  ASSERT (ftell (stdin) == ch + 10);
+
+  return 0;
 }
diff --git a/tests/test-ftello.c b/tests/test-ftello.c
index 0357282..73fd527 100644
--- a/tests/test-ftello.c
+++ b/tests/test-ftello.c
@@ -1,5 +1,5 @@
 /* Test of ftello() function.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -19,17 +19,90 @@
 #include <config.h>
 
 #include <stdio.h>
+#include <stdlib.h>
 
-/* Get off_t.  */
-#include <sys/types.h>
+#include "binary-io.h"
+
+#define ASSERT(expr) \
+  do                                                                        \
+    {                                                                       \
+      if (!(expr))                                                          \
+        {                                                                   \
+          fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+          abort ();                                                         \
+        }                                                                   \
+    }                                                                       \
+  while (0)
 
 int
 main (int argc, char **argv)
 {
+  int ch;
   /* Assume stdin is seekable iff argc > 1.  */
-  int expected = argc > 1 ? 0 : -1;
-  /* Exit with success only if ftell/ftello agree.  */
-  off_t pos1 = ftello (stdin);
-  long pos2 = ftell (stdin);
-  return ! (pos1 == pos2 && pos1 == expected);
+  if (argc == 1)
+    {
+      ASSERT (ftell (stdin) == -1);
+      ASSERT (ftello (stdin) == -1);
+      return 0;
+    }
+
+  /* mingw ftell is unreliable on text mode input.  */
+  SET_BINARY (0);
+
+  /* Simple tests.  For each test, make sure ftell and ftello agree.  */
+  ASSERT (ftell (stdin) == 0);
+  ASSERT (ftello (stdin) == 0);
+
+  ch = fgetc (stdin);
+  ASSERT (ch == '#');
+  ASSERT (ftell (stdin) == 1);
+  ASSERT (ftello (stdin) == 1);
+
+  /* Test ftell after ungetc of read input.  */
+  ch = ungetc ('#', stdin);
+  ASSERT (ch == '#');
+  ASSERT (ftell (stdin) == 0);
+  ASSERT (ftello (stdin) == 0);
+
+  ch = fgetc (stdin);
+  ASSERT (ch == '#');
+  ASSERT (ftell (stdin) == 1);
+  ASSERT (ftello (stdin) == 1);
+
+  /* Test ftell after fseek.  */
+  ASSERT (fseek (stdin, 2, SEEK_SET) == 0);
+  ASSERT (ftell (stdin) == 2);
+  ASSERT (ftello (stdin) == 2);
+
+  /* Test ftell after random ungetc.  */
+  ch = fgetc (stdin);
+  ASSERT (ch == '/');
+  ch = ungetc ('@', stdin);
+  ASSERT (ch == '@');
+  ASSERT (ftell (stdin) == 2);
+  ASSERT (ftello (stdin) == 2);
+
+  ch = fgetc (stdin);
+  ASSERT (ch == '@');
+  ASSERT (ftell (stdin) == 3);
+  ASSERT (ftello (stdin) == 3);
+
+  /* Test ftell after ungetc without read.  */
+  ASSERT (fseek (stdin, 0, SEEK_CUR) == 0);
+  ASSERT (ftell (stdin) == 3);
+  ASSERT (ftello (stdin) == 3);
+
+  ch = ungetc ('~', stdin);
+  ASSERT (ch == '~');
+  ASSERT (ftell (stdin) == 2);
+  ASSERT (ftello (stdin) == 2);
+
+  /* Test ftell beyond end of file.  */
+  ASSERT (fseek (stdin, 0, SEEK_END) == 0);
+  ch = ftello (stdin);
+  ASSERT (fseek (stdin, 10, SEEK_END) == 0);
+  ASSERT (ftell (stdin) == ch + 10);
+  ASSERT (ftello (stdin) == ch + 10);
+
+  return 0;
 }
-- 
1.5.4


reply via email to

[Prev in Thread] Current Thread [Next in Thread]