#!/usr/bin/bash
# Configure for Makefil#
# Warren W. Gay VE3WWG
# for APQ
#
# NOTES ABOUT READLINE HISTORY :
#
# The way history -s works, it replaces the last command in the history
# with what you provide. This leads to some difficult situations, where I
# would like to simply _add_ entries to the history. So don't expect
# everything you want to be found in the history. It is hit and miss. I
# have given up all hope of ever getting it totally right here. Maybe
# between bash and readline, this will be corrected someday.
#
# READLINE STUFF:
#
#    completion-ignore-case (Off)
#           If set to On, readline performs filename matching and completion
#           in a case-insensitive fashion.
#    completion-query-items (100)
#           This determines when the user is queried about viewing the  num-
#           ber  of  possible  completions generated by the possible-comple-
#           tions command.  It may be set to any integer value greater  than
#           or  equal  to  zero.   If  the number of possible completions is
#           greater than or equal to the value of this variable, the user is
#           asked  whether or not he wishes to view them; otherwise they are
#           simply listed on the terminal.
#    disable-completion (Off)
#           If set to On, readline will inhibit word completion.  Completion
#           characters will be inserted into the line as if  they  had  been
#           mapped to self-insert.
#    editing-mode (emacs)
#           Controls whether readline begins with a set of key bindings sim-
#           ilar to emacs or vi.  editing-mode can be set to either emacs or
#           vi.
#
#    history [n]
#    history -c
#    history -d offset
#    history -anrw [filename]
#    history -p arg [arg ...]
#    history -s arg [arg ...]
#
#    With no options, display the command history list with line num-
#    bers.  Lines listed with a * have been modified.	An argument of
#    n lists only the last n lines.  If filename is supplied,	it  is
#    used as the name of the history file; if not, the value of HIST-
#    FILE is used.  Options, if supplied, have	the  following	mean-
#    ings:
#
#    -c     Clear the history list by deleting all the entries.
#
#    -d offset
#    Delete the history entry at position offset.
#
#    -a     Append  the  ``new'' history lines (history lines entered
#    since the beginning of the current bash session)  to  the
#    history file.
#
#    -n     Read  the history lines not already read from the history
#    file into the current  history  list.   These  are	lines
#    appended  to  the history file since the beginning of the
#    current bash session.
#
#    -r     Read the contents of the history file and use them as the
#    current history.
#
#    -w     Write  the current history to the history file, overwrit-
#    ing the history file's contents.
#
#    -p     Perform history substitution on the  following  args  and
#    display  the  result  on  the  standard output.  Does not
#    store the results in the history list.  Each arg must  be
#    quoted to disable normal history expansion.
#
#    -s     Store  the	args  in  the history list as a single entry.
#    The last command in the history list  is  removed	before
#    the args are added.
#
#    The  return  value is 0 unless an invalid option is encountered,
#    an error occurs while reading or writing the  history  file,  an
#    invalid  offset is supplied as an argument to -d, or the history
#    expansion supplied as an argument to -p fails.

#
# STUFF WE DON'T WANT TO RECORD IN THE HISTORY :
#
HISTIGNORE="readit*:set *:if *:case *:while *:history*:*=*:get_info*:cat*:\
yesno*:unset *:upath(*:wpath(*:upath *:wpath *:find_path*:find_dll*:have_mstools*:\
eval *:echo *:#*:get_path*"

set -o history
history 500

set completion-ignore-case on
set completion-query-items 30
set disable-completion off

set -o vi		# Default to vi, even though emacs is better
set -eu

VERSION=$(cat ./APQ_VERSION)

#
# TELL THE USER THAT WE HAVE STARTED :
#
cat >/dev/tty <<EOF

THIS IS A WIN32 INSTALL OF APQ-$VERSION :

EOF

./GNATCONF

. ./gnat.conf

cat >/dev/tty <<EOF

  You have GNAT $GNAT_VERSION installed :

  Please choose your preference for input editing
  bindings:
EOF


#
# PROMPT TO AND READ FROM THE TTY
#
readit() {
	read -erp "$1" reply </dev/tty >/dev/tty
	history -s "$reply"
}


#
# ASK THE USER FOR THEIR EDIT PREFERENCES, SINCE THERE
# DOESN'T SEEM TO BE A RELIABLE WAY TO DETERMINE THIS
# IN ADVANCE:
#
while true; do
	cat >/dev/tty <<EOF

  e - emacs mode
  v - vi mode
  n - neither

