changeset 9820:03b4e25928e9

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 <ebb9@byu.net>
author Eric Blake <ebb9@byu.net>
date Sat, 29 Mar 2008 16:55:56 -0600
parents 9ccce8a9bf52
children 18bab9955c43
files ChangeLog lib/ftell.c modules/ftell-tests modules/ftello-tests tests/test-ftell.c tests/test-ftello.c
diffstat 6 files changed, 168 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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)
 {
--- a/modules/ftell-tests
+++ b/modules/ftell-tests
@@ -3,6 +3,7 @@
 tests/test-ftell.sh
 
 Depends-on:
+binary-io
 
 configure.ac:
 
--- a/modules/ftello-tests
+++ b/modules/ftello-tests
@@ -3,6 +3,7 @@
 tests/test-ftello.sh
 
 Depends-on:
+binary-io
 
 configure.ac:
 
--- 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;
 }
--- 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;
 }