#!/bin/sh
###############################################################################
#
#  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are met:
#
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#  3. The name of the author may not be used to endorse or promote products
#     derived from this software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
#  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#  SUCH DAMAGE.
#
#
#  $Id: configure,v 1.198 2006/02/18 13:15:20 debug Exp $
#
#  This is a minimal configure script, hardcoded for GXemul. This script
#  figures out which compiler flags will work, and creates Makefiles in
#  sub-directories. A config.h file is also created.
#
#
#  --->   FOR NORMAL USE, JUST RUN ./configure WITHOUT OPTIONS!
#
#
#  To compile the emulator with profiling (during development), use
#  CFLAGS="-pg", run the emulator, and then run 'gprof gxemul' and study
#  the results.
#
#
#  The main things that are detected by this script:
#
#    o)  special hacks for some OSes
#    o)  which compiler to use  (overridden by setting CC)
#    o)  which compiler flags to use  (overridden by setting CFLAGS)
#    o)  X11 flags and libraries  (TODO: should be possible to override)
#    o)  binary translation (on supported platforms)
#
#  TODO:
#    o)  X11 libs and includes via command line options?
#
###############################################################################

#  Figure out if this is a stable version (0.x.x).
#X=`basename \`pwd\`|cut -d \- -f 2-|cut -c1-2`
#if [ z"$X" = z0. ]; then
#	#  Stable:
#	ENABLEARM=YES
#	ENABLEMIPS=YES
#	ENABLEPPC=YES
#else
#	#  Development:
#	UNSTABLE=YES
#	DYNTRANSBACKEND=NO #YES
#	ENABLEALPHA=YES
#	ENABLEARM=YES
#	ENABLEAVR=YES
#	ENABLEHPPA=YES
#	ENABLEI960=YES
#	ENABLEIA64=YES
#	ENABLEM68K=YES
#	ENABLEMIPS=YES
#	NEWMIPS=NO
#	ENABLEPPC=YES
#	ENABLESH=YES
#	ENABLESPARC=YES
#	ENABLEX86=YES
#fi

# enable X interface
	NOX11=

	UNSTABLE=NO

	ENABLEALPHA=NO
	ENABLEARM=NO
	ENABLEAVR=NO
	ENABLEHPPA=NO
	ENABLEI960=NO
	ENABLEIA64=NO
	ENABLEM68K=NO
	ENABLEPPC=NO
	ENABLESH=NO
	ENABLESPARC=NO
	ENABLEX86=NO

	ENABLEMIPS=YES
# newmips doesnt quite work at all yet
	NEWMIPS=NO
	MIPS16=NO

	NOBINTRANS=YES
	DYNTRANSBACKEND=NO

# ALWAYS32 is more accurate, but very slow :/
#	ALWAYS32=YES
	ALWAYS32=NO

	TRACENULL=NO
	DELAYS=YES
# CACHES is buggy
	CACHES=NO
	ONEKPAGE=NO

if [ z"$UNSTABLE" = zYES ]; then
	printf "###  DEVELOPMENT (UNSTABLE)\n\n"
fi

if [ z"$*" != z ]; then
	#  Parse command line options:
	for a in $*; do
		if [ z$a = z--disable-x ]; then
			NOX11=YES
		else if [ z$a = z--always32 ]; then
			ALWAYS32=YES
		else if [ z$a = z--tracenull ]; then
			TRACENULL=YES
		else if [ z$a = z--disable-bintrans ]; then
			NOBINTRANS=YES
		else if [ z$a = z--enable-bintrans ]; then
			NOBINTRANS=NO
		else if [ z$a = z--disable-mips16 ]; then
			MIPS16=NO
		else if [ z$a = z--enable-mips16 ]; then
			MIPS16=YES
		else if [ z$a = z--disable-dyntransbackend ]; then
			DYNTRANSBACKEND=NO
		else if [ z$a = z--enable-dyntransbackend ]; then
			DYNTRANSBACKEND=YES
		else if [ z$a = z--disable-delays ]; then
			DELAYS=NO
		else if [ z$a = z--enable-delays ]; then
			DELAYS=YES
		else if [ z$a = z--disable-caches ]; then
			CACHES=NO
		else if [ z$a = z--enable-caches ]; then
			CACHES=YES
		else if [ z$a = z--disable-newmips ]; then
			NEWMIPS=NO
		else if [ z$a = z--enable-newmips ]; then
			NEWMIPS=YES
		else if [ z$a = z--disable-1k-pages ]; then
			ONEKPAGE=NO
		else if [ z$a = z--enable-1k-pages ]; then
			ONEKPAGE=YES
		else if [ z$a = z--help ]; then
			echo "usage: $0 [options]"

			printf "\nGeneral options:\n\n"

			echo "  --disable-bintrans  configure without the" \
			    "old binary translation subsystem,"
			echo "                      even if the host" \
			    "supports it"
			echo "  --disable-x         don't include X11 support"

			printf "\nDevelopment (debug) options:\n\n"

			echo "  --always32         enable ALWAYS_SIGNEXTEND_32"\
			    "(for hunting down 32-bit bugs)"
			printf "  --enable-caches    enable cache emulation"
			printf " (BUGGY)\n"
			echo "  --enable-delays    enable instruction" \
			    "latency/delay emulation"

			if [ z$DYNTRANSBACKEND = zYES ]; then
				printf "  --disable-dyntransbackend  disable "
			else
				printf "  --enable-dyntransbackend  enable"
			fi
			printf "dyntrans backend\n"

			echo "  --enable-mips16    enable MIPS16 support"
			echo "  --enable-newmips   use new MIPS dyntrans code"
			#printf "  --enable-1k-pages  allow 1KB dyntrans pages"
			#printf " (default: 4KB)\n"

			printf "\n(Pretty much all of these options are only"
			printf " meaningful during the development of\nthe"
			printf " emulator, and should not be used when "
			printf "compiling a stable version.)\n"
			exit
		else
			echo "Invalid option: $a"
			echo "Run  $0 --help  to get a list of" \
			    "available options."
			exit
		fi; fi; fi; fi; fi; fi; fi; fi; fi; fi; fi; fi; fi; fi; fi; fi
		fi; fi
	done
