#!/bin/sh

show_usage() {
cat <<EOT
Usage: ./configure [OPTION]...

This script creates necessary configuration files to build/install.

Main options:
  --prefix=[path]    Base path for build/install.  Default: /usr/local
  --qtdir=[path]     Directory where Qt is installed.
  --help             This help text.

EOT
}

while [ $# -gt 0 ]; do
	case "$1" in
		--prefix=*)
			PREFIX=`expr "${1}" : "--prefix=\(.*\)"`
			shift
			;;

		--qtdir=*)
			QTDIR=`expr "${1}" : "--qtdir=\(.*\)"`
			shift
			;;

		--debug)
			QC_DEBUG="Y"
			shift
			;;
		--help) show_usage; exit ;;
		*) show_usage; exit ;;
	esac
done

PREFIX=${PREFIX:-/usr/local}

echo "Configuring Qt Cryptographic Architecture (QCA) ..."

if [ "$QC_DEBUG" = "Y" ]; then
echo
echo PREFIX=$PREFIX
echo QTDIR=$QTDIR
echo
fi

printf "Verifying Qt 3.x Multithreaded (MT) build environment ... "

if [ -z "$QTDIR" ]; then
	if [ "$QC_DEBUG" = "Y" ]; then
		echo \$QTDIR not set... trying to find Qt manually
	fi
	for p in /usr/lib/qt /usr/share/qt /usr/share/qt3 /usr/local/lib/qt /usr/local/share/qt /usr/lib/qt3 /usr/local/lib/qt3 /usr/X11R6/share/qt /usr/qt/3 ; do
		if [ -d "$p/mkspecs" ]; then
			QTDIR=$p
			break;
		fi;
	done
	if [ -z "$QTDIR" ]; then
		echo fail
		echo
		echo Unable to find Qt 'mkspecs'. Please set QTDIR
		echo manually. Perhaps you need to install Qt 3
		echo development utilities. You may download them either
		echo from the vendor of your operating system or from
		echo www.trolltech.com
		echo
		exit 1;
	fi
fi

if [ ! -x "$QTDIR/bin/qmake" ]; then
	if [ "$QC_DEBUG" = "Y" ]; then
		echo Warning: qmake not in \$QTDIR/bin/qmake
		echo trying to find it in \$PATH
	fi
	qm=`type -p qmake`
	if [ -x "$qm" ]; then
		if [ "$QC_DEBUG" = "Y" ]; then
			echo qmake found in $qm
		fi
	else
		echo fail
		echo
		echo Sorry, you seem to have a very unusual setup,
		echo or I missdetected \$QTDIR=$QTDIR
		echo
		echo Please set \$QTDIR manually and make sure that
		echo \$QTDIR/bin/qmake exists.
		echo
		exit 1;
	fi
else
	qm=$QTDIR/bin/qmake
fi