EOF
	readit "Choose e/v/n ? "
	mode="$reply"

	case "$mode" in
	E* | e* )	mode=emacs;	break;;
	V* | v* )	mode=vi;	break;;
	N* | n* )	mode=none;	break;;
	esac
done

#
# SET THE EDITING MODE :
#
if [ "$mode" != none ] ; then
	set -o $mode
	set editing-mode $mode
	E=-e	# editing
else
	E=	# no editing
fi
unset mode	# no longer need this variable

#
# PROMPT FOR YES/NO ANSWER :
#
yesno() {
	while true ; do
		readit "$1 (Yes/No)? "
		case "$reply" in
		Y* | y* )	echo 1; return 0;;
		N* | n* )	echo 0; return 0;;
		* )		;;
		esac
	done
}

#
# CONVERT WINDOWS PATHNAME TO A CYGWIN UNIX PATHNAME
#
upath() {
	set +e
	cygpath "$1" 2>/dev/null
	return 0;
}

#
# CONVERT A CYGWIN UNIX PATHNAME TO A WINDOWS PATHNAME
#
wpath() {
	set +e
	cygpath -w "$1" 2>/dev/null
	return 0;
}

#
# PROMPT FOR A WINDOWS PATHNAME AND RETURN A CYGWIN UNIX PATHNAME
#
get_path() {
	readit "$1 : "
	win_path="$reply"
	cygpath "$win_path" 2>/dev/null
}

#
# LOCATE A FILE ON THE PATH
#
find_path() {
	FILE="$1"
	not_cwd="${2:-0}"	# When 1, do not consider current directory in search (for DLL searches)
	IFS=':'
	for dir in $PATH ; do
		if [ -r "$dir/$FILE" ] ; then
			if [ "$dir" != '.' -o $not_cwd -eq 0 ] ; then
				echo "$dir/$FILE"
				return 0
			fi
		fi
	done
	return 1
}

#
# LOCATE A DLL FILE
#
find_dll() {
	set +e
	PATH=".:$PATH" find_path "$1"
}

#
# LOCATE DLL ON PATH OTHER THAN CURRENT DIRECTORY
#
find_dll_not_cwd() {
	DLL="$1"
	set +e
	P=$(find_path "$DLL" 1)
	if [ $? -ne 0 ] ; then
		return 1; # Not found at all
	fi
	if [ $(cygpath -w "$P") = $(cygpath -w "$DLL") ] ; then
		return 1; # Current directory does not count
	fi

	echo $(dirname $P)
	return 0 # Found, and not in current directory
} 

#
# TEST TO SEE THAT WE HAVE THE MICROSOFT TOOLS NEEDED
#
have_mstools() {
	set +e

	type -p cl >/dev/null 2>&1	# Need MS CL compiler for compiling dll modules
	MSCL=$?
	type -p lib >/dev/null 2>&1	# Need MS LIB utility to generate export file (for dll)
	MSLIB=$?
	type -p link >/dev/null 2>&1	# Need MS LINK utility to create dll files
	MSLINK=$?

	if [ $MSCL -ne 0 -o $MSLIB -ne 0 -o $MSLINK -ne 0 ] ; then
		echo "You seem to be lacking Microsoft Visual Studio tools" >/dev/tty
		echo "or perhaps they are not on your PATH." >/dev/tty
		echo
		if [ $MSCL -ne 0 ] ; then 	echo "- Cannot locate Microsoft CL compiler."; fi
		if [ $MSLIB -ne 0 ] ; then 	echo "- Cannot locate Microsoft LIB utility for export files."; fi
		if [ $MSLINK -ne 0 ] ; then 	echo "- Cannot locate Microsoft LINK utility to create DLL files."; fi
		echo >/dev/tty
		MS=1
	else
		MS=0
	fi
	return $MS
}

