?RCS: $Id: Protochk.U,v $
?RCS:
?RCS: Copyright (c) 1998 Andy Dougherty
?RCS:
?RCS: You may distribute under the terms of either the GNU General Public
?RCS: License or the Artistic License, as specified in the README file.
?RCS:
?X:	This unit generates a ./protochk script that is used internally
?X:	by Configure to check if this system will accept a particular
?X:	prototype.
?X:
?X:	To use it, say something like:
?X:	hdrs="$define sys/types.h
?X:		$i_systime sys/time.h
?X:		$i_sysselct sys/select.h
?X:		$d_socket sys/socket.h"
?X:	$xxx='fd_set *'
?X:	try='extern int select _((int, $xxx, $xxx, $xxx, struct timeval *'));'
?X:	if ./protochk "$try" $hdrs; then
?X:		echo "Your system accepts $xxx for the arguments to select."
?X:	fi
?X:  (Of course select is harder, since the first arg can be int,
?X:	size_t, or unsigned long, and the last arg may or may not have a
?X:	'const' before the 'struct timeval' :-(.  Also SunOS 4.1.3 doesn't
?X:	provide a select prototype so the compiler accepts anything :-).
?X:
?X:	The C compiler on QNX warns about invalid pointer types, but
?X:	still exits with a 0 exit status, so it's not much help here.
?X:	(It does correctly detect incorrect non-pointer arguments).
?X:	Still, since QNX is a POSIX-ish system, just make your first
?X:	a POSIX-ish one, and QNX will probably accept it.
?X:
?X:	For determining argument types, your compiler must support
?X:	prototypes, and the header files must use them.  Determining
?X:	return types, however, is easier.  Just give an ridiculous
?X:	return type, something like
?X:	./protochk 'extern int atof _((void));' $i_stdlib stdlib.h
?X:	that should surely fail if atof() is defined in <stdlib.h>
?X:
?X:	There is also an 'escape' hatch built in.  If you have a pair
?X:	of args   'literal 'stuff' then 'stuff' gets included literally
?X:	into the test program.  This could be useful for doing something
?X:	like
?X:	hdrs="$define stdio.h
?X:		$define sys/types.h"
?X:	./protochk 'extern int fsetpos(FILE *, Fpos_t);' $args \
?X:			'literal' '#define Fpos_t long long'
?X:	but you have to be really careful about the spaces in "literal".
?X:
?X:		Andy Dougherty   Feb. 1998
?MAKE:Protochk: cat rm_try startsh eunicefix +cc +optimize +ccflags \
	i_pthread usethreads
?MAKE:	-pick add $@ %<
?F:./protochk
?X: Comfort metalint.  All these are actually used in the protochk script.
?T:foo status pthread_h_done
?LINT: change cc optimize ccflags define rm_try
?LINT: extern pthread_h_first
?LINT: change pthread_h_first
?LINT: change usethreads
?LINT: change i_pthread
: define a function to check prototypes
$cat > protochk <<EOSH
$startsh
cc="$cc"
optimize="$optimize"
ccflags="$ccflags"
define="$define"
rm_try="$rm_try"
usethreads=$usethreads
i_pthread=$i_pthread
pthread_h_first=$pthread_h_first
EOSH

$cat >> protochk <<'EOSH'

$rm_try
foo="$1"
shift
while test $# -ge 2; do
	case "$1" in
		$define) echo "#include <$2>" >> try.c ;;
		literal) echo "$2" >> try.c ;;
	esac
    # Extra magic for the benefit of systems that need pthread.h
    # to be included early to correctly detect threadsafe functions.
    # Such functions must guarantee themselves, though, that the usethreads
    # and i_pthread have been defined, before calling protochk.
    if test "$usethreads" = "$define" -a "$i_pthread" = "$define" -a "$pthread_h_first" = "$define" -a "$pthread_h_done" = ""; then
	echo "#include <pthread.h>" >> try.c
	pthread_h_done=yes
    fi
    shift 2
done
cat >> try.c <<'EOCP'
#define _(args) args
EOCP
echo "$foo" >> try.c
?X: Just so we have something to compile.
echo 'int no_real_function_has_this_name _((void)) { return 0; }' >> try.c
$cc $optimize $ccflags -c try.c > /dev/null 2>&1
status=$?
$rm_try
exit $status
EOSH
chmod +x protochk
$eunicefix protochk