gen_files() {
cat >$1/modules.cpp <<EOT

EOT
cat >$1/modules_new.cpp <<EOT

EOT
cat >$1/conf.cpp <<EOT
#include<stdio.h>
#include<stdlib.h>
#include<qstring.h>
#include<qdict.h>
#include<qptrlist.h>
#include<qfileinfo.h>
#include<qfile.h>
#include<qdir.h>
#include<qstringlist.h>

class Conf;

class ConfObj
{
public:
	ConfObj(Conf *c);
	virtual ~ConfObj();

	virtual QString name() const=0;
	virtual QString shortname() const=0;
	virtual bool exec()=0;

	Conf *conf;
	bool required;
	bool disabled;
};

typedef QPtrList<ConfObj> ConfObjList;
typedef QPtrListIterator<ConfObj> ConfObjListIt;

class Conf
{
public:
	Conf() : vars(17)
	{
		list.setAutoDelete(true);
		vars.setAutoDelete(true);

		vars.insert("QMAKE_INCDIR_X11", new QString(X11_INC));
		vars.insert("QMAKE_LIBDIR_X11", new QString(X11_LIBDIR));
		vars.insert("QMAKE_LIBS_X11",   new QString(X11_LIB));
		vars.insert("QMAKE_CC",         new QString(CC));
	}

	~Conf()
	{
	}

	void added(ConfObj *o)
	{
		list.append(o);
	}

	QString getenv(const QString &var)
	{
		char *p = ::getenv(var.latin1());
		if(!p)
			return QString::null;
		return QString(p);
	}

	bool exec()
	{
		ConfObjListIt it(list);
		for(ConfObj *o; (o = it.current()); ++it) {
			// if this was a disabled-by-default option, check if it was enabled
			if(o->disabled) {
				QString v = QString("QC_ENABLE_") + o->shortname();
				if(getenv(v) != "Y")
					continue;
			}
			// and the opposite?
			else {
				QString v = QString("QC_DISABLE_") + o->shortname();
				if(getenv(v) == "Y")
					continue;
			}

			printf("Checking for %s ...", o->name().latin1());
			fflush(stdout);
			bool ok = o->exec();
			if(ok)
				printf(" yes\n");
			else
				printf(" no\n");
			if(!ok && o->required) {
				printf("\nError: need %s!\n", o->name().latin1());
				return false;
			}
		}
		return true;
	}

	const QString & qvar(const QString &s)
	{
		QString *p = vars.find(s);
		if(p)
			return *p;
		else
			return blank;
	}

	QString expandIncludes(const QString &inc)
	{
		return QString("-I") + inc;
	}

	QString expandLibs(const QString &lib)
	{
		return QString("-L") + lib;
	}

	int doCommand(const QString &s)
	{
		//printf("[%s]\n", s.latin1());
		int r = system((s + " 1>/dev/null 2>/dev/null").latin1());
		//printf("returned: %d\n", r);
		return r;
	}

	bool doCompileAndLink(const QString &filedata, const QString &flags, int *retcode=0)
	{
		QDir dir(".");
		QString fname = "atest.c";
		QString out = "atest";
		QFile f(fname);
		QCString cs = filedata.latin1();
		if(!f.open(IO_WriteOnly | IO_Truncate))
			return false;
		f.writeBlock(cs.data(), cs.length());
		f.close();

		QString str = qvar("QMAKE_CC") + ' ' + fname + " -o " + out + ' ' + flags;
		int r = doCommand(str);
		if(r == 0 && retcode)
			*retcode = doCommand(QString("./") + out);
		dir.remove(fname);
		dir.remove(out);
		if(r != 0)
			return false;
		return true;
	}

	bool checkHeader(const QString &path, const QString &h)
	{
		QFileInfo fi(path + '/' + h);
		if(fi.exists())
			return true;
		return false;
	}

	bool findHeader(const QString &h, const QStringList &ext, QString *inc)
	{
		if(checkHeader("/usr/include", h)) {
			*inc = "";
			return true;
		}
		QStringList dirs;
		dirs += "/usr/local/include";
		dirs += ext;
		for(QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it) {
			if(checkHeader(*it, h)) {
				*inc = *it;
				return true;
			}
		}
		return false;
	}

	bool checkLibrary(const QString &path, const QString &name)
	{
		QString str =
			"int main()\n"
			"{\n"
			"    return 0;\n"
			"}\n";

		QString extra;
		if(!path.isEmpty())
			extra += QString("-L") + path + ' ';
		extra += QString("-l") + name;
		if(!doCompileAndLink(str, extra))
			return false;
		return true;
	}

	bool findLibrary(const QString &name, QString *lib)
	{
		if(checkLibrary("", name)) {
			*lib = "";
			return true;
		}
		if(checkLibrary("/usr/local/lib", name)) {
			*lib = "/usr/local/lib";
			return true;
		}
		return false;
	}

	void addDefine(const QString &str)
	{
		if(DEFINES.isEmpty())
			DEFINES = str;
		else
			DEFINES += QString(" ") + str;
	}

	void addLib(const QString &str)
	{
		if(LIBS.isEmpty())
			LIBS = str;
		else
			LIBS += QString(" ") + str;
	}

	void addIncludePath(const QString &str)
	{
		if(INCLUDEPATH.isEmpty())
			INCLUDEPATH = str;
		else
			INCLUDEPATH += QString(" ") + str;
	}

	void addExtra(const QString &str)
	{
		extra += str + '\n';
	}

	QString DEFINES;
	QString INCLUDEPATH;
	QString LIBS;
	QString extra;

private:
	ConfObjList list;
	QDict<QString> vars;
	QString blank;
};

ConfObj::ConfObj(Conf *c)
{
	conf = c;
	conf->added(this);
	required = false;
	disabled = false;
}

ConfObj::~ConfObj()
{
}

#include"modules.cpp"

//----------------------------------------------------------------------------
// main
//----------------------------------------------------------------------------
int main()
{
	Conf *conf = new Conf;
	ConfObj *o;
	o = 0;
#include"modules_new.cpp"

	printf("ok\n");
	bool success = false;
	if(conf->exec()) {
		QFile f("conf.pri");
		if(!f.open(IO_WriteOnly | IO_Truncate)) {
			printf("Error writing %s\n", f.name().latin1());
			return 1;
		}

		QString str;
		str += "# qconf\n";
		if(!conf->DEFINES.isEmpty())
			str += "DEFINES += " + conf->DEFINES + '\n';
		if(!conf->INCLUDEPATH.isEmpty())
			str += "INCLUDEPATH += " + conf->INCLUDEPATH + '\n';
		if(!conf->LIBS.isEmpty())
			str += "LIBS += " + conf->LIBS + '\n';
		if(!conf->extra.isEmpty())
			str += conf->extra;
		str += '\n';

		char *p = getenv("BINDIR");
		if(p) {
			str += QString("target.path = ") + p + '\n';
			str += "INSTALLS += target\n";
		}

		QCString cs = str.latin1();
		f.writeBlock(cs.data(), cs.length());
		f.close();
		success = true;
	}
	delete conf;

	if(success)
		return 0;
	else
		return 1;
}

EOT
cat >$1/conf.pro <<EOT
TEMPLATE = app
CONFIG += qt x11 thread console
TARGET = conf

DEFINES += X11_INC='"\$\$QMAKE_INCDIR_X11"'
DEFINES += X11_LIBDIR='"\$\$QMAKE_LIBDIR_X11"'
DEFINES += X11_LIB='"\$\$QMAKE_LIBS_X11"'
DEFINES += CC='"\$\$QMAKE_CC"'

SOURCES += conf.cpp

EOT
}