fi


###############################################################################
#
#  Configure options:
#
#  This creates a config.h file, which is then included from include/misc.h.
#
###############################################################################

#  Head of config.h:
printf "/*
 *  THIS FILE IS AUTOMATICALLY CREATED BY configure!
 *  DON'T EDIT THIS FILE MANUALLY, IT WILL BE OVERWRITTEN.
 */
\n#ifndef CONFIG_H\n#define CONFIG_H\n\n" > config.h


#  Figure out if VERSION should be defined.
X=`basename \`pwd\`|cut -d \- -f 2-`
if [ z"$X" = zgxemul ]; then
	echo '/*  No VERSION defined.  */' >> config.h
else
	printf "#define VERSION \"$X\"\n" >> config.h
fi


ZZ=`echo compiled on \`uname\`/\`uname -m\`, \`date\``
printf "#define COMPILE_DATE \"$ZZ\"\n" >> config.h



#  Support for various CPU types:
if [ z$MIPS16 = zYES ]; then
	printf 'Enabling MIPS16 support.  '
	printf 'NOTE: MIPS16 support is not really working yet.\n'
	printf "#define ENABLE_MIPS16\n" >> config.h
fi
#if [ z$ENABLEALPHA = zYES ]; then
#	printf "#define ENABLE_ALPHA\n" >> config.h
#	CPU_ARCHS="$CPU_ARCHS cpu_alpha.o cpu_alpha_palcode.o"
#	CPU_TOOLS="$CPU_TOOLS generate_alpha_misc"
#fi
#if [ z$ENABLEARM = zYES ]; then
#	printf "#define ENABLE_ARM\n" >> config.h
#	CPU_ARCHS="$CPU_ARCHS cpu_arm.o cpu_arm_coproc.o memory_arm.o "
#	CPU_ARCHS="$CPU_ARCHS tmp_arm_dpi.o tmp_arm_loadstore.o tmp_arm_r.o"
#	CPU_ARCHS="$CPU_ARCHS tmp_arm_r0.o tmp_arm_r1.o"
#	CPU_ARCHS="$CPU_ARCHS tmp_arm_r2.o tmp_arm_r3.o"
#	CPU_ARCHS="$CPU_ARCHS tmp_arm_r4.o tmp_arm_r5.o"
#	CPU_ARCHS="$CPU_ARCHS tmp_arm_r6.o tmp_arm_r7.o"
#	CPU_ARCHS="$CPU_ARCHS tmp_arm_r8.o tmp_arm_r9.o"
#	CPU_ARCHS="$CPU_ARCHS tmp_arm_ra.o tmp_arm_rb.o"
#	CPU_ARCHS="$CPU_ARCHS tmp_arm_rc.o tmp_arm_rd.o"
#	CPU_ARCHS="$CPU_ARCHS tmp_arm_re.o tmp_arm_rf.o tmp_arm_multi.o"
#	CPU_TOOLS="$CPU_TOOLS generate_arm_dpi generate_arm_r"
#	CPU_TOOLS="$CPU_TOOLS generate_arm_loadstore generate_arm_multi"
#fi
#if [ z$ENABLEAVR = zYES ]; then
#	printf "#define ENABLE_AVR\n" >> config.h
#	CPU_ARCHS="$CPU_ARCHS cpu_avr.o"
#fi
#if [ z$ENABLEHPPA = zYES ]; then
#	printf "#define ENABLE_HPPA\n" >> config.h
#	CPU_ARCHS="$CPU_ARCHS cpu_hppa.o"
#fi
#if [ z$ENABLEI960 = zYES ]; then
#	printf "#define ENABLE_I960\n" >> config.h
#	CPU_ARCHS="$CPU_ARCHS cpu_i960.o"
#fi
#if [ z$ENABLEIA64 = zYES ]; then
#	printf "#define ENABLE_IA64\n" >> config.h
#	CPU_ARCHS="$CPU_ARCHS cpu_ia64.o"
#fi
#if [ z$ENABLEM68K = zYES ]; then
#	printf "#define ENABLE_M68K\n" >> config.h
#	CPU_ARCHS="$CPU_ARCHS cpu_m68k.o"
#fi
if [ z$ENABLEMIPS = zYES ]; then
	printf "#define ENABLE_MIPS\n" >> config.h
	if [ z$NEWMIPS = zYES ]; then
		echo 'Enabling the _EXPERIMENTAL_ MIPS dyntrans code.'
		printf "#define EXPERIMENTAL_NEWMIPS\n" >> config.h
	fi
fi
#if [ z$ENABLEPPC = zYES ]; then
#	printf "#define ENABLE_PPC\n" >> config.h
#	CPU_ARCHS="$CPU_ARCHS cpu_ppc.o"
#	CPU_TOOLS="$CPU_TOOLS generate_ppc_loadstore"
#fi
#if [ z$ENABLESH = zYES ]; then
#	printf "#define ENABLE_SH\n" >> config.h
#	CPU_ARCHS="$CPU_ARCHS cpu_sh.o"
#fi
#if [ z$ENABLESPARC = zYES ]; then
#	printf "#define ENABLE_SPARC\n" >> config.h
#	CPU_ARCHS="$CPU_ARCHS cpu_sparc.o"
#fi
#if [ z$ENABLEX86 = zYES ]; then
#	printf "#define ENABLE_X86\n" >> config.h
#	CPU_ARCHS="$CPU_ARCHS cpu_x86.o"
#fi