#
# PROMPT FOR DATABASE FILE INFO
#
get_info() {
	DB="$1"		# PostgreSQL or MySQL

	echo >/dev/tty
	echo "Questions for $DB :" >/dev/tty
	echo >/dev/tty

	HAVE=$(yesno "Installing $DB database support ?")

	if [ $HAVE -gt 0 ] ; then
		while true ; do
			INCL_DIR=$(get_path "Windows pathname to $DB include directory")
			history -s $(cygpath -w "$INCL_DIR" 2>/dev/null)

			if [ -d "$INCL_DIR" ] ; then
				case "$DB" in
				PostgreSQL )	inclfile=libpq-fe.h;;
				MySQL )		inclfile=mysql.h;;
				esac
				if [ -r "$INCL_DIR/$inclfile" ] ; then
					break
				else
					echo "Include file $inclfile does not seem to be there." >/dev/tty
				fi
			else
				echo "Directory $(wpath "$INCL_DIR") does not exist." >/dev/tty
			fi
		done

		case "$DB" in
		PostgreSQL )	dllname=libpq.dll;;
		MySQL )		dllname=libmysql.dll;;
		esac

		if [ "X$dllname" != X ] ; then
			set +e
			DLLPATH=$(find_dll "$dllname")
			RC=$?
			history -s $(cygpath -w "$DLLPATH" 2>/dev/null)
			if [ $RC -ne 0 ] ; then
				echo "******************************************************" >/dev/tty
				echo "Sorry, but I was unable to find DLL $dllname." >/dev/tty
				echo "Check your PATH variable, or the location of the file." > /dev/tty
				echo "******************************************************" >/dev/tty
				exit 3
			else
				echo "Windows path of $DB DLL file is           : $(cygpath -w $DLLPATH 2>/dev/null)" >/dev/tty
			fi
		else
			DLLPATH=
		fi
		set -e
		if [ "$DB" = MySQL ] ; then
			while true ; do
				IMPLIBF=$(get_path "Windows path to libmysql.lib file          ")
				history -s $(cygpath -w "$IMPLIBF" 2>/dev/null)
				if [ -f "$IMPLIBF" ] ; then
					break;
				else
					echo "The file $(wpath "$IMPLIBF") does not exist." >/dev/tty
					echo "To build a DLL, I need the libmysql.lib import library." >/dev/tty
				fi
			done
		fi
	else
		INCL_DIR=
		DLLPATH=
		IMPLIBF=
	fi
	echo "HAVE=$HAVE INCL='$INCL_DIR' DLL='$DLLPATH' IMPLIBF='$IMPLIBF'"
}

#
# DETERMINE IF WE HAVE THE MICROSOFT VISUAL STUDIO UTILITIES :
# (CL, LIB AND LINK)
#
set +e
have_mstools
MSTOOLS=$?
set -e

#
# INFORM THE USER ABOUT THEIR OPTIONS WHEN NO MS TOOLS ARE AVAILABLE :
#
if [ $MSTOOLS -ne 0 ] ; then
	cat <<EOF >/dev/tty
****************************************************************

  APQ needs the Microsoft tools to build support for:

     - MySQL
     - Sybase

  If you are not including MySQL or Sybase support, then you do
  not need them, since GNAT can build what you need.

****************************************************************

EOF
else
	echo >/dev/tty
	echo "You seem to have the Microsoft Toolset available.." >/dev/tty
	echo >/dev/tty
fi

#
# SEE IF THE APQ_MYADAPTER.DLL IS ALREADY INSTALLED. IF SO,
# THEN WE CAN DETERMINE FROM THIS, THAT IS THE LIKELY PLACE
# THAT WE WANT TO RE-INSTALL THE DLL.
#
set +e
APQ_MYADAPTER=$(find_dll_not_cwd apq_myadapter.dll)	# Locate our DLL but not current directory
if [ $? -eq 0 ] ; then
	DLL_INSTPATH="$APQ_MYADAPTER"
else
	DLL_INSTPATH=
fi

#
# GET MySQL DATABASE INFORMATION :
#
eval $(get_info MySQL)
if [ $? -ne 0 ] ; then
	exit 13			# Failure in interrogation
fi

HAVE_MY=$HAVE				# Installing MySQL (or not)
MY_UINCL="$INCL"			# MySQL UNIX Include directory pathname
MY_WINCL=$(wpath "$MY_UINCL")		# Windows path of same
MY_UDLL="$DLL"				# Pathname to MySQL libmySQL.dll file
MY_WDLL=$(wpath "$MY_UDLL")		# Windows path of same
MY_UIMP="$IMPLIBF"			# UNIX pathname to MySQL import library (libmySQL.lib)
MY_WIMP=$(wpath "$MY_UIMP")		# Windows path of same
if [ $HAVE_MY -gt 0 ] ; then
	MY_OBJS="apq-mysql.o apq-mysql-client.o"
