This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
More specific comment based on findings in RT#7586
[metaconfig.git] / U / perl / fflushall.U
1 ?RCS: $Id$
2 ?RCS:
3 ?RCS: Copyright (c) 1999, Jarkko Hietaniemi
4 ?RCS:
5 ?RCS: You may redistribute only under the terms of the Artistic License,
6 ?RCS: as specified in the README file that comes with the distribution.
7 ?RCS: You may reuse parts of this distribution only within the terms of
8 ?RCS: that same Artistic License; a copy of which may be found at the root
9 ?RCS: of the source tree for dist 3.0.
10 ?RCS:
11 ?MAKE:fflushNULL fflushall: Compile cat rm rm_try test osname run to from \
12         Oldconfig Myread Setvar echo \
13         d_sysconf i_unistd d_stdio_stream_array stdio_stream_array i_stdlib
14 ?MAKE:  -pick add $@ %<
15 ?S:fflushNULL:
16 ?S:     This symbol, if defined, tells that fflush(NULL) correctly
17 ?S:     flushes all pending stdio output without side effects. In
18 ?S:     particular, on some platforms calling fflush(NULL) *still*
19 ?S:     corrupts STDIN if it is a pipe.
20 ?S:.
21 ?S:fflushall:
22 ?S:     This symbol, if defined, tells that to flush
23 ?S:     all pending stdio output one must loop through all
24 ?S:     the stdio file handles stored in an array and fflush them.
25 ?S:     Note that if fflushNULL is defined, fflushall will not
26 ?S:     even be probed for and will be left undefined.
27 ?S:.
28 ?C:FFLUSH_NULL:
29 ?C:     This symbol, if defined, tells that fflush(NULL) correctly
30 ?C:     flushes all pending stdio output without side effects. In
31 ?C:     particular, on some platforms calling fflush(NULL) *still*
32 ?C:     corrupts STDIN if it is a pipe.
33 ?C:.
34 ?C:FFLUSH_ALL:
35 ?C:     This symbol, if defined, tells that to flush
36 ?C:     all pending stdio output one must loop through all
37 ?C:     the stdio file handles stored in an array and fflush them.
38 ?C:     Note that if fflushNULL is defined, fflushall will not
39 ?C:     even be probed for and will be left undefined.
40 ?C:.
41 ?H:#$fflushNULL FFLUSH_NULL             /**/
42 ?H:#$fflushall  FFLUSH_ALL              /**/
43 ?H:.
44 ?T:output code
45 ?F:!try.out !try !tryp
46 : Check how to flush
47 echo " "
48 $cat >&4 <<EOM
49 Checking how to flush all pending stdio output...
50 EOM
51 # I only know how to find the first 32 possibly open files on SunOS.
52 # See also hints/sunos_4_1.sh and util.c  --AD
53 case "$osname" in
54 sunos) $echo '#define PERL_FFLUSH_ALL_FOPEN_MAX 32' > try.c ;;
55 esac
56 $cat >>try.c <<EOCP
57 #include <stdio.h>
58 #$i_stdlib I_STDLIB
59 #ifdef I_STDLIB
60 #include <stdlib.h>
61 #endif
62 #$i_unistd I_UNISTD
63 #ifdef I_UNISTD
64 # include <unistd.h>
65 #endif
66 #$d_sysconf HAS_SYSCONF
67 #$d_stdio_stream_array HAS_STDIO_STREAM_ARRAY
68 #ifdef HAS_STDIO_STREAM_ARRAY
69 # define STDIO_STREAM_ARRAY $stdio_stream_array
70 #endif
71 int main() {
72   FILE* p;
73   unlink("try.out");
74   p = fopen("try.out", "w");
75 #ifdef TRY_FPUTC
76   fputc('x', p);
77 #else
78 # ifdef TRY_FPRINTF
79   fprintf(p, "x");
80 # endif
81 #endif
82 #ifdef TRY_FFLUSH_NULL
83   fflush(NULL);
84 #endif
85 #ifdef TRY_FFLUSH_ALL
86   {
87     long open_max = -1;
88 # ifdef PERL_FFLUSH_ALL_FOPEN_MAX
89     open_max = PERL_FFLUSH_ALL_FOPEN_MAX;
90 # else
91 #  if defined(HAS_SYSCONF) && defined(_SC_OPEN_MAX)
92     open_max = sysconf(_SC_OPEN_MAX);
93 #  else
94 #   ifdef FOPEN_MAX
95     open_max = FOPEN_MAX;
96 #   else
97 #    ifdef OPEN_MAX
98     open_max = OPEN_MAX;
99 #    else
100 #     ifdef _NFILE
101     open_max = _NFILE;
102 #     endif
103 #    endif
104 #   endif
105 #  endif
106 # endif
107 # ifdef HAS_STDIO_STREAM_ARRAY
108     if (open_max > 0) {
109       long i;
110       for (i = 0; i < open_max; i++)
111             if (STDIO_STREAM_ARRAY[i]._file >= 0 &&
112                 STDIO_STREAM_ARRAY[i]._file < open_max &&
113                 STDIO_STREAM_ARRAY[i]._flag)
114                 fflush(&STDIO_STREAM_ARRAY[i]);
115     }
116   }
117 # endif
118 #endif
119   _exit(42);
120 }
121 EOCP
122 : first we have to find out how _not_ to flush
123 $to try.c
124 if $test "X$fflushNULL" = X -o "X$fflushall" = X; then
125     output=''
126     set try -DTRY_FPUTC
127     if eval $compile; then
128             $run ./try 2>/dev/null
129             code="$?"
130             $from try.out
131             if $test ! -s try.out -a "X$code" = X42; then
132                 output=-DTRY_FPUTC
133             fi
134     fi
135     case "$output" in
136     '')
137             set try -DTRY_FPRINTF
138             if eval $compile; then
139                     $run ./try 2>/dev/null
140                     code="$?"
141                     $from try.out
142                     if $test ! -s try.out -a "X$code" = X42; then
143                         output=-DTRY_FPRINTF
144                     fi
145             fi
146         ;;
147     esac
148 fi
149 : check for fflush NULL behavior
150 case "$fflushNULL" in
151 '')     set try -DTRY_FFLUSH_NULL $output
152         if eval $compile; then
153                 $run ./try 2>/dev/null
154                 code="$?"
155                 $from try.out
156                 if $test -s try.out -a "X$code" = X42; then
157                         fflushNULL="`$cat try.out`"
158                 else
159                         if $test "X$code" != X42; then
160                                 $cat >&4 <<EOM
161 (If this test failed, don't worry, we'll try another method shortly.)
162 EOM
163                         fi
164                 fi
165         fi
166         $rm -f core try.core core.try.*
167         case "$fflushNULL" in
168         x)      $cat >&4 <<EOM
169 Your fflush(NULL) works okay for output streams.
170 Let's see if it clobbers input pipes...
171 EOM
172 # As of mid-March 2000 all versions of Solaris appear to have a stdio
173 # bug that improperly flushes the input end of pipes.  So we avoid the
174 # autoflush on fork/system/exec support for now. :-(
175 $cat >tryp.c <<EOCP
176 #include <stdio.h>
177 int
178 main(int argc, char **argv)
179 {
180     char buf[1024];
181     int i;
182     char *bp = buf;
183     while (1) {
184         while ((i = getc(stdin)) != -1
185                && (*bp++ = i) != '\n'
186                && bp < &buf[1024])
187         /* DO NOTHING */ ;
188         *bp = '\0';
189         fprintf(stdout, "%s", buf);
190         fflush(NULL);
191         if (i == -1)
192             return 0;
193         bp = buf;
194     }
195 }
196 EOCP
197                 fflushNULL="$define"
198                 set tryp
199                 if eval $compile; then
200                     $rm -f tryp.out
201                     $cat tryp.c | $run ./tryp 2>/dev/null > tryp.out
202                     if cmp tryp.c tryp.out >/dev/null 2>&1; then
203                        $cat >&4 <<EOM
204 fflush(NULL) seems to behave okay with input streams.
205 EOM
206                         fflushNULL="$define"
207                     else
208                         $cat >&4 <<EOM
209 Ouch, fflush(NULL) clobbers input pipes!  We will not use it.
210 EOM
211                         fflushNULL="$undef"
212                     fi
213                 fi
214                 $rm -f core tryp.c tryp.core core.tryp.*
215                 ;;
216         '')     $cat >&4 <<EOM
217 Your fflush(NULL) isn't working (contrary to ANSI C).
218 EOM
219                 fflushNULL="$undef"
220                 ;;
221         *)      $cat >&4 <<EOM
222 Cannot figure out whether your fflush(NULL) works or not.
223 I'm assuming it doesn't (contrary to ANSI C).
224 EOM
225                 fflushNULL="$undef"
226                 ;;
227         esac
228         ;;
229 $define|true|[yY]*)
230         fflushNULL="$define"
231         ;;
232 *)
233         fflushNULL="$undef"
234         ;;
235 esac
236 : check explicit looping only if NULL did not work, and if the pipe
237 : bug does not show up on an explicit flush too
238 case "$fflushNULL" in
239 "$undef")
240         $cat >tryp.c <<EOCP
241 #include <stdio.h>
242 int
243 main(int argc, char **argv)
244 {
245     char buf[1024];
246     int i;
247     char *bp = buf;
248     while (1) {
249         while ((i = getc(stdin)) != -1
250                && (*bp++ = i) != '\n'
251                && bp < &buf[1024])
252         /* DO NOTHING */ ;
253         *bp = '\0';
254         fprintf(stdout, "%s", buf);
255         fflush(stdin);
256         if (i == -1)
257             return 0;
258         bp = buf;
259     }
260 }
261 EOCP
262         set tryp
263         if eval $compile; then
264             $rm -f tryp.out
265             $cat tryp.c | $run ./tryp 2>/dev/null > tryp.out
266             if cmp tryp.c tryp.out >/dev/null 2>&1; then
267                $cat >&4 <<EOM
268 Good, at least fflush(stdin) seems to behave okay when stdin is a pipe.
269 EOM
270                 : now check for fflushall behaviour
271                 case "$fflushall" in
272                 '')     set try -DTRY_FFLUSH_ALL $output
273                         if eval $compile; then
274                                 $cat >&4 <<EOM
275 (Now testing the other method--but note that this also may fail.)
276 EOM
277                                 $run ./try 2>/dev/null
278                                 code=$?
279                                 $from try.out
280                                 if $test -s try.out -a "X$code" = X42; then
281                                         fflushall="`$cat try.out`"
282                                 fi
283                         fi
284                         $rm_try
285                         case "$fflushall" in
286                         x)      $cat >&4 <<EOM
287 Whew. Flushing explicitly all the stdio streams works.
288 EOM
289                                 fflushall="$define"
290                                 ;;
291                         '')     $cat >&4 <<EOM
292 Sigh. Flushing explicitly all the stdio streams doesn't work.
293 EOM
294                                 fflushall="$undef"
295                                 ;;
296                         *)      $cat >&4 <<EOM
297 Cannot figure out whether flushing stdio streams explicitly works or not.
298 I'm assuming it doesn't.
299 EOM
300                                 fflushall="$undef"
301                                 ;;
302                         esac
303                         ;;
304                 "$define"|true|[yY]*)
305                         fflushall="$define"
306                         ;;
307                 *)
308                         fflushall="$undef"
309                         ;;
310                 esac
311             else
312                 $cat >&4 <<EOM
313 All is futile.  Even fflush(stdin) clobbers input pipes!
314 EOM
315                 fflushall="$undef"
316             fi
317         else
318             fflushall="$undef"
319         fi
320         $rm -f core tryp.c tryp.core core.tryp.*
321         ;;
322 *)      fflushall="$undef"
323         ;;
324 esac
325
326 case "$fflushNULL$fflushall" in
327 undefundef)
328         $cat <<EOM
329 OK, I give up.  I cannot figure out how to flush pending stdio output.
330 We won't be flushing handles at all before fork/exec/popen.
331 EOM
332         ;;
333 esac
334 $rm_try tryp
335