#  Instruction delay/latency emulation:
if [ z$DELAYS = zYES ]; then
	echo 'Enabling Instruction delay/latency emulation.'
	printf "#define ENABLE_INSTRUCTION_DELAYS\n" >> config.h
fi


#  Development option: ALWAYS_SIGNEXTEND_32
if [ z$ALWAYS32 = zYES ]; then
	echo 'Enabling ALWAYS_SIGNEXTEND_32. (NOTE:' \
	    'This slows down everything.)'
	printf "#define ALWAYS_SIGNEXTEND_32\n" >> config.h
fi


#  1KB page emulation:
if [ z$ONEKPAGE = zYES ]; then
	echo '1 KB pages: not yet.'
	exit
	echo 'Enabling 1 KB page dyntrans support. (NOTE:' \
	    'This slows down everything.)'
	printf "#define ONEKPAGE\n" >> config.h
fi


#  Cache emulation:
if [ z$CACHES = zYES ]; then
	echo 'Enabling Cache emulation. (EXPERIMENTAL and BUGGY)'
	printf "#define ENABLE_CACHE_EMULATION\n" >> config.h

	if [ z$DELAYS != zYES ]; then
		printf 'WARNING: Cache emulation without instruction '
		printf 'delay/latency emulation\n'
		printf '         (--delays) will not produce correct '
		printf 'cache miss penalties and such.\n'
	fi

	printf "\nNOTE: Cache emulation enabled, but right now it triggers "
	printf "weird bugs in the\n      emulator. You have been warned.\n\n"
fi


###############################################################################
#
#  Special hacks for some host OSes:
#
###############################################################################

if [ z"`uname|cut -c 1-6`" = zCYGWIN ]; then
	CYGWIN=YES

	if [ z"$CC" = z ]; then
		#  Assume gcc on Cygwin (Windows) systems.
		CC=gcc
	fi
fi

if [ z"`uname`" = zHP-UX ]; then
	HPUX=YES

	if [ z$CC = z ]; then
		if [ -f /usr/local/pa64/bin/gcc ]; then
			CC=/usr/local/pa64/bin/gcc
		fi
	fi
fi

if [ z"`uname`" = zOSF1 ]; then
	OSF1=YES
fi


###############################################################################
#
#  Create the Makefile header:
#
###############################################################################

rm -f _Makefile.header

printf "#
#  DO NOT EDIT THIS FILE! It is automagically created by
#  the configure script, based on Makefile.skel.
#\n\n" >> _Makefile.header


echo 'int main(int argc, char *argv[]) { return 0; }' > _testprog.c


#  Try to detect which C compiler to use, if CC is not set:
printf "checking which C compiler to use... "

if [ z"$CC" = z ]; then
	CC=cc

	#  Try gcc first:
	printf "#!/bin/sh\ngcc _testprog.c -o _testprog >" > _test.sh
	printf " /dev/null 2> /dev/null\n" >> _test.sh
	chmod 755 _test.sh
	./_test.sh > /dev/null 2> /dev/null
	if [ -x _testprog ]; then
		CC=gcc
	fi
	rm -f _testprog

	#  If both gcc and cc exist, then cc might be a vendor specific
	#  compiler which produces faster code than gcc (eg on Solaris):
	printf "#!/bin/sh\ncc _testprog.c -o _testprog >" > _test.sh
	printf " /dev/null 2> /dev/null\n" >> _test.sh
	chmod 755 _test.sh
	./_test.sh > /dev/null 2> /dev/null
	if [ -x _testprog ]; then
		CC=cc
	fi
	rm -f _testprog

#	#  Try ccc (FreeBSD/Alpha):
#	printf "#!/bin/sh\nccc _testprog.c -o _testprog >" > _test.sh
#	printf " /dev/null 2> /dev/null\n" >> _test.sh
#	chmod 755 _test.sh
#	./_test.sh > /dev/null 2> /dev/null
#	if [ -x _testprog ]; then
#		CC="ccc"
#	fi
#	rm -f _testprog

	rm -f _test.sh
fi


rm -f _testprog
printf "$CC $CFLAGS"


CCTYPE="generic"

if $CC $CFLAGS -V 2> /dev/null | grep ompaq 1> /dev/null 2> /dev/null; then
	COMPAQCC=YES
	CCTYPE="Compaq CC"
fi

if $CC $CFLAGS -V 2>&1 | grep Sun 1> /dev/null 2> /dev/null; then
	SUNCC=YES
	CCTYPE="Solaris CC"
fi

if $CC $CFLAGS -v 2>&1 | grep gcc 1> /dev/null 2> /dev/null; then
	GCCCC=YES
	CCTYPE="GNU CC"
fi

if [ z$CYGWIN = zYES ]; then
	CCTYPE="$CCTYPE (Cygwin)"
fi

echo " ($CCTYPE)"