fi

eval $(get_info PostgreSQL)
if [ $? -ne 0 ] ; then
	exit 13
fi
echo >/dev/tty

HAVE_PG=$HAVE				# Installing PostgreSQL (or not)
if [ $HAVE_PG -ne 0 ] ; then
	PG_UINCL="$INCL"			# UNIX pathname to include files
	PG_WINCL=$(wpath "$PG_UINCL")		# Windows pathname to same
	PG_UDLL="$DLL"				# UNIX pathname to libpq.dll
	PG_WDLL=$(wpath "$PG_UDLL")		# Windows pathname to same
	PG_OBJS="apq-postgresql.o apq-postgresql-client.o numeric.o notices.o"
else
	PG_UINCL=
	PG_WINCL=
	PG_UDLL=
	PG_WDLL=
	PG_OBJS=
fi

######################################################################
# Test for SYBASE support
######################################################################

if [ "${SYBASE:-NOT}" = NOT ] ; then
	if [ -d /opt/sybase ] ; then
		if [ -r /opt/sybase/SYBASE.sh ] ; then
			set +u
			. /opt/sybase/SYBASE.sh
			set -u
		fi
	fi
fi

if [ "${SYBASE:-NOT}" != NOT ] ; then
	HAVE_SY=1
else
	HAVE_SY=0
fi

if [ $HAVE_SY -gt 0 ] ; then
	echo "    You have Sybase support."
fi

if [ $HAVE_SY -gt 0 ] ; then
	SY=$(cygpath "$SYBASE" 2>/dev/null)
	WP=$(cygpath -w "$SY/$SYBASE_OCS/include")
	SY_INCL="-I$WP"
	SY_OBJS="apq-sybase.o apq-sybase-client.o"

	UP="$SY/$SYBASE_OCS/lib"
	WP=$(cygpath -w "$UP")
	SY_LIBS="-L$WP -lcs -lct"
	SY_UIMP="$UP/libcs.lib $UP/libct.lib"
	SY_WIMP="$WP\\libcs.lib $WP\\libct.lib"
else
	SY_INCL=
	SY_LIBS=
	SY_OBJS=
	SY_UIMP=
	SY_WIMP=
fi

#
# TEST TO SEE IF WE HAVE ANY DATABASES TO WORK WITH
#
if [ $(expr $HAVE_PG + $HAVE_MY + $HAVE_SY) -eq 0 ] ; then
	cat <<EOF >/dev/tty

------------------------------------------------------------------------------

	Based upon the configure script's findings, and your answers,
	there were no databases left to configure the APQ package
	to build for.

	Also check any exported environment variables like HAVE_PG/HAVE_MY.

	Consequently, the configuration of APQ will be abandoned.

	Please install your database software first, and then
	try building APQ again later.

------------------------------------------------------------------------------

EOF
	exit 13
fi

#
# CHECK MICROSOFT TOOL DEPENDENCIES
#
if [ $MSTOOLS -ne 0 ] ; then
	echo >/dev/tty
	echo "*********************************************************" >/dev/tty
	echo "You are building support for MySQL, yet lack the Microsoft" >/dev/tty
	echo "toolset. I feel your pain.  However, you may still build" >/dev/tty
	echo "the remaining APQ components using GNAT, provided that you" >/dev/tty
	echo "have the binary file apq_myadapter.dll available. ">/dev/tty
	echo "*********************************************************" >/dev/tty
	echo >/dev/tty
	if [ ! -f apq_myadapter.dll ] ; then
		echo >/dev/tty
		echo "*********************************************************" >/dev/tty
		echo "It appears that you do not have it downloaded, or it" >/dev/tty
		echo "does not exist in the current directory. Please place" >/dev/tty
		echo "a copy of the APQ_MYADAPTER.DLL into the current" >/dev/tty
		echo "directory, and run configure again." >/dev/tty
		echo "*********************************************************" >/dev/tty
		echo >/dev/tty
		exit 2;
	else
		echo >/dev/tty
		echo "******************************************************" >/dev/tty
		echo "I see you have the DLL in the current directory. Good." >/dev/tty
		echo "******************************************************" >/dev/tty
		echo >/dev/tty
	fi
	echo >/dev/tty
fi		

