#!/bin/sh
#
# Generated by qconf 2.0 ( https://github.com/psi-plus/qconf )
#

show_usage() {
cat <<EOT
Usage: $0 [OPTION]...

This script creates necessary configuration files to build/install.

Main options:
  --qtdir=[path]        Directory where Qt is installed.
  --static              Create a static library instead of shared.
  --extraconf=[conf]    Extra configuration for nonstandard cases.
  --verbose             Show extra configure output.
  --qtselect=[N]        Select major Qt version (4 or 5).
  --help                This help text.

Project options:
  --release                   Build with debugging turned off (default).
  --debug                     Build with debugging turned on.
  --debug-and-release         Build two versions, with and without debugging
                              turned on (mac only).
  --no-separate-debug-info    Do not store debug information in a separate
                              file (default for mac).
  --separate-debug-info       Strip debug information into a separate .debug
                              file (default for non-mac).
  --no-framework              Do not build as a Mac framework.
  --framework                 Build as a Mac framework (default).
  --universal                 Build with Mac universal binary support.
  --mac-sdk=[path]            Path to Mac universal SDK (PPC host only).
  --enable-tests              Build examples and unittests.

Dependency options:
  --with-qca-inc=[path]      Path to QCA include files
  --with-qca-lib=[path]      Path to QCA library or framework files
  --with-zlib-inc=[path]     Path to zlib include files
  --with-zlib-lib=[path]     Path to zlib library files
  --with-qjdns-inc=[path]    Path to QJDns include files
  --with-qjdns-lib=[path]    Path to QJDns library files
  --with-b2-inc=[path]       Path to libb2 include files
  --with-b2-lib=[path]       Path to libb2 library or framework files

EOT
}

# which/make detection adapted from Qt
which_command() {
    ALL_MATCHES=
    if [ "$1" = "-a" ]; then
        ALL_MATCHES="-a"
        shift
    fi

    OLD_HOME=$HOME
    HOME=/dev/null
    export HOME

    WHICH=`which which 2>/dev/null`
    if echo $WHICH | grep 'shell built-in command' >/dev/null 2>&1; then
        WHICH=which
    elif [ -z "$WHICH" ]; then
        if which which >/dev/null 2>&1; then
            WHICH=which
        else
            for a in /usr/ucb /usr/bin /bin /usr/local/bin; do
                if [ -x $a/which ]; then
                    WHICH=$a/which
                    break
                fi
            done
        fi
    fi

    RET_CODE=1
    if [ -z "$WHICH" ]; then
        OLD_IFS=$IFS
        IFS=:
        for a in $PATH; do
            if [ -x $a/$1 ]; then
                echo "$a/$1"
                RET_CODE=0
                [ -z "$ALL_MATCHES" ] && break
            fi
        done
        IFS=$OLD_IFS
        export IFS
    else
        a=`"$WHICH" "$ALL_MATCHES" "$1" 2>/dev/null`
        if [ ! -z "$a" -a -x "$a" ]; then
            echo "$a"
            RET_CODE=0
        fi
    fi
    HOME=$OLD_HOME
    export HOME
    return $RET_CODE
}
WHICH=which_command

# find a make command
if [ -z "$MAKE" ]; then
    MAKE=
    for mk in gmake make; do
        if $WHICH $mk >/dev/null 2>&1; then
            MAKE=`$WHICH $mk`
            break
        fi
    done
    if [ -z "$MAKE" ]; then
        echo "You don't seem to have 'make' or 'gmake' in your PATH."
        echo "Cannot proceed."
        exit 1
    fi
fi

show_qt_info() {
    printf "Be sure you have a proper Qt 4.0+ build environment set up.  This means not\n"
    printf "just Qt, but also a C++ compiler, a make tool, and any other packages\n"
    printf "necessary for compiling C++ programs.\n"
    printf "\n"
    printf "If you are certain everything is installed, then it could be that Qt is not\n"
    printf "being recognized or that a different version of Qt is being detected by\n"
    printf "mistake (for example, this could happen if \$QTDIR is pointing to a Qt 3\n"
    printf "installation).  At least one of the following conditions must be satisfied:\n"
    printf "\n"
    printf " 1) --qtdir is set to the location of Qt\n"
    printf " 2) \$QTDIR is set to the location of Qt\n"
    printf " 3) QtCore is in the pkg-config database\n"
    printf " 4) qmake is in the \$PATH\n"
    printf "\n"
    printf "This script will use the first one it finds to be true, checked in the above\n"
    printf "order.  #3 and #4 are the recommended options.  #1 and #2 are mainly for\n"
    printf "overriding the system configuration.\n"
    printf "\n"
}

while [ $# -gt 0 ]; do
    optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
    case "$1" in
        --qtdir=*)
            EX_QTDIR=$optarg
            shift
            ;;

        --static)
            QC_STATIC="Y"
            shift
            ;;

        --extraconf=*)
            QC_EXTRACONF=$optarg
            shift
            ;;

        --release)
            QC_RELEASE="Y"
            shift
            ;;

        --debug)
            QC_DEBUG="Y"
            shift
            ;;

        --debug-and-release)
            QC_DEBUG_AND_RELEASE="Y"
            shift
            ;;

        --no-separate-debug-info)
            QC_NO_SEPARATE_DEBUG_INFO="Y"
            shift
            ;;

        --separate-debug-info)
            QC_SEPARATE_DEBUG_INFO="Y"
            shift
            ;;

        --no-framework)
            QC_NO_FRAMEWORK="Y"
            shift
            ;;

        --framework)
            QC_FRAMEWORK="Y"
            shift
            ;;

        --universal)
            QC_UNIVERSAL="Y"
            shift
            ;;

        --mac-sdk=*)
            QC_MAC_SDK=$optarg
            shift
            ;;

        --enable-tests)
            QC_ENABLE_TESTS="Y"
            shift
            ;;

        --with-qca-inc=*)
            QC_WITH_QCA_INC=$optarg
            shift
            ;;

        --with-qca-lib=*)
            QC_WITH_QCA_LIB=$optarg
            shift
            ;;

        --with-zlib-inc=*)
            QC_WITH_ZLIB_INC=$optarg
            shift
            ;;

        --with-zlib-lib=*)
            QC_WITH_ZLIB_LIB=$optarg
            shift
            ;;

        --with-qjdns-inc=*)
            QC_WITH_QJDNS_INC=$optarg
            shift
            ;;

        --with-qjdns-lib=*)
            QC_WITH_QJDNS_LIB=$optarg
            shift
            ;;

        --with-b2-inc=*)
            QC_WITH_B2_INC=$optarg
            shift
            ;;

        --with-b2-lib=*)
            QC_WITH_B2_LIB=$optarg
            shift
            ;;

        --verbose)
            QC_VERBOSE="Y"
            shift
            ;;
        --qtselect=*)
            QC_QTSELECT="${optarg}"
            shift
            ;;
        --help) show_usage; exit ;;
        *) echo "configure: WARNING: unrecognized options: $1" >&2; shift; ;;
    esac
done


echo "Configuring Iris ..."

if [ "$QC_VERBOSE" = "Y" ]; then
echo
echo EX_QTDIR=$EX_QTDIR
echo QC_STATIC=$QC_STATIC
echo QC_EXTRACONF=$QC_EXTRACONF
echo QC_RELEASE=$QC_RELEASE
echo QC_DEBUG=$QC_DEBUG
echo QC_DEBUG_AND_RELEASE=$QC_DEBUG_AND_RELEASE
echo QC_NO_SEPARATE_DEBUG_INFO=$QC_NO_SEPARATE_DEBUG_INFO
echo QC_SEPARATE_DEBUG_INFO=$QC_SEPARATE_DEBUG_INFO
echo QC_NO_FRAMEWORK=$QC_NO_FRAMEWORK
echo QC_FRAMEWORK=$QC_FRAMEWORK
echo QC_UNIVERSAL=$QC_UNIVERSAL
echo QC_MAC_SDK=$QC_MAC_SDK
echo QC_ENABLE_TESTS=$QC_ENABLE_TESTS
echo QC_WITH_QCA_INC=$QC_WITH_QCA_INC
echo QC_WITH_QCA_LIB=$QC_WITH_QCA_LIB
echo QC_WITH_ZLIB_INC=$QC_WITH_ZLIB_INC
echo QC_WITH_ZLIB_LIB=$QC_WITH_ZLIB_LIB
echo QC_WITH_QJDNS_INC=$QC_WITH_QJDNS_INC
echo QC_WITH_QJDNS_LIB=$QC_WITH_QJDNS_LIB
echo QC_WITH_B2_INC=$QC_WITH_B2_INC
echo QC_WITH_B2_LIB=$QC_WITH_B2_LIB
echo
fi

printf "Verifying Qt build environment ... "

if [ -z "$QC_QTSELECT" ]; then
    QC_QTSELECT="$(echo $QT_SELECT | tr -d "qt")"
fi

if [ ! -z "$QC_QTSELECT" ]; then
    QTSEARCHTEXT="$QC_QTSELECT"