if [ z$NOX11 = z ]; then
	printf "checking for X11 headers and libs\n"

	#  Try to compile a small X11 test program:
	printf "#include <X11/Xlib.h>
	#include <stdio.h>
	Display *dis;
	void f(void) {
		dis = XOpenDisplay(NULL);
	}
	int main(int argc, char *argv[])
	{ return 0; }
	" > _test_x11.c

	XOK=0

	XINCLUDE=-I/usr/X11R6/include
	$CC $CFLAGS _test_x11.c -c -o _test_x11.o $XINCLUDE 2> /dev/null

	XLIB="-L/usr/X11R6/lib -lX11"
	$CC $CFLAGS _test_x11.o -o _test_x11 $XLIB 2> /dev/null

	if [ -x _test_x11 ]; then
		XOK=1
	fi

	rm -f _test_x11 _test_x11.o

	if [ z$XOK = z0 ]; then
		XINCLUDE=""
		$CC $CFLAGS _test_x11.c -c -o _test_x11.o \
		    $XINCLUDE 2> /dev/null

		#  -lsocket for Solaris
		XLIB="-lX11 -lsocket"
		$CC $CFLAGS _test_x11.o -o _test_x11 $XLIB 2> /dev/null

		if [ -x _test_x11 ]; then
			XOK=1
		fi
		rm -f _test_x11 _test_x11.o
	fi

	if [ z`uname` = zNetBSD ]; then
		echo "Using NetBSD hack for X11 libs..."
		XLIB="$XLIB -Wl,-rpath,/usr/X11R6/lib"
	fi

	if [ z`uname` = zOpenBSD ]; then
		if [ z`uname -m` = zarc ]; then
			echo "Using old OpenBSD/arc hack for X11 libs..."
			XLIB="$XLIB -Wl,-rpath,/usr/X11R6/lib"
		fi
	fi

	if [ z$XOK = z0 ]; then
		echo "Failed to compile X11 test program." \
		    "Configuring without X11."
	else
		printf "X11 headers: $XINCLUDE\n"
		printf "X11 libraries: $XLIB\n"
		echo "XINCLUDE=$XINCLUDE" >> _Makefile.header
		echo "XLIB=$XLIB" >> _Makefile.header
		printf "#define WITH_X11\n" >> config.h
	fi

	rm -f _test_x11.c
fi


if [ z$HPUX = zYES ]; then
	CFLAGS="-D_XOPEN_SOURCE_EXTENDED $CFLAGS"
	printf "#define HPUX\n" >> config.h
fi


if [ z$OSF1 = zYES ]; then
	CFLAGS="-D_XOPEN_SOURCE=500 -D_OSF_SOURCE -D_POSIX_PII_SOCKET $CFLAGS"
fi


