Fix ftell on mingw.
authorEric Blake <ebb9@byu.net>
Sat, 29 Mar 2008 22:55:56 +0000 (16:55 -0600)
committerEric Blake <ebb9@byu.net>
Sat, 29 Mar 2008 22:55:56 +0000 (16:55 -0600)
* 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 <ebb9@byu.net>
ChangeLog
lib/ftell.c
modules/ftell-tests
modules/ftello-tests
tests/test-ftell.c
tests/test-ftello.c

index 5b5933c0e30d9d7dabeb7673ce9a34a2ecd81e30..f6c7dc0d3d0846ddd5011444eed17d5ac3894277 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2008-03-29  Eric Blake  <ebb9@byu.net>
 
+       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
index 84622d7133e8cb009fcec2306130c88378b00590..e586fdb81cfcca3289e85f441e7d9e6a6dcf736a 100644 (file)
@@ -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
 /* 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)
 {
index 03fbf272ad2b15fe517f1b56a2893ef5a0e298e3..ad82ded0a26e7c83a329bb793d7ff4467ae83f1b 100644 (file)
@@ -3,6 +3,7 @@ tests/test-ftell.c
 tests/test-ftell.sh
 
 Depends-on:
+binary-io
 
 configure.ac:
 
index 9f0c6e2499840dfdac55579642340b8be73264e0..48179bc129f3c57bb2df13da951484026a383d7c 100644 (file)
@@ -3,6 +3,7 @@ tests/test-ftello.c
 tests/test-ftello.sh
 
 Depends-on:
+binary-io
 
 configure.ac:
 
index 05e393db5146cdf1ed5bdc9343887ae62ee43e70..e25bc029f5ae5fe81b6063c760a36cd56fe1a919 100644 (file)
@@ -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
 #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;
 }
index 0357282636e9d85f3839932d22a6a8b74890dea8..73fd5274823338f68208df60d66fa581bc1f108c 100644 (file)
@@ -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
 #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;
 }