?RCS: $Id$
?RCS:
?RCS: Copyright (c) 1999, Jarkko Hietaniemi
?RCS:
?RCS: You may redistribute only under the terms of the Artistic Licence,
?RCS: as specified in the README file that comes with the distribution.
?RCS: You may reuse parts of this distribution only within the terms of
?RCS: that same Artistic Licence; a copy of which may be found at the root
?RCS: of the source tree for dist 3.0.
?RCS:
?MAKE:fflushNULL fflushall: Compile cat rm test osname run to from \
Oldconfig Myread Setvar exe_ext echo \
d_sysconf i_unistd d_stdio_stream_array stdio_stream_array i_stdlib
?MAKE: -pick add $@ %<
?S:fflushNULL:
?S: This symbol, if defined, tells that fflush(NULL) does flush
?S: all pending stdio output.
?S:.
?S:fflushall:
?S: This symbol, if defined, tells that to flush
?S: all pending stdio output one must loop through all
?S: the stdio file handles stored in an array and fflush them.
?S: Note that if fflushNULL is defined, fflushall will not
?S: even be probed for and will be left undefined.
?S:.
?C:FFLUSH_NULL:
?C: This symbol, if defined, tells that fflush(NULL) does flush
?C: all pending stdio output.
?C:.
?C:FFLUSH_ALL:
?C: This symbol, if defined, tells that to flush
?C: all pending stdio output one must loop through all
?C: the stdio file handles stored in an array and fflush them.
?C: Note that if fflushNULL is defined, fflushall will not
?C: even be probed for and will be left undefined.
?C:.
?H:#$fflushNULL FFLUSH_NULL /**/
?H:#$fflushall FFLUSH_ALL /**/
?H:.
?T:output code
?F:!try.out
echo " "
$cat >&4 <<EOM
Checking how to flush all pending stdio output...
EOM
# I only know how to find the first 32 possibly open files on SunOS.
# See also hints/sunos_4_1.sh and util.c --AD
case "$osname" in
sunos) $echo '#define PERL_FFLUSH_ALL_FOPEN_MAX 32' > try.c ;;
esac
$cat >>try.c <<EOCP
#include <stdio.h>
#$i_stdlib I_STDLIB
#ifdef I_STDLIB
#include <stdlib.h>
#endif
#$i_unistd I_UNISTD
#ifdef I_UNISTD
# include <unistd.h>
#endif
#$d_sysconf HAS_SYSCONF
#$d_stdio_stream_array HAS_STDIO_STREAM_ARRAY
#ifdef HAS_STDIO_STREAM_ARRAY
# define STDIO_STREAM_ARRAY $stdio_stream_array
#endif
int main() {
FILE* p;
unlink("try.out");
p = fopen("try.out", "w");
#ifdef TRY_FPUTC
fputc('x', p);
#else
# ifdef TRY_FPRINTF
fprintf(p, "x");
# endif
#endif
#ifdef TRY_FFLUSH_NULL
fflush(NULL);
#endif
#ifdef TRY_FFLUSH_ALL
{
long open_max = -1;
# ifdef PERL_FFLUSH_ALL_FOPEN_MAX
open_max = PERL_FFLUSH_ALL_FOPEN_MAX;
# else
# if defined(HAS_SYSCONF) && defined(_SC_OPEN_MAX)
open_max = sysconf(_SC_OPEN_MAX);
# else
# ifdef FOPEN_MAX
open_max = FOPEN_MAX;
# else
# ifdef OPEN_MAX
open_max = OPEN_MAX;
# else
# ifdef _NFILE
open_max = _NFILE;
# endif
# endif
# endif
# endif
# endif
# ifdef HAS_STDIO_STREAM_ARRAY
if (open_max > 0) {
long i;
for (i = 0; i < open_max; i++)
if (STDIO_STREAM_ARRAY[i]._file >= 0 &&
STDIO_STREAM_ARRAY[i]._file < open_max &&
STDIO_STREAM_ARRAY[i]._flag)
fflush(&STDIO_STREAM_ARRAY[i]);
}
}
# endif
#endif
_exit(42);
}
EOCP
: first we have to find out how _not_ to flush
$to try.c
if $test "X$fflushNULL" = X -o "X$fflushall" = X; then
output=''
set try -DTRY_FPUTC
if eval $compile; then
$run ./try 2>/dev/null
code="$?"
$from try.out
if $test ! -s try.out -a "X$code" = X42; then
output=-DTRY_FPUTC
fi
fi
case "$output" in
'')
set try -DTRY_FPRINTF
if eval $compile; then
$run ./try 2>/dev/null
code="$?"
$from try.out
if $test ! -s try.out -a "X$code" = X42; then
output=-DTRY_FPRINTF
fi
fi
;;
esac
fi
: check for fflush NULL behaviour
case "$fflushNULL" in
'') set try -DTRY_FFLUSH_NULL $output
if eval $compile; then
$run ./try 2>/dev/null
code="$?"
$from try.out
if $test -s try.out -a "X$code" = X42; then
fflushNULL="`$cat try.out`"
else
if $test "X$code" != X42; then
$cat >&4 <<EOM
(If this test failed, don't worry, we'll try another method shortly.)
EOM
fi
fi
fi
$rm -f core try.core core.try.*
case "$fflushNULL" in
x) $cat >&4 <<EOM
Your fflush(NULL) works okay for output streams.
Let's see if it clobbers input pipes...
EOM
# As of mid-March 2000 all versions of Solaris appear to have a stdio
# bug that improperly flushes the input end of pipes. So we avoid the
# autoflush on fork/system/exec support for now. :-(
$cat >tryp.c <<EOCP
#include <stdio.h>
int
main(int argc, char **argv)
{
char buf[1024];
int i;
char *bp = buf;
while (1) {
while ((i = getc(stdin)) != -1
&& (*bp++ = i) != '\n'
&& bp < &buf[1024])
/* DO NOTHING */ ;
*bp = '\0';
fprintf(stdout, "%s", buf);
fflush(NULL);
if (i == -1)
return 0;
bp = buf;
}
}
EOCP
fflushNULL="$define"
set tryp
if eval $compile; then
$rm -f tryp.out
$cat tryp.c | $run ./tryp 2>/dev/null > tryp.out
if cmp tryp.c tryp.out >/dev/null 2>&1; then
$cat >&4 <<EOM
fflush(NULL) seems to behave okay with input streams.
EOM
fflushNULL="$define"
else
$cat >&4 <<EOM
Ouch, fflush(NULL) clobbers input pipes! We will not use it.
EOM
fflushNULL="$undef"
fi
fi
$rm -f core tryp.c tryp.core core.tryp.*
;;
'') $cat >&4 <<EOM
Your fflush(NULL) isn't working (contrary to ANSI C).
EOM
fflushNULL="$undef"
;;
*) $cat >&4 <<EOM
Cannot figure out whether your fflush(NULL) works or not.
I'm assuming it doesn't (contrary to ANSI C).
EOM
fflushNULL="$undef"
;;
esac
;;
$define|true|[yY]*)
fflushNULL="$define"
;;
*)
fflushNULL="$undef"
;;
esac
: check explicit looping only if NULL did not work, and if the pipe
: bug does not show up on an explicit flush too
case "$fflushNULL" in
"$undef")
$cat >tryp.c <<EOCP
#include <stdio.h>
int
main(int argc, char **argv)
{
char buf[1024];
int i;
char *bp = buf;
while (1) {
while ((i = getc(stdin)) != -1
&& (*bp++ = i) != '\n'
&& bp < &buf[1024])
/* DO NOTHING */ ;
*bp = '\0';
fprintf(stdout, "%s", buf);
fflush(stdin);
if (i == -1)
return 0;
bp = buf;
}
}
EOCP
set tryp
if eval $compile; then
$rm -f tryp.out
$cat tryp.c | $run ./tryp 2>/dev/null > tryp.out
if cmp tryp.c tryp.out >/dev/null 2>&1; then
$cat >&4 <<EOM
Good, at least fflush(stdin) seems to behave okay when stdin is a pipe.
EOM
: now check for fflushall behaviour
case "$fflushall" in
'') set try -DTRY_FFLUSH_ALL $output
if eval $compile; then
$cat >&4 <<EOM
(Now testing the other method--but note that this also may fail.)
EOM
$run ./try 2>/dev/null
code=$?
$from try.out
if $test -s try.out -a "X$code" = X42; then
fflushall="`$cat try.out`"
fi
fi
$rm -f core try.core core.try.*
case "$fflushall" in
x) $cat >&4 <<EOM
Whew. Flushing explicitly all the stdio streams works.
EOM
fflushall="$define"
;;
'') $cat >&4 <<EOM
Sigh. Flushing explicitly all the stdio streams doesn't work.
EOM
fflushall="$undef"
;;
*) $cat >&4 <<EOM
Cannot figure out whether flushing stdio streams explicitly works or not.
I'm assuming it doesn't.
EOM
fflushall="$undef"
;;
esac
;;
"$define"|true|[yY]*)
fflushall="$define"
;;
*)
fflushall="$undef"
;;
esac
else
$cat >&4 <<EOM
All is futile. Even fflush(stdin) clobbers input pipes!
EOM
fflushall="$undef"
fi
else
fflushall="$undef"
fi
$rm -f core tryp.c tryp.core core.tryp.*
;;
*) fflushall="$undef"
;;
esac
case "$fflushNULL$fflushall" in
undefundef)
$cat <<EOM
OK, I give up. I cannot figure out how to flush pending stdio output.
We won't be flushing handles at all before fork/exec/popen.
EOM
;;
esac
$rm -f try.* try$exe_ext