#  Check for 'alpha' define.
printf "checking for 'alpha' define... "
printf "#include <stdio.h>\nint main(int argc, char *argv[]){
#ifdef alpha
printf(\"1\");
#undef alpha
#ifdef alpha
printf(\"2\");
#endif
#endif
printf(\"\\\n\");return 0;}\n" > _testm.c
$CC $CFLAGS _testm.c -o _testm 2> /dev/null
if [ ! -x _testm ]; then
	printf "\nWARNING! COULD NOT COMPILE alpha define TEST"
	printf " PROGRAM AT ALL!\n"
else
	if [ z`./_testm` = z1 ]; then
		printf "yes, workaround applied\n"
		echo "#undef alpha" >> config.h
	else
		if [ z`./_testm` = z12 ]; then
			printf "yes, but workaround not possible\n"
			exit
		else
			printf "no\n"
		fi
	fi
fi
rm -f _testm*


#  Some OSes on MIPS seems to define 'mips' to 1. (eg OpenBSD/arc)
printf "checking for 'mips' define... "
printf "#include <stdio.h>\nint main(int argc, char *argv[]){
#ifdef mips
printf(\"1\");
#undef mips
#ifdef mips
printf(\"2\");
#endif
#endif
printf(\"\\\n\");return 0;}\n" > _testm.c
$CC $CFLAGS _testm.c -o _testm 2> /dev/null
if [ ! -x _testm ]; then
	printf "\nWARNING! COULD NOT COMPILE mips define TEST"
	printf " PROGRAM AT ALL!\n"
else
	if [ z`./_testm` = z1 ]; then
		printf "yes, workaround applied\n"
		echo "#undef mips" >> config.h
	else
		if [ z`./_testm` = z12 ]; then
			printf "yes, but workaround not possible\n"
			exit
		else
			printf "no\n"
		fi
	fi
fi
rm -f _testm*


#  Similar to the mips define check above, although I don't know if
#  any OS actually defined ppc like this.
printf "checking for 'ppc' define... "
printf "#include <stdio.h>\nint main(int argc, char *argv[]){
#ifdef ppc
printf(\"1\");
#undef ppc
#ifdef ppc
printf(\"2\");
#endif
#endif
printf(\"\\\n\");return 0;}\n" > _testm.c
$CC $CFLAGS _testm.c -o _testm 2> /dev/null
if [ ! -x _testm ]; then
	printf "\nWARNING! COULD NOT COMPILE ppc define TEST"
	printf " PROGRAM AT ALL!\n"
else
	if [ z`./_testm` = z1 ]; then
		printf "yes, workaround applied\n"
		echo "#undef ppc" >> config.h
	else
		if [ z`./_testm` = z12 ]; then
			printf "yes, but workaround not possible\n"
			exit
		else
			printf "no\n"
		fi
	fi
fi
rm -f _testm*


#  Similar to the mips define check above, although I don't know if
#  any OS actually defined sparc like this.
printf "checking for 'sparc' define... "
printf "#include <stdio.h>\nint main(int argc, char *argv[]){
#ifdef sparc
printf(\"1\");
#undef sparc
#ifdef sparc
printf(\"2\");
#endif
#endif
printf(\"\\\n\");return 0;}\n" > _testm.c
$CC $CFLAGS _testm.c -o _testm 2> /dev/null
if [ ! -x _testm ]; then
	printf "\nWARNING! COULD NOT COMPILE sparc define TEST "
	printf "PROGRAM AT ALL!\n"
else
	if [ z`./_testm` = z1 ]; then
		printf "yes, workaround applied\n"
		echo "#undef sparc" >> config.h
	else
		if [ z`./_testm` = z12 ]; then
			printf "yes, but workaround not possible\n"
			exit
		else
			printf "no\n"
		fi
	fi
fi
rm -f _testm*


#  CWARNINGS:
printf "checking whether -Wall can be used... "
$CC $CFLAGS _testprog.c -o _testprog -Wall 2> /dev/null
if [ -x _testprog ]; then
	printf "yes\n"
	CWARNINGS="-Wall $CWARNINGS"

	#  Compaq's compiler always seems to warn about the long long type,
	#  and unusedtop suppresses warnings about include files being
	#  included more than once.
	if [ z"$COMPAQCC" = zYES ]; then
		CWARNINGS="$CWARNINGS -msg_disable longlongtype,unusedtop"
	fi

	if [ z"$UNSTABLE" = zYES ]; then
		printf "checking whether -Werror can be used... "
		rm -f _testprog
		$CC $CFLAGS $CWARNINGS _testprog.c -o _testprog -Werror 2> /dev/null
		if [ -x _testprog ]; then
			printf "yes\n"
			CWARNINGS="$CWARNINGS -Werror"
		else
			printf "no\n"
		fi
	fi
else
	printf "no\n"
fi
rm -f _testprog


if [ z"$COMPAQCC" = zYES ]; then
	#  -O4 is possible, but sometimes -O3 is better?
	CFLAGS="-O4 $CFLAGS"
else
	if [ z"`uname`" = zSunOS ]; then
		#  "cc", the system's default compiler:
		if [ z"$SUNCC" = zYES ]; then
			CFLAGS="-xO5 -xdepend $CFLAGS"
		fi
		printf "#define SOLARIS\n" >> config.h
		OTHERLIBS="-lsocket $OTHERLIBS"
	else
		#  gcc or something else:
		$CC $CFLAGS _testprog.c -o _testprog -O 2> /dev/null
		if [ -x _testprog ]; then
			rm -f _testprog
			$CC $CFLAGS _testprog.c -o _testprog -O3 2> /dev/null
			if [ -x _testprog ]; then
				CFLAGS="-O3 $CFLAGS"
			else
				CFLAGS="-O $CFLAGS"
			fi
		fi
	fi
fi
rm -f _testprog


#  -fschedule-insns causes bugs on i386 with gcc,
#  but works OK on my alpha with ccc (compaq's cc).
if [ z"$COMPAQCC" = zYES ]; then
	printf "checking whether -fschedule-insns2 can be used... "
	$CC $CFLAGS _testprog.c -o _testprog -fschedule-insns2 2> /dev/null
	if [ -x _testprog ]; then
		CFLAGS="-fschedule-insns2 $CFLAGS"
		printf "yes\n"
	else
		printf "no\n"
	fi
	rm -f _testprog

	printf "checking whether -fschedule-insns can be used... "
	$CC $CFLAGS _testprog.c -o _testprog -fschedule-insns 2> /dev/null
	if [ -x _testprog ]; then
		CFLAGS="-fschedule-insns $CFLAGS"
		printf "yes\n"
	else
		printf "no\n"
	fi
	rm -f _testprog

#	#  -intrinsics
#	$CC $CFLAGS _testprog.c -o _testprog -intrinsics 2> /dev/null
#	if [ -x _testprog ]; then
#		CFLAGS="-intrinsics $CFLAGS"
#	fi
#	rm -f _testprog

	#  -fast
	printf "checking whether -fast can be used... "
	$CC $CFLAGS _testprog.c -o _testprog -fast 2> /dev/null
	if [ -x _testprog ]; then
		CFLAGS="-fast $CFLAGS"
		printf "yes\n"
	else
		printf "no\n"
	fi
	rm -f _testprog
fi


#  -fpeephole
printf "checking whether -fpeephole can be used... "
$CC $CFLAGS -fpeephole _testprog.c -o _testprog > _testprog.stdout 2>&1
cat _testprog.stdout >> _testprog.error
if grep peephole _testprog.error > /dev/null 2>&1; then
	printf "no\n"
else
	if [ -x _testprog ]; then
		CFLAGS="-fpeephole $CFLAGS"
		printf "yes\n"
	else
		printf "no\n"
	fi
fi
rm -f _testprog _testprog.error _testprog.stdout


#  -fomit-frame-pointer
printf "checking whether -fomit-frame-pointer can be used... "
$CC $CFLAGS -fomit-frame-pointer _testprog.c -o \
    _testprog 1> _testprog.stdout 2>&1
cat _testprog.stdout >> _testprog.error
if grep frame _testprog.error > /dev/null 2>&1; then
	printf "no\n"
else
	if [ -x _testprog ]; then
		CFLAGS="-fomit-frame-pointer $CFLAGS"
		printf "yes\n"
	else
		printf "no\n"
	fi
fi
rm -f _testprog _testprog.error _testprog.stdout


#  -g
printf "checking whether -g can be used... "
if [ z"$COMPAQCC" = zYES ]; then
	printf "skipping\n"
else
	$CC $CFLAGS -g _testprog.c -o _testprog > _testprog.stdout 2>&1
	cat _testprog.stdout >> _testprog.error
	if [ -x _testprog ]; then
		CFLAGS="-g $CFLAGS"
		printf "yes\n"
	else
		printf "no\n"
	fi
fi
rm -f _testprog _testprog.error _testprog.stdout


#  -lrt for nanosleep?
printf "checking whether -lrt is required for nanosleep... "
printf "#include <time.h>\n#include <stdio.h>
int main(int argc, char *argv[]){nanosleep(NULL,NULL);return 0;}\n" > _testns.c
$CC $CFLAGS _testns.c -o _testns 2> /dev/null
if [ ! -x _testns ]; then
	$CC $CFLAGS -lrt _testns.c -o _testns 2> /dev/null
	if [ ! -x _testns ]; then
		printf "WARNING! COULD NOT COMPILE WITH nanosleep AT ALL!\n"
	else
		#  -lrt for nanosleep
		OTHERLIBS="-lrt $OTHERLIBS"
		printf "yes\n"
	fi
else
	printf "no\n"
fi
rm -f _testns.c _testns


#  -lresolv for inet_pton?
printf "checking whether -lresolv is required for inet_pton... "
printf "int inet_pton(void); int main(int argc, " > _testr.c
printf "char *argv[]) { return inet_pton(); }\n" >> _testr.c
$CC $CFLAGS _testr.c -o _testr 2> /dev/null
if [ ! -x _testr ]; then
	$CC $CFLAGS _testr.c -lresolv -o _testr 2> /dev/null
	if [ ! -x _testr ]; then
		$CC $CFLAGS _testr.c -lresolv -lnsl -o _testr 2> /dev/null
		if [ ! -x _testr ]; then
			printf "no, using inet_aton\n"
		else
			#  -lresolv -lnsl for inet_pton
			OTHERLIBS="-lresolv -lnsl $OTHERLIBS"
			printf "yes (and -lnsl)\n"
			printf "#define HAVE_INET_PTON\n" >> config.h
		fi
	else
		#  -lresolv for inet_pton
		OTHERLIBS="-lresolv $OTHERLIBS"
		printf "yes\n"
		printf "#define HAVE_INET_PTON\n" >> config.h
	fi
else
	printf "no\n"
	printf "#define HAVE_INET_PTON\n" >> config.h
fi
rm -f _testr.[co] _testr


#  -lm?
printf "checking for math libs..."
printf "#include <math.h>\nint main(int argc, char *argv[]) { " > _testr.c
printf "double x = sqrt((double)argc); return (int)x; }\n" >> _testr.c
$CC $CFLAGS _testr.c -o _testr 2> /dev/null
if [ ! -x _testr ]; then
	$CC $CFLAGS _testr.c -lm -o _testr 2> /dev/null
	if [ ! -x _testr ]; then
		$CC $CFLAGS _testr.c -lm -lcpml -o _testr 2> /dev/null
		if [ ! -x _testr ]; then
			printf "\nWARNING! Could not compile math test "
			printf "at all!\nContinuing anyway.\n\n"
		else
			#  -lm AND -lcpml
			OTHERLIBS="-lm -lcpml $OTHERLIBS"
			printf " -lm -lcpml\n"
		fi
	else
		#  Normal -lm
		OTHERLIBS="-lm $OTHERLIBS"
		printf " -lm\n"
	fi
else
	printf " none needed\n"
fi
rm -f _testr.[co] _testr


#  strlcpy missing?
printf "checking for strlcpy... "
printf "#include <string.h>
int main(int argc, char *argv[]) { char *p; char *q; size_t x;
  x = strlcpy(p, q, 50); return 0;}\n" > _tests.c
$CC $CFLAGS _tests.c -o _tests 2> /dev/null
if [ ! -x _tests ]; then
	printf "missing, using mystrlcpy\n"
	printf "#define strlcpy mystrlcpy\n" >> config.h
	printf "#define strlcat mystrlcat\n" >> config.h
	printf "#define USE_STRLCPY_REPLACEMENTS\n" >> config.h
else
	printf "found\n"
fi
rm -f _tests.[co] _tests


#  strtoull missing?
printf "checking for strtoull... "
printf "#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
  long long x = strtoull(argv[1], NULL, 0); return 0;}\n" > _tests.c
$CC $CFLAGS _tests.c -o _tests 2> /dev/null
if [ ! -x _tests ]; then
	printf "missing, using mystrtoull\n"
	printf "#define strtoull mystrtoull\n" >> config.h
else
	printf "found\n"
fi
rm -f _tests.[co] _tests


#  mkstemp missing?
printf "checking for mkstemp... "
printf "#include <unistd.h>
int main(int argc, char *argv[]) { int x; char *y = \"abc\";
x = mkstemp(y); return 0;}\n" > _tests.c
$CC $CFLAGS _tests.c -o _tests 2> /dev/null
if [ ! -x _tests ]; then
	printf "missing, using workaround\n"
	printf "#define mkstemp mymkstemp\n" >> config.h
else
	printf "found\n"
fi
rm -f _tests.[co] _tests


#  fseeko missing?
printf "checking for fseeko... "
printf "#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
#include <sys/types.h>
int main(int argc, char *argv[]) { fseeko(NULL, 0, 0); return 0;}\n" > _tests.c
$CC $CFLAGS _tests.c -o _tests 2> /dev/null
if [ ! -x _tests ]; then
	printf "missing\n"
	printf "WARNING! fseeko missing from libc. Using a hack, "
	printf "which probably doesn't work.\n"
	printf "#define HACK_FSEEKO\n" >> config.h
else
	printf "found\n"
fi
rm -f _tests.[co] _tests


#  socklen_t missing?
#  (for example really old OpenBSD/arc 2.3, inside the emulator)
printf "checking for socklen_t... "
printf "#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
int main(int argc, char *argv[]) { socklen_t x; return 0;}\n" > _tests.c
$CC $CFLAGS _tests.c -o _tests 2> /dev/null
if [ ! -x _tests ]; then
	printf "no, using int\n"
	CFLAGS="$CFLAGS -Dsocklen_t=int"
else
	printf "socklen_t\n"
fi
rm -f _tests.[co] _tests


#  MAP_ANON missing? (On some HP-UX systems? Use MAP_ANONYMOUS instead.)
printf "checking for MAP_ANON... "
rm -f _tests
printf "#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
int main(int argc, char *argv[]) { int x = MAP_ANON; return 0;}\n" > _tests.c
$CC $CFLAGS _tests.c -o _tests 2> /dev/null
if [ ! -x _tests ]; then
	printf "#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{ int x = MAP_ANONYMOUS; return 0;}\n" > _tests.c
	$CC $CFLAGS _tests.c -o _tests 2> /dev/null
	if [ ! -x _tests ]; then
		printf "no\n\n"
		printf "WARNING! Neither MAP_ANON nor MAP_ANONYMOUS work on "
		printf "this system.\nPlease try to compile anyway, and report"
		printf " to me whether it builds/runs or not.\n\n"
		printf "#define MAP_ANON 0\n" >> config.h
		printf "#define NO_MAP_ANON\n" >> config.h
	else
		printf "using MAP_ANONYMOUS\n"
		printf "#define MAP_ANON MAP_ANONYMOUS\n" >> config.h
	fi
else
	printf "yes\n"
fi
rm -f _tests.[co] _tests


#  Check for 64-bit off_t:
printf "checking for 64-bit off_t... "
printf "#include <stdio.h>\n#include <inttypes.h>\n#include <sys/types.h>\n
int main(int argc, char *argv[]){printf(\"%%i\\\n\",
 (int)sizeof(off_t));return 0;}\n" > _testoff.c
$CC $CFLAGS _testoff.c -o _testoff 2> /dev/null
if [ ! -x _testoff ]; then
	printf "\nWARNING! COULD NOT COMPILE off_t TEST PROGRAM AT ALL!\n"
else
	if [ z`./_testoff` = z8 ]; then
		printf "yes\n"
	else
		$CC $CFLAGS -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \
		    _testoff.c -o _testoff 2> /dev/null
		if [ ! -x _testoff ]; then
			printf "\nWARNING! COULD NOT COMPILE off_t TEST "
			printf "PROGRAM!\n"
		else
			if [ z`./_testoff` = z8 ]; then
				CFLAGS="-D_FILE_OFFSET_BITS=64 $CFLAGS"
				CFLAGS="-D_LARGEFILE_SOURCE $CFLAGS"
				printf "using -D_FILE_OFFSET_BITS=64"
				printf " -D_LARGEFILE_SOURCE\n"
			else
				printf "NO\n"
				printf "Warning! No 64-bit off_t. Continuing "
				printf "anyway.\n"
			fi
		fi
	fi
fi
rm -f _testoff.c _testoff


#  Check for u_int8_t etc:
#  These are needed because some header files in src/include/ use u_int*
#  instead of uint*, and I don't have time to rewrite them all.
printf "checking for u_int8_t... "
printf "#include <stdio.h>\n#include <inttypes.h>\n#include <sys/types.h>\n
int main(int argc, char *argv[]){printf(\"%%i\\\n\",
 (int)sizeof(u_int8_t));return 0;}\n" > _testuint.c
$CC $CFLAGS _testuint.c -o _testuint 2> /dev/null
if [ ! -x _testuint ]; then
	rm -f _testuint*
	printf "#include <stdio.h>\n#include <inttypes.h>
	\n#include <sys/types.h>\nint main(int argc, char *argv[])
	{printf(\"%%i\\\n\", (int)sizeof(uint8_t));return 0;}\n" > _testuint.c
	$CC $CFLAGS _testuint.c -o _testuint 2> /dev/null
	if [ ! -x _testuint ]; then
		printf "no\n\nERROR: No u_int8_t or uint8_t. Aborting\n"
		#  TODO: Automagically detect using various combinations
		#  of char, int, short, long etc.
		exit
	fi

	printf "typedef uint8_t u_int8_t;\n" >> config.h
	printf "typedef uint16_t u_int16_t;\n" >> config.h
	printf "typedef uint32_t u_int32_t;\n" >> config.h
	printf "uint8_t\n"
else
	printf "yes\n"
fi
rm -f _testuint.c _testuint

printf "checking for u_int64_t... "
printf "#include <stdio.h>\n#include <inttypes.h>\n#include <sys/types.h>\n
int main(int argc, char *argv[]){printf(\"%%i\\\n\",
 (int)sizeof(u_int64_t));return 0;}\n" > _testuint.c
$CC $CFLAGS _testuint.c -o _testuint 2> /dev/null
if [ ! -x _testuint ]; then
	rm -f _testuint*
	printf "#include <stdio.h>\n#include <inttypes.h>
	\n#include <sys/types.h>\nint main(int argc, char *argv[])
	{printf(\"%%i\\\n\", (int)sizeof(uint64_t));return 0;}\n" > _testuint.c
	$CC $CFLAGS _testuint.c -o _testuint 2> /dev/null
	if [ ! -x _testuint ]; then
		printf "no\n\nERROR: No u_int64_t or uint64_t. Aborting\n"
		#  TODO: Automagically detect using various combinations
		#  of char, int, short, long etc.
		exit
	fi

	printf "typedef uint64_t u_int64_t;\n" >> config.h
	printf "uint64_t\n"
else
	printf "yes\n"
fi
rm -f _testuint.c _testuint


###############################################################################
#
#  OLD binary translation (BINTRANS):
#
###############################################################################

printf "checking for bintrans backend... "

BINTRANS=NO

if [ z$ENABLEMIPS = zNO ]; then
	printf "NO!\nTEMPORARY HACK/PROBLEM: Disabling bintrans for now,\n"
	printf "until things have stabilized.\n"
	NOBINTRANS=YES
fi

if [ z$NOBINTRANS = zYES ]; then
	printf "disabled\n"
else
	#  Alpha:
	if [ z"`uname -m`" = zalpha ]; then
		printf "#define ALPHA\n" >> config.h
		printf "#define BINTRANS\n" >> config.h
		printf "Alpha\n"
		BINTRANS=YES
	fi

	#  x86:
	if `uname -m|grep -v 64|grep -q 86`; then
		printf "#define I386\n" >> config.h
		printf "#define BINTRANS\n" >> config.h
		printf "i386\n"
		BINTRANS=YES
	fi

# MIPS not yet
#	#  MIPS:
#	if [ z"`uname -m`" = zmips ]; then
#		printf "#define MIPS\n" >> config.h
#		printf "#define BINTRANS\n" >> config.h
#		printf "MIPS\n"
#		BINTRANS=YES
#	fi

#	#  UltraSPARC:
#	if [ z"`uname -m`" = zsun4u ]; then
#		printf "#define SPARCV9\n" >> config.h
#		printf "#define BINTRANS\n" >> config.h
#		printf "SPARC V9\n"
#		BINTRANS=YES
#	else
#		if [ z"`uname -m`" = zsparc64 ]; then
#			printf "#define SPARCV9\n" >> config.h
#			printf "#define BINTRANS\n" >> config.h
#			printf "SPARC V9\n"
#			BINTRANS=YES
#		fi
#	fi

	if [ z$BINTRANS = zNO ]; then
		printf "not supported yet on this arch\n"
	fi
fi

if [ z$BINTRANS = zNO ]; then
	printf "#define DISABLE_BINTRANS\n" >> config.h
fi

###############################################################################
#
#  Dyntrans recompilation (native backend) support:
#
###############################################################################

if [ z$DYNTRANSBACKEND = zYES ]; then
	printf "Dyntrans: Not yet.\n"
	exit

	printf "checking for dyntrans backend... "
	DBFOUND=NO

	#  Alpha:
	if [ z"`uname -m`" = zalpha ]; then
		printf "#define DYNTRANS_BACKEND_ALPHA\n" >> config.h
		printf "Alpha\n"
		CPU_BACKENDS="$CPU_BACKENDS backend_alpha.o"
		DBFOUND=YES
	fi

	#  AMD64:
	#  TODO

#	#  UltraSPARC:
#	if [ z"`uname -m`" = zsun4u ]; then
#		printf "#define DYNTRANS_BACKEND_SPARC64\n" >> config.h
#		printf "UltraSPARC\n"
#		CPU_BACKENDS="$CPU_BACKENDS backend_sparc.o"
#		DBFOUND=YES
#	fi
#	if [ z"`uname -m`" = zsparc64 ]; then
#		printf "#define DYNTRANS_BACKEND_SPARC64\n" >> config.h
#		printf "UltraSPARC\n"
#		CPU_BACKENDS="$CPU_BACKENDS backend_sparc.o"
#		DBFOUND=YES
#	fi

	#  x86:
	if `uname -m|grep -q -v 64|grep -q 86`; then
		printf "#define DYNTRANS_BACKEND_I386\n" >> config.h
		printf "i386\n"
		CPU_BACKENDS="$CPU_BACKENDS backend_i386.o"
		DBFOUND=YES
	fi

	if [ z$DBFOUND = zYES ]; then
		printf "#define DYNTRANS_BACKEND\n" >> config.h
	else
		printf "not supported yet on this arch ("
		printf `uname -m`
		printf ")\n"
	fi
fi


###############################################################################

#  Host byte order?
printf "checking host endianness... "
rm -f _test_end*
printf '#include <stdio.h>
int main(int argc, char *argv[])
{  int x = 1; void *xp = (void *)&x; char *p = (char *)xp;
if (*p) printf("little\\\n"); else printf("big\\\n"); }
' > _test_end.c
$CC $CFLAGS _test_end.c -o _test_end 2> /dev/null
X=`./_test_end`
echo $X
if [ z$X = zlittle ]; then
	printf "#define HOST_LITTLE_ENDIAN\n" >> config.h
else
	if [ z$X = zbig ]; then
		printf "#define HOST_BIG_ENDIAN\n" >> config.h
	else
		echo "Error! Could not determine host's endianness."
		exit
	fi
fi
rm -f _test_end*

###############################################################################

INCLUDE=-Iinclude/
DINCLUDE=-I../include/

rm -f _testprog.c

CFLAGS="-O3 -g -pg -Wall"

echo C compiler flags: $CFLAGS $CWARNINGS
echo Linker flags: $OTHERLIBS
echo "CWARNINGS=$CWARNINGS" >> _Makefile.header
echo "COPTIM=$CFLAGS" >> _Makefile.header
echo "INCLUDE=$INCLUDE" >> _Makefile.header
echo "DINCLUDE=$DINCLUDE" >> _Makefile.header
echo "CC=$CC" >> _Makefile.header
echo "OTHERLIBS=$OTHERLIBS" >> _Makefile.header
echo "CPU_ARCHS=$CPU_ARCHS" >> _Makefile.header
echo "CPU_BACKENDS=$CPU_BACKENDS" >> _Makefile.header
echo "CPU_TOOLS=$CPU_TOOLS" >> _Makefile.header
echo "" >> _Makefile.header


#  Create the Makefiles:
#D=". src src/include src/cpus src/devices src/devices/fonts"
D=". src src/include src/cpus src/devices"
D="$D src/machines src/promemul"
for a in $D; do
	echo "creating $a/Makefile"
	touch $a/Makefile
	cat _Makefile.header > $a/Makefile
	cat $a/Makefile.skel >> $a/Makefile
done

#  Tail of config.h:
printf "\n#endif  /*  CONFIG_H  */\n" >> config.h

#  Remove temporary Makefile header:
rm -f _Makefile.header

echo Configured. You may now run make to build gxemul.