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