export PREFIX
export QTDIR
rm -rf .qconftemp
(
	mkdir .qconftemp
	gen_files .qconftemp
	cd .qconftemp
	$qm conf.pro >/dev/null
	QTDIR=$QTDIR make clean >/dev/null 2>&1
	QTDIR=$QTDIR make >../conf.log 2>&1
)

if [ "$?" != "0" ]; then
	rm -rf .qconftemp
	echo fail
	echo
	echo "There was an error compiling 'conf'.  Be sure you have a proper"
	echo "Qt 3.x Multithreaded (MT) build environment set up."
	if [ ! -f "$QTDIR/lib/libqt-mt.so.3" ]; then
		echo
		echo "One possible reason is that you don't have"
		echo "libqt-mt.so.3 installed in $QTDIR/lib/."
	fi
	echo
	exit 1;
fi

.qconftemp/conf
ret="$?"
if [ "$ret" = "1" ]; then
	rm -rf .qconftemp
	echo
	exit 1;
else
	if [ "$ret" != "0" ]; then
		rm -rf .qconftemp
		echo fail
		echo
		echo Unexpected error launching 'conf'
		echo
		exit 1;
	fi
fi
rm -rf .qconftemp

if [ -x "./qcextra" ]; then
	./qcextra
fi
# run qmake
$qm qca.pro
if [ "$?" != "0" ]; then
	echo
	exit 1;
fi
cat >Makefile.tmp <<EOT
export QTDIR = $QTDIR
EOT
cat Makefile >> Makefile.tmp
rm -f Makefile
cp -f Makefile.tmp Makefile
rm -f Makefile.tmp

echo
echo Good, your configure finished.  Now run \'make\'.
echo