#
# DETERMINE WHERE THE DLL(S) SHOULD BE INSTALLED :
#
if [ "$DLL_INSTPATH" = "" ] ; then
	if [ $HAVE_MY -ne 0 -a $HAVE_PG -ne 0 ] ; then
		DLL_INSTPATH=$(find_dll_not_cwd libmysql.dll)
	elif [ $HAVE_MY -ne 0 ] ; then
		DLL_INSTPATH=$(find_dll_not_cwd libmysql.dll)
	elif [ $HAVE_PG -ne 0 ] ; then
		DLL_INSTPATH=$(find_dll_not_cwd libpq.dll)
	elif [ $HAVE_SY -ne 0 ] ; then
		true;	# Ignore this one for sybase (there are multiple dlls)
	else
		echo "Bug!"
		exit 13
	fi
fi

history -s $(cygpath -w "$DLL_INSTPATH" 2>/dev/null)

#
# GENERATE MAKEINCL.WIN32 FILE
#
set +ue

cat >config.win32 <<EOF
# win32.config : Generated by ./win32_config on $(date)

VERSION=$(cat APQ_VERSION)

#DBG=-g
#OPTZ=-O0

# MSTOOLS=0  Micrsoft Toolset available
# MSTOOLS=1  Micrsoft Toolset not available
MSTOOLS=$MSTOOLS
CC=gcc

ZOPTS=$DBG $OPTZ
COPTS=-Wall $ZOPTS
AOPTS=-gnata -gnatf -gnato -gnatwp $ZOPTS

#
# MySQL Config :
#
HAVE_MY=$HAVE_MY
MY_UINCL=$MY_UINCL
MY_DLL=$MY_UDLL
MY_UIMP=$MY_UIMP
MY_WIMP=$MY_WIMP

MY_INCL=-I$(cygpath -w $MY_UINCL 2>/dev/null)
MY_OBJS=${MY_OBJS:-}

#
# PostgreSQL Config :
#
HAVE_PG=$HAVE_PG
PG_UINCL="$PG_UINCL"
PG_DLL="$PG_UDLL"

PG_INCL=-I$(cygpath -w $PG_UINCL 2>/dev/null)
PG_OBJS=${PG_OBJS:-}

#
# Sybase Config :
#
HAVE_SY=$HAVE_SY
SY_INCL=$SY_INCL
SY_LIBS=$SY_LIBS
SY_OBJS=$SY_OBJS
SY_UIMP=$SY_UIMP
SY_WIMP=$SY_WIMP

#
# DLL INSTALL PARAMETERS
#
DLL_UINSTPATH=$DLL_INSTPATH
DLL_WINSTPATH=$(cygpath -w "$DLL_INSTPATH" 2>/dev/null)

#
# GNAT INFO
#
GNAT_VERSION=$(./gnat_info -v)
GNAT_ROOT=$(cygpath "$(./gnat_info -r)")
GNAT_BIN=$(cygpath "$(./gnat_info -b)")
GNAT_BINDINGS=$(cygpath "$(./gnat_info -B)")

# End
EOF

ln -s Makefile.win32 GNUmakefile

XC=0
cat <<EOF >/dev/tty

    You are now ready to 'make'

EOF

APQ_INSTALLED=$(./gnat_info -a)

if [ "$APQ_INSTALLED" != "NOT INSTALLED" ] ; then
	cat >/dev/tty <<EOF

    ********************************************
    WARNING: YOU ALREADY HAVE APQ-$APQ_INSTALLED INSTALLED.
    ********************************************

    APQ will not build successfully, while APQ-$APQ_INSTALLED
    remains installed.

    You can uninstall APQ from the Control Panel,
    using Add/Remove Programs.

    Look for the entry:

       "APQ-$APQ_INSTALLED (remove only)"

EOF
	XC=1
fi

set +e
MAKENSIS=$(find_path makensis)
if [ $? -ne 0 -o "$MAKENSIS" = "" ] ; then
	cat >/dev/tty <<EOF

        ******************************************************
        WARNING: You do not appear to have makensis installed.
        ******************************************************

        You will need this tool to build the win32 installer.
        Download it from 

            http://nsis.sourceforge.net/site/Home.2.0.html

        and install it prior to performing the 'make install'
        step.

EOF
	XC=1

fi

cat <<EOF >/dev/tty

    To proceed with the build, perform the following:

    $ make		 (do 'make clean' prior to rebuids)
    $ make installer     (optional)
    $ make install

EOF

exit $XC

# End