else
    QTSEARCHTEXT="4 or 5"
fi

# run qmake and check version
qmake_check() {
    if [ -x "$1" ]; then
        cmd="\"$1\" -query QT_VERSION"
        if [ "$QC_VERBOSE" = "Y" ]; then
            echo "running: $cmd"
        fi
        vout=`/bin/sh -c "$cmd" 2>&1`
        case "${vout}" in
            *.*.*)
                vmaj="${vout%%.*}"
                if [ ! -z "$QC_QTSELECT" ]; then
                    if [ "$vmaj" = "$QC_QTSELECT" ]; then
                        return 0
                    fi
                else
                    if [ "$vmaj" = "4" ] || [ "$vmaj" = "5" ]; then
                        return 0
                    fi
                fi
                ;;
        esac
        if [ "$QC_VERBOSE" = "Y" ]; then
            echo "Warning: $1 not for Qt ${QTSEARCHTEXT}"
        fi
    fi
    return 1
}

if [ "$QC_VERBOSE" = "Y" ]; then
    echo
fi

qm=""
qt4_names="qmake-qt4 qmake4"
qt5_names="qmake-qt5 qmake5"
names="qmake"
if [ -z "$QC_QTSELECT" ]; then
    names="${qt5_names} ${qt4_names} $names"
else
    if [ "$QC_QTSELECT" = "4" ]; then
        names="${qt4_names} $names"
    elif [ "$QC_QTSELECT" -ge "5" ]; then
        names="${qt5_names} $names"
    fi
fi

if [ -z "$qm" ] && [ ! -z "$EX_QTDIR" ]; then
    # qt4 check: --qtdir
    for n in $names; do
        qstr=$EX_QTDIR/bin/$n
        if qmake_check "$qstr"; then
            qm=$qstr
            break
        fi
    done
    if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
        echo "Warning: qmake not found via --qtdir"
    fi

elif [ -z "$qm" ] && [ ! -z "$QTDIR" ]; then
    # qt4 check: QTDIR
    for n in $names; do
        qstr=$QTDIR/bin/$n
        if qmake_check "$qstr"; then
            qm=$qstr
            break
        fi
    done
    if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
        echo "Warning: qmake not found via \$QTDIR"
    fi

else
    # Try all other implicit checks

    # qtchooser
    if [ -z "$qm" ]; then
        qtchooser=$($WHICH qtchooser 2>/dev/null)
        if [ ! -z "$qtchooser" ]; then
            if [ ! -z "$QC_QTSELECT" ]; then
                versions="$QC_QTSELECT"
            else
                cmd="$qtchooser --list-versions"
                if [ "$QC_VERBOSE" = "Y" ]; then
                    echo "running: $cmd"
                fi
                versions=`$cmd`
            fi
            for version in $versions; do
                cmd="$qtchooser -run-tool=qmake -qt=${version} -query QT_INSTALL_BINS"
                if [ "$QC_VERBOSE" = "Y" ]; then
                    echo "running: $cmd"
                fi
                qtbins=`$cmd 2>/dev/null`
                if [ ! -z "$qtbins" ] && qmake_check "$qtbins/qmake"; then
                    qm="$qtbins/qmake"
                    break
                fi
            done
        fi
    fi
    if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
        echo "Warning: qmake not found via qtchooser"
    fi

    # qt4: pkg-config
    if [ -z "$qm" ]; then
        cmd="pkg-config QtCore --variable=exec_prefix"
        if [ "$QC_VERBOSE" = "Y" ]; then
            echo "running: $cmd"
        fi
        str=`$cmd 2>/dev/null`
        if [ ! -z "$str" ]; then
            for n in $names; do
                qstr=$str/bin/$n
                if qmake_check "$qstr"; then
                    qm=$qstr
                    break
                fi
            done
        fi
    fi
    if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
        echo "Warning: qmake not found via pkg-config"
    fi

    # qmake in PATH
    if [ -z "$qm" ]; then
        for n in $names; do
            qstr=`$WHICH -a $n 2>/dev/null`
            for q in $qstr; do
                if qmake_check "$q"; then
                    qm="$q"
                    break
                fi
            done
            if [ ! -z "$qm" ]; then
                break
            fi
        done
    fi
    if [ -z "$qm" ] && [ "$QC_VERBOSE" = "Y" ]; then
        echo "Warning: qmake not found via \$PATH"
    fi

    # end of implicit checks
fi

if [ -z "$qm" ]; then
    if [ "$QC_VERBOSE" = "Y" ]; then
        echo " -> fail"
    else
        echo "fail"
    fi
    printf "\n"
    printf "Reason: Unable to find the 'qmake' tool for Qt ${QTSEARCHTEXT}.\n"
    printf "\n"
    show_qt_info
    exit 1;
fi
if [ "$QC_VERBOSE" = "Y" ]; then
    echo qmake found in "$qm"
fi

# try to determine the active makespec
defmakespec=$QMAKESPEC
if [ -z "$defmakespec" ]; then
    if $WHICH readlink >/dev/null 2>&1; then
        READLINK=`$WHICH readlink`
    fi
    if [ ! -z "$READLINK" ]; then
        qt_mkspecsdir=`"$qm" -query QT_INSTALL_DATA`/mkspecs
        if [ -d "$qt_mkspecsdir" ] && [ -h "$qt_mkspecsdir/default" ]; then
            defmakespec=`$READLINK $qt_mkspecsdir/default`
        fi
    fi
fi

if [ "$QC_VERBOSE" = "Y" ]; then
    echo makespec is $defmakespec
fi

qm_spec=""
# if the makespec is macx-xcode, force macx-g++
if [ "$defmakespec" = "macx-xcode" ]; then
    qm_spec=macx-g++
    QMAKESPEC=$qm_spec
    export QMAKESPEC
    if [ "$QC_VERBOSE" = "Y" ]; then
        echo overriding makespec to $qm_spec
    fi
fi

