realloc: more improvements for realloc (p, 0)
[gnulib.git] / m4 / ftello.m4
blob2bdb63148fcc5859a26a90919afa44a97ed3f254
1 # ftello.m4
2 # serial 16
3 dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
4 dnl This file is free software; the Free Software Foundation
5 dnl gives unlimited permission to copy and/or distribute it,
6 dnl with or without modifications, as long as this notice is preserved.
7 dnl This file is offered as-is, without any warranty.
9 AC_DEFUN([gl_FUNC_FTELLO],
11   AC_REQUIRE([gl_STDIO_H_DEFAULTS])
12   AC_REQUIRE([AC_PROG_CC])
13   AC_REQUIRE([gl_STDIN_LARGE_OFFSET])
14   AC_REQUIRE([gl_SYS_TYPES_H])
16   dnl Persuade glibc <stdio.h> to declare ftello().
17   AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
19   AC_CHECK_DECLS_ONCE([ftello])
20   if test $ac_cv_have_decl_ftello = no; then
21     HAVE_DECL_FTELLO=0
22   fi
24   AC_CACHE_CHECK([for ftello], [gl_cv_func_ftello],
25     [
26       AC_LINK_IFELSE(
27         [AC_LANG_PROGRAM(
28            [[#include <stdio.h>]],
29            [[ftello (stdin);]])],
30         [gl_cv_func_ftello=yes],
31         [gl_cv_func_ftello=no])
32     ])
33   if test $gl_cv_func_ftello = no; then
34     HAVE_FTELLO=0
35   else
36     if test $WINDOWS_64_BIT_OFF_T = 1; then
37       REPLACE_FTELLO=1
38     fi
39     if test $gl_cv_var_stdin_large_offset = no; then
40       REPLACE_FTELLO=1
41     fi
42     AC_REQUIRE([AC_CANONICAL_HOST])
43     if test $REPLACE_FTELLO = 0; then
44       dnl On native Windows, in some circumstances, ftell(), ftello(),
45       dnl fgetpos(), lseek(), _lseeki64() all succeed on devices of type
46       dnl FILE_TYPE_PIPE. However, to match POSIX behaviour, we want
47       dnl ftell(), ftello(), fgetpos(), lseek() to fail when the argument fd
48       dnl designates a pipe. See also
49       dnl https://github.com/python/cpython/issues/78961#issuecomment-1093800325
50       case "$host_os" in
51         mingw* | windows*) REPLACE_FTELLO=1 ;;
52       esac
53     fi
54     if test $REPLACE_FTELLO = 0; then
55       dnl Detect bug on Solaris.
56       dnl ftell and ftello produce incorrect results after putc that followed a
57       dnl getc call that reached EOF on Solaris. This is because the _IOREAD
58       dnl flag does not get cleared in this case, even though _IOWRT gets set,
59       dnl and ftell and ftello look whether the _IOREAD flag is set.
60       AC_CACHE_CHECK([whether ftello works],
61         [gl_cv_func_ftello_works],
62         [
63           dnl Initial guess, used when cross-compiling or when /dev/tty cannot
64           dnl be opened.
65 changequote(,)dnl
66           case "$host_os" in
67                                # Guess no on Solaris.
68             solaris*)          gl_cv_func_ftello_works="guessing no" ;;
69                                # Guess yes on native Windows.
70             mingw* | windows*) gl_cv_func_ftello_works="guessing yes" ;;
71                                # Guess yes otherwise.
72             *)                 gl_cv_func_ftello_works="guessing yes" ;;
73           esac
74 changequote([,])dnl
75           AC_RUN_IFELSE(
76             [AC_LANG_SOURCE([[
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <string.h>
80 #define TESTFILE "conftest.tmp"
81 int
82 main (void)
84   FILE *fp;
86   /* Create a file with some contents.  */
87   fp = fopen (TESTFILE, "w");
88   if (fp == NULL)
89     return 70;
90   if (fwrite ("foogarsh", 1, 8, fp) < 8)
91     { fclose (fp); return 71; }
92   if (fclose (fp))
93     return 72;
95   /* The file's contents is now "foogarsh".  */
97   /* Try writing after reading to EOF.  */
98   fp = fopen (TESTFILE, "r+");
99   if (fp == NULL)
100     return 73;
101   if (fseek (fp, -1, SEEK_END))
102     { fclose (fp); return 74; }
103   if (!(getc (fp) == 'h'))
104     { fclose (fp); return 1; }
105   if (!(getc (fp) == EOF))
106     { fclose (fp); return 2; }
107   if (!(ftell (fp) == 8))
108     { fclose (fp); return 3; }
109   if (!(ftell (fp) == 8))
110     { fclose (fp); return 4; }
111   if (!(putc ('!', fp) == '!'))
112     { fclose (fp); return 5; }
113   if (!(ftell (fp) == 9))
114     { fclose (fp); return 6; }
115   if (!(fclose (fp) == 0))
116     return 7;
117   fp = fopen (TESTFILE, "r");
118   if (fp == NULL)
119     return 75;
120   {
121     char buf[10];
122     if (!(fread (buf, 1, 10, fp) == 9))
123       { fclose (fp); return 10; }
124     if (!(memcmp (buf, "foogarsh!", 9) == 0))
125       { fclose (fp); return 11; }
126   }
127   if (!(fclose (fp) == 0))
128     return 12;
130   /* The file's contents is now "foogarsh!".  */
132   return 0;
133 }]])],
134             [gl_cv_func_ftello_works=yes],
135             [gl_cv_func_ftello_works=no], [:])
136         ])
137       case "$gl_cv_func_ftello_works" in
138         *yes) ;;
139         *)
140           REPLACE_FTELLO=1
141           AC_DEFINE([FTELLO_BROKEN_AFTER_SWITCHING_FROM_READ_TO_WRITE], [1],
142             [Define to 1 if the system's ftello function has the Solaris bug.])
143           ;;
144       esac
145     fi
146     if test $REPLACE_FTELLO = 0; then
147       dnl Detect bug on macOS >= 10.15.
148       gl_FUNC_UNGETC_WORKS
149       if test $gl_ftello_broken_after_ungetc = yes; then
150         REPLACE_FTELLO=1
151         AC_DEFINE([FTELLO_BROKEN_AFTER_UNGETC], [1],
152           [Define to 1 if the system's ftello function has the macOS bug.])
153       fi
154     fi
155   fi
158 # Prerequisites of lib/ftello.c.
159 AC_DEFUN([gl_PREREQ_FTELLO],
161   dnl Native Windows has the function _ftelli64. mingw hides it, but mingw64
162   dnl makes it usable again.
163   AC_CHECK_FUNCS([_ftelli64])