gen_files() {
cat >"$1/modules.cpp" <<EOT
#line 1 "qt42.qcm"
/*
-----BEGIN QCMOD-----
name: Qt >= 4.2
-----END QCMOD-----
*/
class qc_qt42 : public ConfObj
{
public:
    qc_qt42(Conf *c) : ConfObj(c) {}
    QString name() const { return "Qt >= 4.2"; }
    QString shortname() const { return "qt42"; }
    bool exec()
    {
        conf->debug(QString("QT_VERSION = 0x%1").arg(QString::number(QT_VERSION, 16)));
        if(QT_VERSION >= 0x040200)
            return true;
        else
            return false;
    }
};
#line 1 "buildmode.qcm"
/*
-----BEGIN QCMOD-----
name: buildmode
section: project
arg: release,Build with debugging turned off (default).
arg: debug,Build with debugging turned on.
arg: debug-and-release,Build two versions, with and without debugging turned on (mac only).
arg: no-separate-debug-info,Do not store debug information in a separate file (default for mac).
arg: separate-debug-info,Strip debug information into a separate .debug file (default for non-mac).
arg: no-framework,Do not build as a Mac framework.
arg: framework,Build as a Mac framework (default).
-----END QCMOD-----
*/

#define QC_BUILDMODE
bool qc_buildmode_release = false;
bool qc_buildmode_debug = false;
bool qc_buildmode_framework = false;
bool qc_buildmode_separate_debug_info = false;

class qc_buildmode : public ConfObj
{
public:
    qc_buildmode(Conf *c) : ConfObj(c) {}
    QString name() const { return "buildmode"; }
    QString shortname() const { return "buildmode"; }

    // no output
    QString checkString() const { return QString(); }

    bool exec()
    {
        // first, parse out the options
        bool opt_release = false;
        bool opt_debug = false;
        bool opt_debug_and_release = false;
        bool opt_no_framework = false;
        bool opt_framework = false;
        bool opt_no_separate_debug_info = false;
        bool opt_separate_debug_info = false;

        if(conf->getenv("QC_RELEASE") == "Y")
            opt_release = true;
        if(conf->getenv("QC_DEBUG") == "Y")
            opt_debug = true;
        if(conf->getenv("QC_DEBUG_AND_RELEASE") == "Y")
            opt_debug_and_release = true;
        if(conf->getenv("QC_NO_FRAMEWORK") == "Y")
            opt_no_framework = true;
        if(conf->getenv("QC_FRAMEWORK") == "Y")
            opt_framework = true;
        if(conf->getenv("QC_NO_SEPARATE_DEBUG_INFO") == "Y")
            opt_no_separate_debug_info = true;
        if(conf->getenv("QC_SEPARATE_DEBUG_INFO") == "Y")
            opt_separate_debug_info = true;

        bool staticmode = false;
        if(conf->getenv("QC_STATIC") == "Y")
            staticmode = true;

#ifndef Q_OS_MAC
        if(opt_debug_and_release)
        {
            printf("\\nError: The --debug-and-release option is for mac only.\\n");
            exit(1);
        }

        if(opt_framework)
        {
            printf("\\nError: The --framework option is for mac only.\\n");
            exit(1);
        }
#endif

        if(opt_framework && opt_debug)
        {
            printf("\\nError: Cannot use both --framework and --debug.\\n");
            exit(1);
        }

        // sanity check exclusive options
        int x;

        // build mode
        x = 0;
        if(opt_release)
            ++x;
        if(opt_debug)
            ++x;
        if(opt_debug_and_release)
            ++x;
        if(x > 1)
        {
            printf("\\nError: Use only one of --release, --debug, or --debug-and-release.\\n");
            exit(1);
        }

        // framework
        if(opt_framework && staticmode)
        {
            printf("\\nError: Cannot use both --framework and --static.\\n");
            exit(1);
        }

        x = 0;
        if(opt_no_framework)
            ++x;
        if(opt_framework)
            ++x;
        if(x > 1)
        {
            printf("\\nError: Use only one of --framework or --no-framework.\\n");
            exit(1);
        }

        // debug info
        x = 0;
        if(opt_no_separate_debug_info)
            ++x;
        if(opt_separate_debug_info)
            ++x;
        if(x > 1)
        {
            printf("\\nError: Use only one of --separate-debug-info or --no-separate-debug-info\\n");
            exit(1);
        }

        // now process the options

        if(opt_release)
            qc_buildmode_release = true;
        else if(opt_debug)
            qc_buildmode_debug = true;
        else if(opt_debug_and_release)
        {
            qc_buildmode_release = true;
            qc_buildmode_debug = true;
        }
        else // default
            qc_buildmode_release = true;

        if(opt_framework)
            qc_buildmode_framework = true;
        else if(opt_no_framework)
        {
            // nothing to do
        }
        else // default
        {
            if(!staticmode && !opt_debug)
                qc_buildmode_framework = true;
        }

        if(opt_separate_debug_info)
            qc_buildmode_separate_debug_info = true;
        else if(opt_no_separate_debug_info)
        {
            // nothing to do
        }
        else // default
        {
#ifndef Q_OS_MAC
            qc_buildmode_separate_debug_info = true;
#endif
        }

        // make the string
        QStringList opts;
        QString other;

        if(qc_buildmode_release && qc_buildmode_debug)
        {
            opts += "debug_and_release";
            opts += "build_all";
        }
        else if(qc_buildmode_release)
            opts += "release";
        else // qc_buildmode_debug
            opts += "debug";

#ifdef Q_OS_MAC
        if(qc_buildmode_framework)
            opts += "lib_bundle";
#endif

        if(qc_buildmode_separate_debug_info)
        {
            opts += "separate_debug_info";
            other += "QMAKE_CFLAGS += -g\\n";
            other += "QMAKE_CXXFLAGS += -g\\n";
        }

        QString str = QString("CONFIG += ") + opts.join(" ") + '\\n';
        conf->addExtra(str);

        if(!other.isEmpty())
            conf->addExtra(other);

        return true;
    }
};
#line 1 "universal.qcm"
/*
-----BEGIN QCMOD-----
name: Mac universal binary support
section: project
arg: universal,Build with Mac universal binary support.
arg: mac-sdk=[path],Path to Mac universal SDK (PPC host only).
-----END QCMOD-----
*/

#define QC_UNIVERSAL
bool qc_universal_enabled = false;
QString qc_universal_sdk;

//----------------------------------------------------------------------------
// qc_universal
//----------------------------------------------------------------------------
class qc_universal : public ConfObj
{
public:
    qc_universal(Conf *c) : ConfObj(c) {}
    QString name() const { return "Mac universal binary support"; }
    QString shortname() const { return "universal"; }
    QString checkString() const { return QString(); }

    bool exec()
    {
#ifdef Q_OS_MAC
        if(qc_getenv("QC_UNIVERSAL") == "Y")
        {
            qc_universal_enabled = true;

            QString str =
            "contains(QT_CONFIG,x86):contains(QT_CONFIG,ppc) {\\n"
            "    CONFIG += x86 ppc\\n"
            "}\\n";

            QString sdk = qc_getenv("QC_MAC_SDK");
            if(!sdk.isEmpty())
            {
                str += QString("QMAKE_MAC_SDK = %1\\n").arg(sdk);
                qc_universal_sdk = sdk;
            }

            conf->addExtra(str);
        }
#endif
        return true;
    }
};
#line 1 "qca.qcm"
/*
-----BEGIN QCMOD-----
name: QCA >= 2.0
arg: with-qca-inc=[path],Path to QCA include files
arg: with-qca-lib=[path],Path to QCA library or framework files
-----END QCMOD-----
*/

// adapted from crypto.prf
static QString internal_crypto_prf(const QString &incdir, const QString &libdir, const QString &frameworkdir)
{
    QString out = QString("QCA_INCDIR = %1\\n"
                          "QCA_LIBDIR = %2\\n"
                          "QMAKE_RPATHDIR = %2\\n"
                          "QCA_FRAMEWORKDIR = %3\\n"
                          "\\n"
                          "CONFIG *= qt\\n"
                          "\\n"
                          "LINKAGE =\\n"
                          "QCA_NAME = qca-qt5\\n"
                          "\\n"
                          "!isEmpty(QCA_FRAMEWORKDIR): {\\n"
                          "    framework_dir = \$\$QCA_FRAMEWORKDIR\\n"
                          "    exists(\$\$framework_dir/\$\${QCA_NAME}.framework) {\\n"
                          "        #QMAKE_FRAMEWORKPATH *= \$\$framework_dir\\n"
                          "        LIBS *= -F\$\$framework_dir\\n"
                          "        INCLUDEPATH += \$\$framework_dir/\$\${QCA_NAME}.framework/Headers\\n"
                          "        LINKAGE = -framework \$\${QCA_NAME}\\n"
                          "    }\\n"
                          "}\\n"
                          "\\n"
                          "# else, link normally\\n"
                          "isEmpty(LINKAGE) {\\n"
                          "    !isEmpty(QCA_INCDIR):INCLUDEPATH += \$\$QCA_INCDIR/QtCrypto\\n"
                          "    !isEmpty(QCA_LIBDIR):LIBS += -L\$\$QCA_LIBDIR\\n"
                          "    LINKAGE = -l\$\${QCA_NAME}\\n"
                          "    CONFIG(debug, debug|release) {\\n"
                          "        windows:LINKAGE = -l\$\${QCA_NAME}d\\n"
                          "        mac:LINKAGE = -l\$\${QCA_NAME}_debug\\n"
                          "    }\\n"
                          "}\\n"
                          "\\n"
                          "LIBS += \$\$LINKAGE\\n")
                      .arg(incdir, libdir, frameworkdir);
    return out;
}

// set either libdir or frameworkdir, but not both
static bool qca_try(Conf *conf, const QString &incdir, const QString &libdir, const QString &frameworkdir, bool release,
                    bool debug, QString *_prf)
{
    QString proextra;
    QString prf;
    if (!incdir.isEmpty() || !libdir.isEmpty() || !frameworkdir.isEmpty()) {
        prf = internal_crypto_prf(conf->escapePath(incdir), conf->escapePath(libdir), frameworkdir);
    } else {
        prf = "CONFIG += crypto\\n";
    }
    proextra = "CONFIG += qt\\n"
               "CONFIG -= debug_and_release debug release\\n"
               "QT -= gui\\n";
    proextra += prf;

    QString str = "#include <QtCrypto>\\n"
                  "\\n"
                  "int main()\\n"
                  "{\\n"
                  "    unsigned long x = QCA_VERSION;\\n"
                  "    if(x >= 0x020000 && x < 0x030000) return 0; else return 1;\\n"
                  "}\\n";

    // test desired versions, potentially both release and debug

    if (release) {
        int ret;
        if (!conf->doCompileAndLink(str, QStringList(), QString(), proextra + "CONFIG += release\\n", &ret) || ret != 0)
            return false;
    }

    if (debug) {
        int ret;
        if (!conf->doCompileAndLink(str, QStringList(), QString(), proextra + "CONFIG += debug\\n", &ret) || ret != 0)
            return false;
    }

    *_prf = prf;
    return true;
}

static bool qca_try_lib(Conf *conf, const QString &incdir, const QString &libdir, bool release, bool debug,
                        QString *prf)
{
    return qca_try(conf, incdir, libdir, QString(), release, debug, prf)
        || qca_try(conf, incdir + "/Qca-qt5", libdir, QString(), release, debug, prf);
}

static bool qca_try_framework(Conf *conf, const QString &frameworkdir, bool release, bool debug, QString *prf)
{
    return qca_try(conf, QString(), QString(), frameworkdir, release, debug, prf);
}

static bool qca_try_ext_prf(Conf *conf, bool release, bool debug, QString *prf)
{
    return qca_try(conf, QString(), QString(), QString(), release, debug, prf);
}

//----------------------------------------------------------------------------
// qc_qca
//----------------------------------------------------------------------------
class qc_qca : public ConfObj {
public:
    qc_qca(Conf *c) : ConfObj(c) { }
    QString name() const { return "QCA >= 2.0"; }
    QString shortname() const { return "qca"; }
    bool    exec()
    {
        // get the build mode
#ifdef QC_BUILDMODE
        bool release = qc_buildmode_release;
        bool debug   = qc_buildmode_debug;
#else
        // else, default to just release mode
        bool release = true;
        bool debug   = false;
#endif

        QString qca_incdir, qca_libdir, qca_crypto_prf;
        qca_incdir = conf->getenv("QC_WITH_QCA_INC");
        qca_libdir = conf->getenv("QC_WITH_QCA_LIB");

#if defined(Q_OS_MAC)
        if (!qca_libdir.isEmpty() && qca_try_framework(conf, qca_libdir, release, debug, &qca_crypto_prf)) {
            conf->addExtra(qca_crypto_prf);
            return true;
        }
#endif

        if (!qca_incdir.isEmpty() && !qca_libdir.isEmpty()
            && qca_try_lib(conf, qca_incdir, qca_libdir, release, debug, &qca_crypto_prf)) {
            conf->addExtra(qca_crypto_prf);
            return true;
        }

        if (qca_try_ext_prf(conf, release, debug, &qca_crypto_prf)) {
            conf->addExtra(qca_crypto_prf);
            return true;
        }

        QStringList incs;
        QString     version, libs, other;

        if (conf->findPkgConfig("qca2-qt5", VersionMin, "2.0.0", &version, &incs, &libs, &other)) {
            for (int n = 0; n < incs.count(); ++n)
                conf->addIncludePath(incs[n]);
            if (!libs.isEmpty())
                conf->addLib(libs);
            return true;
        }

        QStringList prefixes;
#ifndef Q_OS_WIN
        prefixes += "/usr";
        prefixes += "/usr/local";
#endif
        QString prefix = conf->getenv("PREFIX");
        if (!prefix.isEmpty()) {
            prefixes += prefix;
        }

        for (int n = 0; n < prefixes.count(); ++n) {
            const QString &prefix = prefixes[n];
            if (qca_try_lib(conf, prefix + "/include", prefix + "/lib", release, debug, &qca_crypto_prf)) {
                conf->addExtra(qca_crypto_prf);
                return true;
            }
        }

        return false;
    }
};
#line 1 "zlib.qcm"
/*
-----BEGIN QCMOD-----
name: zlib
arg: with-zlib-inc=[path],Path to zlib include files
arg: with-zlib-lib=[path],Path to zlib library files
-----END QCMOD-----
*/

//----------------------------------------------------------------------------
// qc_zlib
//----------------------------------------------------------------------------
class qc_zlib : public ConfObj
{
public:
    qc_zlib(Conf *c) : ConfObj(c) {}
    QString name() const { return "zlib"; }
    QString shortname() const { return "zlib"; }
    bool exec()
    {
        QString inc, lib;
        QString s;

        s = conf->getenv("QC_WITH_ZLIB_INC");
        if(!s.isEmpty()) {
            if(!conf->checkHeader(s, "zlib.h"))
                return false;
            inc = s;
        }
        else {
            if(!conf->findHeader("zlib.h", QStringList(), &s))
                return false;
            inc = s;
        }

        s = conf->getenv("QC_WITH_ZLIB_LIB");
        if(!s.isEmpty()) {
            if(!conf->checkLibrary(s, "z"))
                return false;
            lib = s;
        }
        else {
            if(!conf->findLibrary("z", &s))
                return false;
            lib = s;
        }

        if(!inc.isEmpty())
            conf->addIncludePath(inc);
        if(!lib.isEmpty())
            conf->addLib(QString("-L") + s);
        conf->addLib("-lz");

        return true;
    }
};
#line 1 "extra.qcm"
/*
-----BEGIN QCMOD-----
name: extra
section: project
arg: enable-tests,Build examples and unittests.
-----END QCMOD-----
*/

class qc_extra : public ConfObj
{
public:
    qc_extra(Conf *c) : ConfObj(c) {}
    QString name() const { return "extra"; }
    QString shortname() const { return "extra"; }

    // no output
    QString checkString() const { return QString(); }

    bool exec()
    {
        QString str;
        QFile f;

        if(conf->getenv("QC_ENABLE_TESTS") == "Y")
            str += "CONFIG += iris_tests\\n";

        conf->addExtra(str);

        bool release = true;
        bool debug = false;
        bool debug_info = false;
        bool universal = false;
        QString sdk;

#ifdef QC_BUILDMODE
        release = qc_buildmode_release;
        debug = qc_buildmode_debug;
        debug_info = qc_buildmode_separate_debug_info;
#endif

#ifdef QC_UNIVERSAL
        universal = qc_universal_enabled;
        sdk = qc_universal_sdk;
#endif

        // write confapp_unix.pri
        str = QString();
                QString var = conf->getenv("BINDIR");
                if(!var.isEmpty())
            str += QString("BINDIR = %1\\n").arg(var);
        if(debug) // debug or debug-and-release
            str += QString("CONFIG += debug\\n");
        else // release
            str += QString("CONFIG += release\\n");
        if(debug_info)
        {
            str += QString("CONFIG += separate_debug_info\\n");
            str += "QMAKE_CFLAGS += -g\\n";
            str += "QMAKE_CXXFLAGS += -g\\n";
        }
        if(universal)
        {
            str +=
            "contains(QT_CONFIG,x86):contains(QT_CONFIG,ppc) {\\n"
            "    CONFIG += x86 ppc\\n"
            "}\\n";

            if(!sdk.isEmpty())
                str += QString("QMAKE_MAC_SDK = %1\\n").arg(sdk);
        }
#ifdef QC_QCA
        if(!qc_qca_procode.isEmpty())
            str += qc_qca_procode;
#endif
        f.setFileName("confapp_unix.pri");
        if(f.open(QFile::WriteOnly | QFile::Truncate))
            f.write(str.toLatin1());
        f.close();

        return true;
    }
};
#line 1 "qjdns.qcm"
/*
-----BEGIN QCMOD-----
name: jdns
arg: with-qjdns-inc=[path],Path to QJDns include files
arg: with-qjdns-lib=[path],Path to QJDns library files
-----END QCMOD-----
*/

//----------------------------------------------------------------------------
// qc_qjdns
//----------------------------------------------------------------------------
class qc_qjdns : public ConfObj
{
public:
    qc_qjdns(Conf *c) : ConfObj(c) {}
    QString name() const { return "QJDns"; }
    QString shortname() const { return "qjdns"; }
    QString resultString() const
    {
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
        return "Disabled for Qt5 and above";
#else
        return ConfObj::resultString();
#endif
    }
    bool exec()
    {
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
        return true; // hack. TODO: figure out how to force jdns
#endif
        conf->addExtra("CONFIG += need_jdns");
#if defined Q_OS_WIN || defined Q_OS_MAC
        // HACK: on Windows and Mac OS X, always use psi's bundled qjdns
        conf->addExtra("CONFIG += iris-qjdns");
        return true;
#else
        QStringList incs;
        QString version, libs, other;
        QString s;

#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
        bool found = conf->findPkgConfig("qjdns-qt5", VersionMin, "2.0.3", &version, &incs, &libs, &other);
#else
        bool found = conf->findPkgConfig("qjdns-qt4", VersionMin, "2.0.3", &version, &incs, &libs, &other);
#endif
        if(!found && !conf->findPkgConfig("qjdns", VersionMin, "2.0.0", &version, &incs, &libs, &other)) {
            s = conf->getenv("QC_WITH_QJDNS_INC");
            if ((!s.isEmpty() && conf->checkHeader(s, "qjdns.h")) ||
                (s.isEmpty() && conf->findHeader("qjdns.h", QStringList(), &s))) {
                incs.append(s);
            }

            s = conf->getenv("QC_WITH_QJDNS_LIB");
            if((!s.isEmpty() && conf->checkLibrary(s, "qjdns")) ||
               (s.isEmpty() && conf->findLibrary("qjdns", &s))) {
                libs = s.isEmpty()? "-lqjdns -ljdns" : QString("-L%1 -lqjdns -ljdns").arg(s);
            }
        }

        if (!incs.isEmpty() && !libs.isEmpty()) {
            foreach(const QString &inc, incs) {
                conf->addIncludePath(inc);
            }
            conf->addLib(libs);
            conf->addExtra("CONFIG += ext-qjdns");
        }

        return true;
#endif
    }
};
#line 1 "b2.qcm"
/*
-----BEGIN QCMOD-----
name: libb2
arg: with-b2-inc=[path],Path to libb2 include files
arg: with-b2-lib=[path],Path to libb2 library or framework files
-----END QCMOD-----
*/

//----------------------------------------------------------------------------
// qc_b2
//----------------------------------------------------------------------------
class qc_b2 : public ConfObj
{
    bool use_system = false;
public:
    qc_b2(Conf *c) : ConfObj(c) {}
    QString name() const { return "LibB2"; }
    QString shortname() const { return "libb2"; }
    QString resultString() const { return use_system? "system":"bundled"; }
    bool exec()
    {
        QString b2_incdir, b2_libdir;
        b2_incdir = conf->getenv("QC_WITH_B2_INC");
        b2_libdir = conf->getenv("QC_WITH_B2_LIB");

        if (b2_incdir.isEmpty() && b2_libdir.isEmpty()) {
            if (!checkCustomDirs(b2_incdir, b2_libdir)) {
                printf("b2 search paths provided but library is not found there. use bundled");
                return true;
            }
            use_system = true;
        } else {
            QStringList incs;
            QString version, libs, other;
            if(conf->findPkgConfig("libb2", VersionAny, QString::null, &version, &incs, &libs, &other))
            {
                    for(int n = 0; n < incs.count(); ++n)
                            conf->addIncludePath(incs[n]);
                    if(!libs.isEmpty())
                            conf->addLib(libs);
                    use_system = true;
            }
        }

        if (use_system) {
            conf->addExtra("CONFIG += bundled_blake2");
        }

        return true;
    }

    bool checkCustomDirs(QString &b2_incdir, QString &b2_libdir)
    {
        if ((b2_incdir.isEmpty() && !conf->findHeader("blake2.h", QStringList(), &b2_incdir)) ||
            (!b2_incdir.isEmpty() && !conf->checkHeader(b2_incdir, "blake2.h"))) {
            printf("Headers not found!\\n");
            return false;
        }

        if((!b2_libdir.isEmpty() && conf->checkLibrary(b2_libdir, "b2")) ||
           (b2_libdir.isEmpty() && conf->findLibrary("b2", &b2_libdir))) {
            conf->addLib(b2_libdir.isEmpty()? "-lb2" : QString("-L%1 -lb2").arg(b2_libdir));
            conf->addIncludePath(b2_incdir);
            return true;
        }

        printf("Libraries not found!\\n");
        return false;
    }
};

EOT
cat >"$1/modules_new.cpp" <<EOT
    o = new qc_qt42(conf);
    o->required = true;
    o->disabled = false;
    o = new qc_buildmode(conf);
    o->required = true;
    o->disabled = false;
    o = new qc_universal(conf);
    o->required = true;
    o->disabled = false;
    o = new qc_qca(conf);
    o->required = true;
    o->disabled = false;
    o = new qc_zlib(conf);
    o->required = true;
    o->disabled = false;
    o = new qc_extra(conf);
    o->required = true;
    o->disabled = false;
    o = new qc_qjdns(conf);
    o->required = true;
    o->disabled = false;
    o = new qc_b2(conf);
    o->required = true;
    o->disabled = false;

EOT
cat >"$1/conf4.h" <<EOT
/*
Copyright (C) 2004-2008  Justin Karneges

This file is free software; unlimited permission is given to copy and/or
distribute it, with or without modifications, as long as this notice is
preserved.
*/

#ifndef QC_CONF4_H
#define QC_CONF4_H

#include <QtCore>

class Conf;

enum VersionMode { VersionMin, VersionExact, VersionMax, VersionAny };

// ConfObj
//
// Subclass ConfObj to create a new configuration module.
class ConfObj {
public:
    Conf *conf;
    bool  required;
    bool  disabled;
    bool  success;

    ConfObj(Conf *c);
    virtual ~ConfObj();

    // long or descriptive name of what is being checked/performed
    // example: "KDE >= 3.3"
    virtual QString name() const = 0;

    // short name
    // example: "kde"
    virtual QString shortname() const = 0;

    // string to display during check
    // default: "Checking for [name] ..."
    virtual QString checkString() const;

    // string to display after check
    // default: "yes" or "no", based on result of exec()
    virtual QString resultString() const;

    // this is where the checking code goes
    virtual bool exec() = 0;
};

// Conf
//
// Interact with this class from your ConfObj to perform detection
// operations and to output configuration parameters.
class Conf {
public:
    bool    debug_enabled;
    QString qmake_path;
    QString qmakespec;
    QString maketool;

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

    QList<ConfObj *>       list;
    QMap<QString, QString> vars;

    Conf();
    ~Conf();

    QString        getenv(const QString &var);
    QString        qvar(const QString &s);
    QString        normalizePath(const QString &s) const;
    QString        escapeQmakeVar(const QString &s) const;
    inline QString escapePath(const QString &s) /* prepare fs path for qmake file */
    {
        return escapeQmakeVar(normalizePath(s));
    }
    QString escapedIncludes() const;
    QString escapedLibs() const;

    bool exec();

    void debug(const QString &s);

    QString expandIncludes(const QString &inc);
    QString expandLibs(const QString &lib);

    int doCommand(const QString &s, QByteArray *out = 0);
    int doCommand(const QString &prog, const QStringList &args, QByteArray *out = 0);

    bool    doCompileAndLink(const QString &filedata, const QStringList &incs, const QString &libs,
                             const QString &proextra, int *retcode = 0);
    bool    checkHeader(const QString &path, const QString &h);
    bool    findHeader(const QString &h, const QStringList &ext, QString *inc);
    bool    checkLibrary(const QString &path, const QString &name);
    bool    findLibrary(const QString &name, QString *lib);
    QString findProgram(const QString &prog);
    bool findSimpleLibrary(const QString &incvar, const QString &libvar, const QString &incname, const QString &libname,
                           QString *incpath, QString *libs);
    bool findFooConfig(const QString &path, QString *version, QStringList *incs, QString *libs, QString *otherflags);
    bool findPkgConfig(const QString &name, VersionMode mode, const QString &req_version, QString *version,
                       QStringList *incs, QString *libs, QString *otherflags);

    void addDefine(const QString &str);
    void addLib(const QString &str);
    void addIncludePath(const QString &str);
    void addExtra(const QString &str);

private:
    bool first_debug;

    friend class ConfObj;
    void added(ConfObj *o);
};

#endif

EOT
cat >"$1/conf4.cpp" <<EOT
/*
Copyright (C) 2004-2008  Justin Karneges

This file is free software; unlimited permission is given to copy and/or
distribute it, with or without modifications, as long as this notice is
preserved.
*/

#include "conf4.h"

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef PATH_MAX
#ifdef Q_OS_WIN
#define PATH_MAX 260
#endif
#endif

class MocTestObject : public QObject {

    Q_OBJECT
public:
    MocTestObject() {}
};

QString qc_getenv(const QString &var)
{
    char *p = ::getenv(var.toLatin1().data());
    if (!p)
        return QString();
    return QString(p);
}

QStringList qc_pathlist()
{
    QStringList list;
    QString     path = qc_getenv("PATH");
    if (!path.isEmpty()) {
#ifdef Q_OS_WIN
        list = path.split(';', QString::SkipEmptyParts);
#else
        list = path.split(':', QString::SkipEmptyParts);
#endif
    }
#ifdef Q_OS_WIN
    list.prepend(".");
#endif
    return list;
}

QString qc_findprogram(const QString &prog)
{
    QString     out;
    QStringList list = qc_pathlist();
    for (int n = 0; n < list.count(); ++n) {
        QFileInfo fi(list[n] + '/' + prog);
        if (fi.exists() && fi.isExecutable()) {
            out = fi.filePath();
            break;
        }

#ifdef Q_OS_WIN
        // on windows, be sure to look for .exe
        if (prog.right(4).toLower() != ".exe") {
            fi = QFileInfo(list[n] + '/' + prog + ".exe");
            if (fi.exists() && fi.isExecutable()) {
                out = fi.filePath();
                break;
            }
        }
#endif
    }
    return out;
}

QString qc_findself(const QString &argv0)
{
#ifdef Q_OS_WIN
    if (argv0.contains('\\\\'))
#else
    if (argv0.contains('/'))
#endif
        return argv0;
    else
        return qc_findprogram(argv0);
}

int qc_run_program_or_command(const QString &prog, const QStringList &args, const QString &command, QByteArray *out,
                              bool showOutput)
{
    if (out)
        out->clear();

    QProcess process;
    process.setReadChannel(QProcess::StandardOutput);

    if (!prog.isEmpty())
        process.start(prog, args);
    else if (!command.isEmpty())
        process.start(command);
    else
        return -1;

    if (!process.waitForStarted(-1))
        return -1;

    QByteArray buf;

    while (process.waitForReadyRead(-1)) {
        buf = process.readAllStandardOutput();
        if (out)
            out->append(buf);
        if (showOutput)
            fprintf(stdout, "%s", buf.data());

        buf = process.readAllStandardError();
        if (showOutput)
            fprintf(stderr, "%s", buf.data());
    }

    buf = process.readAllStandardError();
    if (showOutput)
        fprintf(stderr, "%s", buf.data());

    // calling waitForReadyRead will cause the process to eventually be
    //   marked as finished, so we should not need to separately call
    //   waitForFinished. however, we will do it anyway just to be safe.
    //   we won't check the return value since false could still mean
    //   success (if the process had already been marked as finished).
    process.waitForFinished(-1);

    if (process.exitStatus() != QProcess::NormalExit)
        return -1;

    return process.exitCode();
}

int qc_runcommand(const QString &command, QByteArray *out, bool showOutput)
{
    return qc_run_program_or_command(QString(), QStringList(), command, out, showOutput);
}

int qc_runprogram(const QString &prog, const QStringList &args, QByteArray *out, bool showOutput)
{
    return qc_run_program_or_command(prog, args, QString(), out, showOutput);
}

bool qc_removedir(const QString &dirPath)
{
    QDir dir(dirPath);
    if (!dir.exists())
        return false;
    QStringList list = dir.entryList();
    foreach (QString s, list) {
        if (s == "." || s == "..")
            continue;
        QFileInfo fi(dir.filePath(s));
        if (fi.isDir()) {
            if (!qc_removedir(fi.filePath()))
                return false;
        } else {
            if (!dir.remove(s))
                return false;
        }
    }
    QString dirName = dir.dirName();
    if (!dir.cdUp())
        return false;
    if (!dir.rmdir(dirName))
        return false;
    return true;
}

// simple command line arguemnts splitter able to understand quoted args.
// the splitter removes quotes and unescapes symbols as well.
QStringList qc_splitflags(const QString &flags)
{
    QStringList ret;
    bool        searchStart = true;
    bool        inQuotes    = false;
    bool        escaped     = false;
    QChar       quote, backslash = QLatin1Char('\\\\');
    QString     buf;
#ifdef PATH_MAX
    buf.reserve(PATH_MAX);
#endif
    for (int i = 0; i < flags.length(); i++) {
        if (searchStart && flags[i].isSpace()) {
            continue;
        }
        if (searchStart) {
            searchStart = false;
            buf.clear();
        }
        if (escaped) {
            buf += flags[i];
            escaped = false;
            continue;
        }
        // buf += flags[i];
        if (inQuotes) {
            if (quote == QLatin1Char('\\'')) {
                if (flags[i] == quote) {
                    inQuotes = false;
                    continue;
                }
            } else { // we are in double quoetes
                if (flags[i] == backslash && i < flags.length() - 1
                    && (flags[i + 1] == QLatin1Char('"') || flags[i + 1] == backslash)) {
                    // if next symbol is one of in parentheses ("\\)
                    escaped = true;
                    continue;
                }
            }
        } else {
            if (flags[i].isSpace()) {
                ret.append(buf);
                searchStart = true;
                buf.clear();
                continue;
#ifndef Q_OS_WIN /* on windows backslash is just a path separator */
            } else if (flags[i] == backslash) {
                escaped = true;
                continue; // just add next symbol
#endif
            } else if (flags[i] == QLatin1Char('\\'') || flags[i] == QLatin1Char('"')) {
                inQuotes = true;
                quote    = flags[i];
                continue;
            }
        }
        buf += flags[i];
    }
    if (buf.size()) {
        ret.append(buf);
    }
    return ret;
}

void qc_splitcflags(const QString &cflags, QStringList *incs, QStringList *otherflags)
{
    incs->clear();
    otherflags->clear();

    QStringList cflagsList = qc_splitflags(cflags);
    for (int n = 0; n < cflagsList.count(); ++n) {
        QString str = cflagsList[n];
        if (str.startsWith("-I")) {
            // we want everything except the leading "-I"
            incs->append(str.remove(0, 2));
        } else {
            // we want whatever is left
            otherflags->append(str);
        }
    }
}

QString qc_escapeArg(const QString &str)
{
    QString out;
    for (int n = 0; n < (int)str.length(); ++n) {
        if (str[n] == '-')
            out += '_';
        else
            out += str[n];
    }
    return out;
}

QString qc_trim_char(const QString &s, const QChar &ch)
{
    if (s.startsWith(ch) && s.endsWith(ch)) {
        return s.mid(1, s.size() - 2);
    }
    return s;
}

// removes surrounding quotes, removes trailing slashes, converts to native separators.
// accepts unescaped but possible quoted path
QString qc_normalize_path(const QString &str)
{
    QString path = str.trimmed();
    path         = qc_trim_char(path, QLatin1Char('"'));
    path         = qc_trim_char(path, QLatin1Char('\\''));

    // It's OK to use unix style'/' paths on windows Qt handles this without any problems.
    // Using Windows-style '\\\\' can leads strange compilation error with MSYS which uses
    // unix style.
    QLatin1Char nativeSep('/');
#ifdef Q_OS_WIN
    path.replace(QLatin1Char('\\\\'), QLatin1Char('/'));
#endif
    // trim trailing slashes
    while (path.length() && path[path.length() - 1] == nativeSep) {
        path.resize(path.length() - 1);
    }
    return path;
}

// escape filesystem path to be added to qmake pro/pri file.
QString qc_escape_string_var(const QString &str)
{
    QString path = str;
    path.replace(QLatin1Char('\\\\'), QLatin1String("\\\\\\\\")).replace(QLatin1Char('"'), QLatin1String("\\\\\\""));
    if (path.indexOf(QLatin1Char(' ')) != -1) { // has spaces
        return QLatin1Char('"') + path + QLatin1Char('"');
    }
    return path;
}

// escapes each path in incs and join into single string suiable for INCLUDEPATH var
QString qc_prepare_includepath(const QStringList &incs)
{
    if (incs.empty()) {
        return QString();
    }
    QStringList ret;
    foreach (const QString &path, incs) {
        ret.append(qc_escape_string_var(path));
    }
    return ret.join(QLatin1String(" "));
}

// escapes each path in libs and to make it suiable for LIBS var
// notice, entries of libs are every single arg for linker.
QString qc_prepare_libs(const QStringList &libs)
{
    if (libs.isEmpty()) {
        return QString();
    }
    QSet<QString> pathSet;
    QStringList   paths;
    QStringList   ordered;
    foreach (const QString &arg, libs) {
        if (arg.startsWith(QLatin1String("-L"))) {
            QString path = qc_escape_string_var(arg.mid(2));
            if (!pathSet.contains(path)) {
                pathSet.insert(path);
                paths.append(path);
            }
        } else if (arg.startsWith(QLatin1String("-l"))) {
            ordered.append(arg);
        } else {
            ordered.append(qc_escape_string_var(arg));
        }
    }
    QString ret;
    if (paths.size()) {
        ret += (QLatin1String(" -L") + paths.join(QLatin1String(" -L")) + QLatin1Char(' '));
    }
    return ret + ordered.join(QLatin1String(" "));
}

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

ConfObj::~ConfObj() {}

QString ConfObj::checkString() const { return QString("Checking for %1 ...").arg(name()); }

QString ConfObj::resultString() const
{
    if (success)
        return "yes";
    else
        return "no";
}

//----------------------------------------------------------------------------
// qc_internal_pkgconfig
//----------------------------------------------------------------------------
class qc_internal_pkgconfig : public ConfObj {
public:
    QString     pkgname, desc;
    VersionMode mode;
    QString     req_ver;

    qc_internal_pkgconfig(Conf *c, const QString &_name, const QString &_desc, VersionMode _mode,
                          const QString &_req_ver) :
        ConfObj(c),
        pkgname(_name), desc(_desc), mode(_mode), req_ver(_req_ver)
    {
    }

    QString name() const { return desc; }
    QString shortname() const { return pkgname; }

    bool exec()
    {
        QStringList incs;
        QString     version, libs, other;
        if (!conf->findPkgConfig(pkgname, mode, req_ver, &version, &incs, &libs, &other))
            return false;

        for (int n = 0; n < incs.count(); ++n)
            conf->addIncludePath(incs[n]);
        if (!libs.isEmpty())
            conf->addLib(libs);
        // if(!other.isEmpty())
        //    conf->addExtra(QString("QMAKE_CFLAGS += %1\\n").arg(other));

        if (!required)
            conf->addDefine("HAVE_PKG_" + qc_escapeArg(pkgname).toUpper());

        return true;
    }
};

//----------------------------------------------------------------------------
// Conf
//----------------------------------------------------------------------------
Conf::Conf()
{
    // TODO: no more vars?
    // 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", CC);

    debug_enabled = false;
    first_debug   = true;
}

Conf::~Conf() { qDeleteAll(list); }

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

QString Conf::getenv(const QString &var) { return qc_getenv(var); }

void Conf::debug(const QString &s)
{
    if (debug_enabled) {
        if (first_debug)
            printf("\\n");
        first_debug = false;
        printf(" * %s\\n", qPrintable(s));
    }
}

bool Conf::exec()
{
    for (int n = 0; n < list.count(); ++n) {
        ConfObj *o = list[n];

        // if this was a disabled-by-default option, check if it was enabled
        if (o->disabled) {
            QString v = QString("QC_ENABLE_") + qc_escapeArg(o->shortname());
            if (getenv(v) != "Y")
                continue;
        }
        // and the opposite?
        else {
            QString v = QString("QC_DISABLE_") + qc_escapeArg(o->shortname());
            if (getenv(v) == "Y")
                continue;
        }

        bool    output = true;
        QString check  = o->checkString();
        if (check.isEmpty())
            output = false;

        if (output) {
            printf("%s", check.toLatin1().data());
            fflush(stdout);
        }

        first_debug = true;
        bool ok     = o->exec();
        o->success  = ok;

        if (output) {
            QString result = o->resultString();
            if (!first_debug)
                printf(" -> %s\\n", result.toLatin1().data());
            else
                printf(" %s\\n", result.toLatin1().data());
        }

        if (!ok && o->required) {
            printf("\\nError: need %s!\\n", o->name().toLatin1().data());
            return false;
        }
    }
    return true;
}

QString Conf::qvar(const QString &s) { return vars.value(s); }

QString Conf::normalizePath(const QString &s) const { return qc_normalize_path(s); }

QString Conf::escapeQmakeVar(const QString &s) const { return qc_escape_string_var(s); }

QString Conf::escapedIncludes() const { return qc_prepare_includepath(INCLUDEPATH); }

QString Conf::escapedLibs() const { return qc_prepare_libs(LIBS); }

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

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

int Conf::doCommand(const QString &s, QByteArray *out)
{
    debug(QString("[%1]").arg(s));
    int r = qc_runcommand(s, out, debug_enabled);
    debug(QString("returned: %1").arg(r));
    return r;
}

int Conf::doCommand(const QString &prog, const QStringList &args, QByteArray *out)
{
    QString fullcmd = prog;
    QString argstr  = args.join(QLatin1String(" "));
    if (!argstr.isEmpty())
        fullcmd += QString(" ") + argstr;
    debug(QString("[%1]").arg(fullcmd));
    int r = qc_runprogram(prog, args, out, debug_enabled);
    debug(QString("returned: %1").arg(r));
    return r;
}

bool Conf::doCompileAndLink(const QString &filedata, const QStringList &incs, const QString &libs,
                            const QString &proextra, int *retcode)
{
#ifdef Q_OS_WIN
    QDir tmp("qconftemp");
#else
    QDir tmp(".qconftemp");
#endif
    QStringList normalizedLibs;
    foreach (const QString &l, qc_splitflags(libs)) {
        normalizedLibs.append(qc_normalize_path(l));
    }

    if (!tmp.mkdir("atest")) {
        debug(QString("unable to create atest dir: %1").arg(tmp.absoluteFilePath("atest")));
        return false;
    }
    QDir dir(tmp.filePath("atest"));
    if (!dir.exists()) {
        debug("atest dir does not exist");
        return false;
    }

    QString fname = dir.filePath("atest.cpp");
    QString out   = "atest";
    QFile   f(fname);
    if (!f.open(QFile::WriteOnly | QFile::Truncate)) {
        debug("unable to open atest.cpp for writing");
        return false;
    }
    if (f.write(filedata.toLatin1()) == -1) {
        debug("error writing to atest.cpp");
        return false;
    }
    f.close();

    debug(QString("Wrote atest.cpp:\\n%1").arg(filedata));

    QString pro = QString("CONFIG  += console\\n"
                          "CONFIG  -= qt app_bundle\\n"
                          "DESTDIR  = \$\$PWD\\n"
                          "SOURCES += atest.cpp\\n");
    QString inc = qc_prepare_includepath(incs);
    if (!inc.isEmpty())
        pro += "INCLUDEPATH += " + inc + '\\n';
    QString escaped_libs = qc_prepare_libs(normalizedLibs);
    if (!escaped_libs.isEmpty())
        pro += "LIBS += " + escaped_libs + '\\n';
    pro += proextra;

    fname = dir.filePath("atest.pro");
    f.setFileName(fname);
    if (!f.open(QFile::WriteOnly | QFile::Truncate)) {
        debug("unable to open atest.pro for writing");
        return false;
    }
    if (f.write(pro.toLatin1()) == -1) {
        debug("error writing to atest.pro");
        return false;
    }
    f.close();

    debug(QString("Wrote atest.pro:\\n%1").arg(pro));

    QString oldpath = QDir::currentPath();
    QDir::setCurrent(dir.path());

    bool ok = false;
    int  r  = doCommand(qmake_path, QStringList() << "atest.pro");
    if (r == 0) {
        r = doCommand(maketool, QStringList());
        if (r == 0) {
            ok = true;
            if (retcode) {
                QString runatest = out;
#ifdef Q_OS_UNIX
                runatest.prepend("./");
#endif
                *retcode = doCommand(runatest, QStringList());
            }
        }
        r = doCommand(maketool, QStringList() << "distclean");
        if (r != 0)
            debug("error during atest distclean");
    }

    QDir::setCurrent(oldpath);

    // cleanup
    // dir.remove("atest.pro");
    // dir.remove("atest.cpp");
    // tmp.rmdir("atest");

    // remove whole dir since distclean doesn't always work
    qc_removedir(tmp.filePath("atest"));

    if (!ok)
        return false;
    return true;
}

bool Conf::checkHeader(const QString &path, const QString &h) { return QDir(path).exists(h); }

bool Conf::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;

    QString prefix = qc_getenv("PREFIX");
    if (!prefix.isEmpty()) {
        prefix += "/include";
        prefix = qc_normalize_path(prefix);
        if (!dirs.contains(prefix))
            dirs << prefix;
    }

    for (QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it) {
        if (checkHeader(*it, h)) {
            *inc = *it;
            return true;
        }
    }
    return false;
}

bool Conf::checkLibrary(const QString &path, const QString &name)
{
    QString str =
        //"#include <stdio.h>\\n"
        "int main()\\n"
        "{\\n"
        //"    printf(\\"library checker running\\\\\\\\n\\");\\n"
        "    return 0;\\n"
        "}\\n";

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

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

    QString prefix = qc_getenv("PREFIX");
    if (!prefix.isEmpty()) {
        prefix += "/lib";
        prefix = qc_normalize_path(prefix);
        if (checkLibrary(prefix, name)) {
            *lib = prefix;
            return true;
        }
    }

    return false;
}

QString Conf::findProgram(const QString &prog) { return qc_findprogram(prog); }

bool Conf::findSimpleLibrary(const QString &incvar, const QString &libvar, const QString &incname,
                             const QString &libname, QString *incpath, QString *libs)
{
    QString inc, lib;
    QString s;

    s = getenv(incvar).trimmed();
    if (!s.isEmpty()) {
        if (!checkHeader(s, incname)) {
            if (debug_enabled)
                printf("%s is not found in \\"%s\\"\\n", qPrintable(incname), qPrintable(s));
            return false;
        }
        inc = s;
    } else {
        if (!findHeader(incname, QStringList(), &s)) {
            if (debug_enabled)
                printf("%s is not found anywhere\\n", qPrintable(incname));
            return false;
        }
        inc = s;
    }

    s = getenv(libvar).trimmed();
    if (!s.isEmpty()) {
        if (!checkLibrary(s, libname)) {
            if (debug_enabled)
                printf("%s is not found in \\"%s\\"\\n", qPrintable(libname), qPrintable(s));
            return false;
        }
        lib = s;
    } else {
        if (!findLibrary(libname, &s)) {
            if (debug_enabled)
                printf("%s is not found anywhere\\n", qPrintable(libname));
            return false;
        }
        lib = s;
    }

    QString lib_out;
    if (!lib.isEmpty())
        lib_out += QString("-L") + s + " ";
    lib_out += QString("-l") + libname;

    *incpath = inc;
    *libs    = lib_out;
    return true;
}

bool Conf::findFooConfig(const QString &path, QString *version, QStringList *incs, QString *libs, QString *otherflags)
{
    QStringList args;
    QByteArray  out;
    int         ret;

    args += "--version";
    ret = doCommand(path, args, &out);
    if (ret != 0)
        return false;

    QString version_out = QString::fromLatin1(out).trimmed();

    args.clear();
    args += "--libs";
    ret = doCommand(path, args, &out);
    if (ret != 0)
        return false;

    QString libs_out = QString::fromLatin1(out).trimmed();

    args.clear();
    args += "--cflags";
    ret = doCommand(path, args, &out);
    if (ret != 0)
        return false;

    QString cflags = QString::fromLatin1(out).trimmed();

    QStringList incs_out, otherflags_out;
    qc_splitcflags(cflags, &incs_out, &otherflags_out);

    *version    = version_out;
    *incs       = incs_out;
    *libs       = libs_out;
    *otherflags = otherflags_out.join(QLatin1String(" "));
    return true;
}

bool Conf::findPkgConfig(const QString &name, VersionMode mode, const QString &req_version, QString *version,
                         QStringList *incs, QString *libs, QString *otherflags)
{
    QStringList args;
    QByteArray  out;
    int         ret;

    args += name;
    args += "--exists";
    ret = doCommand("pkg-config", args, &out);
    if (ret != 0)
        return false;

    if (mode != VersionAny) {
        args.clear();
        args += name;
        if (mode == VersionMin)
            args += QString("--atleast-version=%1").arg(req_version);
        else if (mode == VersionMax)
            args += QString("--max-version=%1").arg(req_version);
        else
            args += QString("--exact-version=%1").arg(req_version);
        ret = doCommand("pkg-config", args, &out);
        if (ret != 0)
            return false;
    }

    args.clear();
    args += name;
    args += "--modversion";
    ret = doCommand("pkg-config", args, &out);
    if (ret != 0)
        return false;

    QString version_out = QString::fromLatin1(out).trimmed();

    args.clear();
    args += name;
    args += "--libs";
    ret = doCommand("pkg-config", args, &out);
    if (ret != 0)
        return false;

    QString libs_out = QString::fromLatin1(out).trimmed();

    args.clear();
    args += name;
    args += "--cflags";
    ret = doCommand("pkg-config", args, &out);
    if (ret != 0)
        return false;

    QString cflags = QString::fromLatin1(out).trimmed();

    QStringList incs_out, otherflags_out;
    qc_splitcflags(cflags, &incs_out, &otherflags_out);

    *version    = version_out;
    *incs       = incs_out;
    *libs       = libs_out;
    *otherflags = otherflags_out.join(QLatin1String(" "));
    return true;
}

void Conf::addDefine(const QString &str)
{
    if (DEFINES.isEmpty())
        DEFINES = str;
    else
        DEFINES += QString(" ") + str;
    debug(QString("DEFINES += %1").arg(str));
}

void Conf::addLib(const QString &str)
{
    QStringList libs = qc_splitflags(str);
    foreach (const QString &lib, libs) {
        if (lib.startsWith("-l")) {
            LIBS.append(lib);
        } else {
            LIBS.append(qc_normalize_path(lib)); // we don't care about -L prefix since normalier does not touch it.
        }
    }
    debug(QString("LIBS += %1").arg(str));
}

void Conf::addIncludePath(const QString &str)
{
    INCLUDEPATH.append(qc_normalize_path(str));
    debug(QString("INCLUDEPATH += %1").arg(str));
}

void Conf::addExtra(const QString &str)
{
    extra += str + '\\n';
    debug(QString("extra += %1").arg(str));
}

//----------------------------------------------------------------------------
// main
//----------------------------------------------------------------------------
#include "conf4.moc"

#ifdef HAVE_MODULES
#include "modules.cpp"
#endif

int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);
    Conf *           conf = new Conf;
    ConfObj *        o    = 0;
    Q_UNUSED(o);
#ifdef HAVE_MODULES
#include "modules_new.cpp"
#endif

    conf->debug_enabled = (qc_getenv("QC_VERBOSE") == "Y") ? true : false;
    if (conf->debug_enabled)
        printf(" -> ok\\n");
    else
        printf("ok\\n");

    QString confCommand = qc_getenv("QC_COMMAND");
    QString proName     = qc_getenv("QC_PROFILE");
    conf->qmake_path    = qc_getenv("QC_QMAKE");
    conf->qmakespec     = qc_getenv("QC_QMAKESPEC");
    conf->maketool      = qc_getenv("QC_MAKETOOL");

    if (conf->debug_enabled)
        printf("conf command: [%s]\\n", qPrintable(confCommand));

    QString confPath = qc_findself(confCommand);
    if (confPath.isEmpty()) {
        printf("Error: cannot find myself; rerun with an absolute path\\n");
        return 1;
    }

    QString srcdir   = QFileInfo(confPath).absolutePath();
    QString builddir = QDir::current().absolutePath();
    QString proPath  = QDir(srcdir).filePath(proName);

    if (conf->debug_enabled) {
        printf("conf path:    [%s]\\n", qPrintable(confPath));
        printf("srcdir:       [%s]\\n", qPrintable(srcdir));
        printf("builddir:     [%s]\\n", qPrintable(builddir));
        printf("profile:      [%s]\\n", qPrintable(proPath));
        printf("qmake path:   [%s]\\n", qPrintable(conf->qmake_path));
        printf("qmakespec:    [%s]\\n", qPrintable(conf->qmakespec));
        printf("make tool:    [%s]\\n", qPrintable(conf->maketool));
        printf("\\n");
    }

    bool success = false;
    if (conf->exec()) {
        QFile f("conf.pri");
        if (!f.open(QFile::WriteOnly | QFile::Truncate)) {
            printf("Error writing %s\\n", qPrintable(f.fileName()));
            return 1;
        }

        QString str;
        str += "# qconf\\n\\n";
        str += "greaterThan(QT_MAJOR_VERSION, 4):CONFIG += c++11\\n";

        QString var;
        var = qc_normalize_path(qc_getenv("PREFIX"));
        if (!var.isEmpty())
            str += QString("PREFIX = %1\\n").arg(var);
        var = qc_normalize_path(qc_getenv("BINDIR"));
        if (!var.isEmpty())
            str += QString("BINDIR = %1\\n").arg(var);
        var = qc_normalize_path(qc_getenv("INCDIR"));
        if (!var.isEmpty())
            str += QString("INCDIR = %1\\n").arg(var);
        var = qc_normalize_path(qc_getenv("LIBDIR"));
        if (!var.isEmpty())
            str += QString("LIBDIR = %1\\n").arg(var);
        var = qc_normalize_path(qc_getenv("DATADIR"));
        if (!var.isEmpty())
            str += QString("DATADIR = %1\\n").arg(var);
        str += '\\n';

        if (qc_getenv("QC_STATIC") == "Y")
            str += "CONFIG += staticlib\\n";

        // TODO: don't need this?
        // str += "QT_PATH_PLUGINS = " + QString(qInstallPathPlugins()) + '\\n';

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

        var = qc_getenv("QC_EXTRACONF");
        if (!var.isEmpty())
            str += ("\\n# Extra conf from command line\\n" + var + "\\n");

        QByteArray cs = str.toLatin1();
        f.write(cs);
        f.close();
        success = true;
    }
    QString qmake_path = conf->qmake_path;
    QString qmakespec  = conf->qmakespec;
    delete conf;

    if (!success)
        return 1;

    // run qmake on the project file
    QStringList args;
    if (!qmakespec.isEmpty()) {
        args += "-spec";
        args += qmakespec;
    }
    args += proPath;
    int ret = qc_runprogram(qmake_path, args, 0, true);
    if (ret != 0)
        return 1;

    return 0;
}

EOT
cat >"$1/conf4.pro" <<EOT
CONFIG  += console
CONFIG  -= app_bundle
QT      -= gui
TARGET   = conf
DESTDIR  = \$\$PWD

HEADERS += conf4.h
SOURCES += conf4.cpp


DEFINES += HAVE_MODULES

greaterThan(QT_MAJOR_VERSION, 4):CONFIG += c++11

EOT
}

export EX_QTDIR
export QC_STATIC
export QC_EXTRACONF
export QC_RELEASE
export QC_DEBUG
export QC_DEBUG_AND_RELEASE
export QC_NO_SEPARATE_DEBUG_INFO
export QC_SEPARATE_DEBUG_INFO
export QC_NO_FRAMEWORK
export QC_FRAMEWORK
export QC_UNIVERSAL
export QC_MAC_SDK
export QC_ENABLE_TESTS
export QC_WITH_QCA_INC
export QC_WITH_QCA_LIB
export QC_WITH_ZLIB_INC
export QC_WITH_ZLIB_LIB
export QC_WITH_QJDNS_INC
export QC_WITH_QJDNS_LIB
export QC_WITH_B2_INC
export QC_WITH_B2_LIB
export QC_VERBOSE
export QC_QTSELECT
rm -rf ".qconftemp"
(
    mkdir ".qconftemp"
    gen_files ".qconftemp"
    cd ".qconftemp"
    if [ ! -z "$qm_spec" ]; then
        "$qm" -spec $qm_spec conf4.pro >/dev/null
    else
        "$qm" conf4.pro >/dev/null
    fi
    $MAKE clean >/dev/null 2>&1
    $MAKE >../conf.log 2>&1
)

if [ "$?" != "0" ]; then
    rm -rf ".qconftemp"
    if [ "$QC_VERBOSE" = "Y" ]; then
        echo " -> fail"
    else
        echo "fail"
    fi
    printf "\n"
    printf "Reason: There was an error compiling 'conf'.  See conf.log for details.\n"
    printf "\n"
    show_qt_info
    if [ "$QC_VERBOSE" = "Y" ]; then
        echo "conf.log:"
        cat conf.log
    fi
    exit 1;
fi

QC_COMMAND=$0
export QC_COMMAND
QC_PROFILE=iris.pro
export QC_PROFILE
QC_QMAKE="$qm"
export QC_QMAKE
QC_QMAKESPEC=$qm_spec
export QC_QMAKESPEC
QC_MAKETOOL=$MAKE
export QC_MAKETOOL
".qconftemp/conf"
ret="$?"
if [ "$ret" = "1" ]; then
    rm -rf ".qconftemp"
    echo
    exit 1;
else
    if [ "$ret" != "0" ]; then
        rm -rf ".qconftemp"
        if [ "$QC_VERBOSE" = "Y" ]; then
            echo " -> fail"
        else
            echo "fail"
        fi
        echo
        echo "Reason: Unexpected error launching 'conf'"
        echo
        exit 1;
    fi
fi
rm -rf ".qconftemp"

echo
echo "Good, your configure finished.  Now run $MAKE."
echo
