/* REXX */
/*
 */ G.!Id = '$Id: configure.cmd 8 2005-11-16 19:36:46Z dmik $' /*
 *
 *  :mode=netrexx:tabSize=4:indentSize=4:noTabs=true:
 *  :folding=explicit:collapseFolds=1:
 *
 *  ----------------------------------------------------------------------------
 *
 *	Qt Toolkit Version 3 for OS/2 Configuration Script
 *
 *  Author: Dmitry A. Kuminov
 */

signal on syntax
signal on halt
signal on novalue
trace off
numeric digits 12
'@echo off'

/* globals
 ******************************************************************************/

G.!Title        = 'Qt Toolkit Version 3 for OS/2 Configuration Script',
                  '${revision} [${revision.date} ${revision.time}]'

G.!TAB          = '09'x
G.!EOL          = '0D0A'x

/* path to GCC */
Opt.!GCCPath            = ''
Opt.!GCCPath.0          = 0
Opt.!GCCPath.!choice    = ''

/* path to ILINK */
Opt.!ILINKPath          = ''
Opt.!ILINKPath.0        = 0
Opt.!ILINKPath.!choice  = ''

/* path to GNU Make */
Opt.!GNUMakePath            = ''
Opt.!GNUMakePath.0          = 0
Opt.!GNUMakePath.!choice    = ''

/* library version */
Opt.!RELEASE    = 1
Opt.!DLL        = 1
/* optional module configuration */
Opt.!NETWORK    = 1
Opt.!WORKSPACE  = 1
Opt.!XML        = 1
/* third party features */
Opt.!ZLIB       = 1
Opt.!JPEG       = 1
Opt.!PNG        = 1
Opt.!MNG        = 1
Opt.!GIF        = 0 /* WARNING: license restrictions apply when setting to 1! */

/* Configuration cache file */
G.!ConfigCache      = '.configure.cache'
/* Configure Compiler targets */
G.!QtCmd            = 'qt.cmd'
/* Configure Qt targets */
G.!QMakeCache       = '.qmake.cache'
G.!QtOS2Config      = '.qtos2config'
G.!QModulesH        = 'include\qmodules.h'
G.!QConfigH         = 'include\qconfig.h'
G.!QMakeMakefile    = 'qmake\Makefile'
G.!Makefile         = 'Makefile'

/* all globals to be exposed in procedures */
Globals = 'G. Opt.'

/* init rexx lib
 ******************************************************************************/

if (RxFuncQuery('SysLoadFuncs')) then do
    call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
    call SysLoadFuncs
end

/* startup code
 ******************************************************************************/

call MagicLogHook arg(1)

parse source . . G.!ScriptFile
G.!ScriptDir = FixDir(filespec('D', G.!ScriptFile) || filespec('P', G.!ScriptFile))

parse value strip(G.!Id,,'$') with,
    'Id: '.' 'G.!Revision' 'G.!RevisionDate' 'G.!RevisionTime' '.
G.!Title = Replace(G.!Title, '${revision}', G.!Revision)
G.!Title = Replace(G.!Title, '${revision.date}', G.!RevisionDate)
G.!Title = Replace(G.!Title, '${revision.time}', G.!RevisionTime)

call Main

/* termination code
 ******************************************************************************/

call Done 0

/* functions
 ******************************************************************************/

/**
 *  Just do the job.
 */
Main: procedure expose (Globals)

    say
    say
    call SaySay 'Qt Toolkit Version 3 for OS/2 Configuration Script'
    call SaySay '=================================================='
    say
    call SaySay 'This script will interactively configure your installation of the'
    call SaySay 'Qt Library for OS/2. It assumes that you have unzipped the entire'
    call SaySay 'contents of the distribution archive to the following directory:'
    say
    call SaySay ''''G.!ScriptDir''''
    say
    call SaySay 'You can cancel the script execution at any time by pressing the'
    call SaySay 'CTRL-BREAK key combination.'
    say

    /* Qt directory */
    G.!QTDir = G.!ScriptDir
    G.!QTDirP = FixDirNoSlash(G.!QTDir)

    /* Fix paths */
    G.!ConfigCache = G.!QTDirP'\'G.!ConfigCache
    G.!QtCmd = G.!QTDirP'\'G.!QtCmd
    G.!QMakeCache = G.!QTDirP'\'G.!QMakeCache
    G.!QtOS2Config = G.!QTDirP'\'G.!QtOS2Config
    G.!QModulesH = G.!QTDirP'\'G.!QModulesH
    G.!QConfigH = G.!QTDirP'\'G.!QConfigH
    G.!QMakeMakefile = G.!QTDirP'\'G.!QMakeMakefile
    G.!Makefile = G.!QTDirP'\'G.!Makefile

    /* Create the \bin subdirectory */
    if (\DirExists(G.!QTDirP'\bin')) then call MakeDir G.!QTDirP'\bin'

    /* Read the configuration cache */
    call ReadConfigCache

    call WaitForAnyKey

    G.!FirstRun = \FileExists(G.!ConfigCache)

    G.!DidConfigureCompiler = 0
    G.!DidConfigureQt = 0
    G.!DidCompileQt = 0

    if (G.!FirstRun | \FileExists(G.!QtCmd)) then call ConfigureCompiler

    if (G.!FirstRun |,
        \FileExists(G.!QMakeCache) | \FileExists(G.!QtOS2Config) |,
        \FileExists(G.!QModulesH) | \FileExists(G.!QConfigH) |,
        \FileExists(G.!QMakeMakefile) | \FileExists(G.!Makefile)) then
        call ConfigureQt

    if (G.!FirstRun) then call CompileQt

    if (\G.!DidConfigureCompiler | \G.!DidConfigureQt | \G.!DidCompileQt) then do
        G.!Choice.0 = 4
        G.!Choice.1 = 'Configure the compiler'
        G.!Choice.2 = 'Configure the Qt Library'
        G.!Choice.3 = 'Compile the Qt Library'
        G.!Choice.4 = 'Nothing, thanks'
        choice = GetChoice('Select what to do:', 'G.!Choice')
        select
            when choice == 1 then call ConfigureCompiler
            when choice == 2 then call ConfigureQt
            when choice == 3 then call CompileQt
            otherwise nop
        end
    end

    call SaySay 'All done.'
    say

    if (G.!DidConfigureCompiler | G.!DidCompileQt) then do
        call SaySay 'You can now put the generated '''filespec('N', G.!QtCmd)'''',
                    'script to one'
        call SaySay 'of the directories listed in your %PATH% environment'
        call SaySay 'variable and use it as a command line wrapper to setup the'
        call SaySay 'environment necessary to work with the Qt Toolkit for OS/2:'
        call SaySay 'to rebuild the library, to run examples and tutorials, to'
        call SaySay 'compile your own projects.'
        say
        call SaySay 'The script was generated in the following directory:'
        call SaySay ''''FixDir(filespec('D', G.!QtCmd)||filespec('P', G.!QtCmd))''''
        say
    end

    return

/** Writes out the given global variable to the given file */
WriteVar: procedure expose (Globals)
    parse arg file, variable
    call lineout file, variable||' = '''||value(variable)''''
    return

/** Writes out the given global stem to the given file */
WriteStem: procedure expose (Globals)
    parse arg file, stem
    call WriteVar file, stem'.0'
    do n = 1 to value(stem'.0')
        call WriteVar file, stem'.'n
    end
    return

/**
 */
WriteConfigCache: procedure expose (Globals)

    call DeleteFile G.!ConfigCache

    call WriteStem G.!ConfigCache, 'Opt.!GCCPath'
    call WriteVar G.!ConfigCache, 'Opt.!GCCPath.!choice'

    call WriteStem G.!ConfigCache, 'Opt.!ILINKPath'
    call WriteVar G.!ConfigCache, 'Opt.!ILINKPath.!choice'

    call WriteStem G.!ConfigCache, 'Opt.!GNUMakePath'
    call WriteVar G.!ConfigCache, 'Opt.!GNUMakePath.!choice'

    call WriteVar G.!ConfigCache, 'Opt.!RELEASE'
    call WriteVar G.!ConfigCache, 'Opt.!DLL'

    call WriteVar G.!ConfigCache, 'Opt.!NETWORK'
    call WriteVar G.!ConfigCache, 'Opt.!WORKSPACE'
    call WriteVar G.!ConfigCache, 'Opt.!XML'

    call WriteVar G.!ConfigCache, 'Opt.!ZLIB'
    call WriteVar G.!ConfigCache, 'Opt.!JPEG'
    call WriteVar G.!ConfigCache, 'Opt.!PNG'
    call WriteVar G.!ConfigCache, 'Opt.!MNG'
    call WriteVar G.!ConfigCache, 'Opt.!GIF'

    call lineout G.!ConfigCache

    return

/**
 */
ReadConfigCache: procedure expose (Globals)

    signal on syntax name ReadConfigCacheError
    signal on novalue name ReadConfigCacheError

    do while lines(G.!ConfigCache)
        line = linein(G.!ConfigCache)
        interpret line
    end

    signal on syntax
    signal on novalue

    call stream G.!ConfigCache, 'C', 'CLOSE'

    Opt.!GCCPath.!changed = 0
    Opt.!ILINKPath.!changed = 0
    Opt.!GNUMAKEPath.!changed = 0

    return

ReadConfigCacheError:
    signal on syntax
    signal on novalue
    call SayErr 'FATAL: Error reading '''G.!ConfigCache'''!'
    call SayErr 'Please remove this file and restart the script.'
    call Done 1

/**
 */
ConfigureCompiler: procedure expose (Globals)

    call SaySay 'Configure the compiler'
    call SaySay '----------------------'
    say
    call SaySay 'Currently, Qt/OS2 supports only the Innotek GCC compiler 3.2.2'
    call SaySay 'used together with IBM ILINK 3.08 to link native OMF object files'
    call SaySay 'generated by GCC into OS/2 executables.'
    say
    call SaySay 'Also, the GNU Make utility version 3.81beta1 or newer (statically'
    call SaySay 'linked to intl.dll) is required.'
    say

    do until (Opt.!GCCPath \= '')
        call MenuSelectPath,
            'Opt.!GCCPath',,
            'Select where to search for a GCC installation:',,
            'bin\gcc.exe', 'CheckGCCPath',  'CheckGCCVersion',,
            'ERROR: Could not find a valid GCC installation'||G.!EOL||,
            'in ''%1''!'||G.!EOL||,
            'Please read the documentation.'
    end
    call WriteConfigCache

    do until (Opt.!ILINKPath \= '')
        call MenuSelectPath,
            'Opt.!ILINKPath',,
            'Select where to search for an ILINK installation:',,
            'ilink.exe', 'CheckILINKPath',  'CheckILINKVersion',,
            'ERROR: Could not find a valid ILINK installation'||G.!EOL||,
            'in ''%1''!'||G.!EOL||,
            'Please read the documentation.'
    end
    call WriteConfigCache

    do until (Opt.!GNUMakePath \= '')
        call MenuSelectPath,
            'Opt.!GNUMakePath',,
            'Select where to search for the GNU Make utility:',,
            'make.exe', 'CheckGNUMakePath',  'CheckGNUMakeVersion',,
            'ERROR: Could not find a GNU Make utility'||G.!EOL||,
            'in ''%1''!'||G.!EOL||,
            'Please read the documentation.'
    end
    call WriteConfigCache

    call SaySay 'You have selected the following compiler configuration:'
    say
    call SaySay 'Compiler     : Innotek GCC ('Opt.!GCCPath')'
    call SaySay 'Linker       : IBM ILINK ('Opt.!ILINKPath')'
    call SaySay 'Make Utility : GNU Make ('Opt.!GNUMakePath')'
    say

    call WaitForAnyKey

    call DeleteFile G.!QtCmd

    call lineout G.!QtCmd, '/*REXX*/'
    call lineout G.!QtCmd, '/*'
    call lineout G.!QtCmd, ' *  Command line wrapper to set up the Qt environment'
    call lineout G.!QtCmd, ' *  Generated on' date() time()
    call lineout G.!QtCmd, ' */'
    call lineout G.!QtCmd, ''
    call lineout G.!QtCmd, 'QMAKESPEC   = ''os2-g++'''
    call lineout G.!QtCmd, 'QTDIR       = '''QuotePath(G.!QTDir)''''
    call lineout G.!QtCmd, ''
    call lineout G.!QtCmd, 'GCC_PATH        = '''QuotePath(FixDirNoSlash(Opt.!GCCPath))''''
    call lineout G.!QtCmd, ''
    call lineout G.!QtCmd, 'trace off'
    call lineout G.!QtCmd, 'address ''cmd'''
    call lineout G.!QtCmd, '''@echo off'''
    call lineout G.!QtCmd, ''
    call lineout G.!QtCmd, 'if (RxFuncQuery(''SysBootDrive'')) then'
    call lineout G.!QtCmd, '    call RxFuncAdd ''SysBootDrive'', ''RexxUtil'', ''SysBootDrive'''
    call lineout G.!QtCmd, ''
    call lineout G.!QtCmd, 'call value ''QMAKESPEC'', QMAKESPEC, ''OS2ENVIRONMENT'''
    call lineout G.!QtCmd, 'call value ''QTDIR'', QTDIR, ''OS2ENVIRONMENT'''
    call lineout G.!QtCmd, ''
    call lineout G.!QtCmd, 'call AddPathEnv ''PATH'', QTDIR''\bin'''
    call lineout G.!QtCmd, 'call AddPathEnv ''BEGINLIBPATH'', QTDIR''\bin'''
    call lineout G.!QtCmd, ''
    call ConfigureCompiler_GenAddPathEnv 'PATH',,
        Opt.!GCCPath.!addPath';'Opt.!ILINKPath.!addPath';'Opt.!GNUMAKEPath.!addPath
    call ConfigureCompiler_GenAddPathEnv 'BEGINLIBPATH',,
        Opt.!GCCPath.!addLibPath';'Opt.!ILINKPath.!addLibPath';'Opt.!GNUMAKEPath.!addLibPath
    call lineout G.!QtCmd, ''
    call lineout G.!QtCmd, '/*'
    call lineout G.!QtCmd, ' * set this to allow for direct linking with DLLs'
    call lineout G.!QtCmd, ' * without first making import libraries'
    call lineout G.!QtCmd, ' */'
    call lineout G.!QtCmd, 'call AddPathEnv ''LIBRARY_PATH'', SysBootDrive()''\OS2\DLL'''
    call lineout G.!QtCmd, 'call AddPathEnv ''LIBRARY_PATH'', SysBootDrive()''\MPTN\DLL'''
    call lineout G.!QtCmd, ''
    call lineout G.!QtCmd, '/* setup the GCC environment */'
    call lineout G.!QtCmd, '''call'' GCC_PATH''\bin\gccenv.cmd'' GCC_PATH ''VAC308'''
    call lineout G.!QtCmd, ''
    call lineout G.!QtCmd, 'parse arg args'
    call lineout G.!QtCmd, '''cmd /c'' args'
    call lineout G.!QtCmd, 'exit rc'
    call lineout G.!QtCmd, ''
    call lineout G.!QtCmd, ''
    call lineout G.!QtCmd, '/* some useful stuff */'
    call lineout G.!QtCmd, ''

    /* copy some function definitions */
    call stream G.!ScriptFile, 'C', 'OPEN READ'
    exportLine = 0
    do while lines(G.!ScriptFile)
        line = linein(G.!ScriptFile)
        if (left(line, 6) == '/* <<<') then exportLine = 1
        else if (left(line, 6) == '/* >>>') then exportLine = 0
        else if exportLine then call lineout G.!QtCmd, line
    end
    call stream G.!ScriptFile, 'C', 'CLOSE'

    call lineout G.!QtCmd, ''
    call lineout G.!QtCmd

    call SaySay 'The compiler has been configured.'
    say

    G.!DidConfigureCompiler = 1
    return

/**
 */
ConfigureCompiler_GenAddPathEnv: procedure expose (Globals)
    parse arg env, paths
    G.!temp = ''
    /* first pass: remove dups */
    do while length(paths) > 0
        parse var paths path';'paths
        if (path \== '') then
            call AddPathVar 'G.!temp', path, 1
    end
    /* second pass: generate AddPathEnv calls */
    paths = G.!temp
    do while length(paths) > 0
        parse var paths path';'paths
        if (path \== '') then
            call lineout G.!QtCmd, 'call AddPathEnv '''env''','''QuotePath(path)''', 1'
    end
    return

/**
 */
ConfigureQt: procedure expose (Globals)

    call SaySay 'Configure Qt Library'
    call SaySay '--------------------'
    say

    G.!Choices.0 = 2
    G.!Choices.1 = 'Dynamic link library (DLL)'
    G.!Choices.2 = 'Static library'
    choice = GetChoice('Select the Qt library type:', 'G.!Choices', -Opt.!DLL + 2)
    Opt.!DLL = -choice + 2

    G.!Choices.0 = 2
    G.!Choices.1 = 'Release (no debug information)'
    G.!Choices.2 = 'Debug'
    choice = GetChoice('Select the Qt library debug level:', 'G.!Choices', -Opt.!RELEASE + 2)
    Opt.!RELEASE = -choice + 2

    G.!Choices.0 = 3
    do forever
        G.!Choices.1 = 'Network     'GetEnabledText(Opt.!NETWORK)
        G.!Choices.2 = 'Workspace   'GetEnabledText(Opt.!WORKSPACE)
        G.!Choices.3 = 'XML         'GetEnabledText(Opt.!XML)
        call SaySay 'Enable or disable optional Qt library modules'
        choice = GetChoice('(pressing Enter will accept the current selection):',,
                           'G.!Choices',, 1)
        select
            when choice == 1 then Opt.!NETWORK = \Opt.!NETWORK
            when choice == 2 then Opt.!WORKSPACE = \Opt.!WORKSPACE
            when choice == 3 then Opt.!XML = \Opt.!XML
            otherwise leave
        end
    end

    call WriteConfigCache

    BasicModules = 'kernel tools widgets dialogs styles'
    BasicModulesHeader =,
        '// These modules are present in this configuration of Qt'G.!EOL||,
        '#define QT_MODULE_KERNEL'G.!EOL||,
        '#define QT_MODULE_TOOLS'G.!EOL||,
        '#define QT_MODULE_WIDGETS'G.!EOL||,
        '#define QT_MODULE_DIALOGS'G.!EOL||,
        '#define QT_MODULE_STYLES'G.!EOL

    if (Opt.!RELEASE == 1) then ReleaseOrDebug = 'release'
    else ReleaseOrDebug = 'debug'

    if (Opt.!DLL == 1) then do
        SharedOrStatic = 'shared'
        DllOrStatic = 'shared (dll)'
        SharedOrNot = 'shared'
    end
    else do
        SharedOrStatic = 'static'
        DllOrStatic = 'static'
        SharedOrNot = ''
    end

    OptionalModules = ''
    ModulesHeader = BasicModulesHeader
    if (Opt.!NETWORK == 1) then do
        OptionalModules = OptionalModules 'network'
        ModulesHeader = ModulesHeader || '#define QT_MODULE_NETWORK'G.!EOL
    end
    if (Opt.!WORKSPACE == 1) then do
        OptionalModules = OptionalModules 'workspace'
        ModulesHeader = ModulesHeader || '#define QT_MODULE_WORKSPACE'G.!EOL
    end
    if (Opt.!XML == 1) then do
        OptionalModules = OptionalModules 'xml'
        ModulesHeader = ModulesHeader || '#define QT_MODULE_XML'G.!EOL
    end
    OptionalModules = strip(OptionalModules)

    OptionalConfig = ''
    if (Opt.!GIF == 1) then do
        OptionalConfig = OptionalConfig 'gif'
    end
    else do
        OptionalConfig = OptionalConfig 'no-gif'
    end
    if (Opt.!ZLIB == 1) then do
        OptionalConfig = OptionalConfig 'zlib'
    end
    if (Opt.!JPEG == 1) then do
        OptionalConfig = OptionalConfig 'jpeg'
    end
    if (Opt.!PNG == 1) then do
        OptionalConfig = OptionalConfig 'png'
    end
    if (Opt.!MNG == 1) then do
        OptionalConfig = OptionalConfig 'mng'
    end
    OptionalConfig = strip(OptionalConfig)

    call SaySay 'You have selected the following compiler configuration:'
    say
    call SaySay 'Library type   : 'DllOrStatic', 'ReleaseOrDebug', multithreaded'
    call SaySay 'Modules        : 'BasicModules OptionalModules
    call SaySay 'Other features : 'OptionalConfig
    say

    call WaitForAnyKey

    call SaySay 'Please wait...'
    say

    /* do the configure Qt job */

    qmake_cache = G.!QMakeCache
    qtos2config = G.!QtOS2Config
    qmodules_h = G.!QModulesH
    qconfig_h = G.!QConfigH

    call DeleteFile qmake_cache
    call DeleteFile qtos2config
    call DeleteFile qmodules_h
    call DeleteFile qconfig_h

    call lineout qmake_cache, 'QMAKE_QT_VERSION_OVERRIDE=331'
    call lineout qmake_cache, 'OBJECTS_DIR=tmp\obj\'ReleaseOrDebug'_mt_'SharedOrStatic
    call lineout qmake_cache, 'MOC_DIR=tmp\moc\'ReleaseOrDebug'_mt_'SharedOrStatic
    call lineout qmake_cache, 'DEFINES+='
    call lineout qmake_cache, 'INCLUDEPATH+='
    call lineout qmake_cache, 'sql-drivers+='
    call lineout qmake_cache, 'sql-plugins+='
    call lineout qmake_cache, 'styles+=windows'
    call lineout qmake_cache, 'style-plugins+='
    call lineout qmake_cache, 'imageformat-plugins+='
    call lineout qmake_cache, 'QT_PRODUCT=qt-enterprise'
    call lineout qmake_cache, 'CONFIG+=nocrosscompiler' BasicModules OptionalModules 'minimal-config small-config medium-config large-config full-config 'ReleaseOrDebug' thread' OptionalConfig 'bigcodecs no-tablet incremental create_prl link_prl'
    call lineout qmake_cache, 'QMAKESPEC=os2-g++'
    call lineout qmake_cache, 'QT_BUILD_TREE='QuotePath(G.!QTDir)
    call lineout qmake_cache, 'QT_SOURCE_TREE='QuotePath(G.!QTDir)
    call lineout qmake_cache, 'QT_INSTALL_PREFIX='QuotePath(G.!QTDir)
    call lineout qmake_cache, 'QT_INSTALL_TRANSLATIONS='QuotePath(G.!QTDirP'\translations')
    call lineout qmake_cache, 'docs.path='QuotePath(G.!QTDirP'\doc')
    call lineout qmake_cache, 'headers.path='QuotePath(G.!QTDirP'\include')
    call lineout qmake_cache, 'plugins.path='QuotePath(G.!QTDirP'\plugins')
    call lineout qmake_cache, 'libs.path='QuotePath(G.!QTDirP'\lib')
    call lineout qmake_cache, 'bins.path='QuotePath(G.!QTDirP'\bin')
    call lineout qmake_cache, 'data.path='QuotePath(G.!QTDirP)
    call lineout qmake_cache, 'translations.path='QuotePath(G.!QTDirP'\translations')
    call lineout qmake_cache

    call lineout qtos2config, 'CONFIG+= 'SharedOrNot' thread 'ReleaseOrDebug
    call lineout qtos2config, 'exists( $(QTDIR)\.qtos2defines ) {'
    call lineout qtos2config, '    include( $(QTDIR)\.qtos2defines )'
    call lineout qtos2config, '    QMAKE_INTERNAL_INCLUDED_FILES += $(QTDIR)\.qtos2defines'
    call lineout qtos2config, '}'
    call lineout qtos2config

    call lineout qmodules_h, ModulesHeader
    call lineout qmodules_h

    call lineout qconfig_h, '/* Everything */'
    call lineout qconfig_h, ''
    call lineout qconfig_h, '/* License information */'
    call lineout qconfig_h, '#define QT_PRODUCT_LICENSEE "Free"'
    call lineout qconfig_h, '#define QT_PRODUCT_LICENSE "qt-free"'
    call lineout qconfig_h, ''
    call lineout qconfig_h, '/* Machine byte-order */'
    call lineout qconfig_h, '#define Q_BIG_ENDIAN 4321'
    call lineout qconfig_h, '#define Q_LITTLE_ENDIAN 1234'
    call lineout qconfig_h, '#define Q_BYTE_ORDER Q_LITTLE_ENDIAN'
    call lineout qconfig_h, ''
    call lineout qconfig_h, '/* Compile time features */'
    call lineout qconfig_h, '#ifndef QT_NO_STL'
    call lineout qconfig_h, '#define QT_NO_STL'
    call lineout qconfig_h, '#endif'
    call lineout qconfig_h, '#ifndef QT_NO_STYLE_WINDOWSXP'
    call lineout qconfig_h, '#define QT_NO_STYLE_WINDOWSXP'
    call lineout qconfig_h, '#endif'
    call lineout qconfig_h

    call CopyFile QuotePath(G.!QTDirP)'\qmake\"Makefile.os2-g++"',
                  G.!QMakeMakefile

    call CopyFile QuotePath(G.!QTDirP)'\"Makefile.os2-g++"',
                  G.!Makefile

    call SaySay 'The Qt Library has been configured.'
    say

    call WaitForAnyKey

    G.!DidConfigureQt = 1
    return

/**
 */
CompileQt: procedure expose (Globals)

    call SaySay 'Compile Qt Library'
    call SaySay '------------------'
    say

    call SaySay 'The configuration script is about to compile and build the Qt'
    call SaySay 'Library. All output generated by the compiler and other tools'
    call SaySay 'will be recorded to a ''build.log'' file located in the'
    call SaySay 'installation directory.'
    say

    build_log = G.!QTDirP'\build.log'

    build_target = ''

    G.!Choice.0 = 2
    G.!Choice.1 = 'Everything (Qt Library, tools, examples and tutorials)'
    G.!Choice.2 = 'Qt Library and tools only'
    choice = GetChoice('Select what to compile:', 'G.!Choice')
    select
        when choice == 1 then build_target = 'all'
        when choice == 2 then build_target = 'sub-src sub-tools'
        otherwise nop
    end

    no_cleanup_query = (G.!FirstRun & G.!DidConfigureCompiler & G.!DidConfigureQt)
    do_cleanup = 1

    if (\no_cleanup_query) then do
        call SaySay "Clean up the previous build?"
        do_cleanup =,
            GetYesNo("(answer Y (yes) until you are sure what are you doing)", 'Y')
    end

    if (build_target \== '') then do
        call DeleteFile build_log
        address 'cmd' 'call' G.!QtCmd
        call lineout build_log, 'Build started on 'date()' 'time()||G.!EOL
        if (do_cleanup) then do
            call lineout build_log, 'Cleaning up...'G.!EOL
            call lineout build_log, 'make clean'G.!EOL
            call lineout build_log
            address 'cmd',
                'make clean 2>&1 | "'G.!ScriptFile'" --magic-log='build_log
        end
        else rc = 0
        if (rc == 0) then do
            call lineout build_log, ''
            call lineout build_log, 'Building...'G.!EOL
            call lineout build_log, 'make 'build_target||G.!EOL
            call lineout build_log
            address 'cmd',
                'make' build_target '2>&1 | "'G.!ScriptFile'" --magic-log='build_log
        end
        if (rc \== 0) then do
            call SayErr 'FATAL: Error has occured while building the Qt Library!'
            call SayErr 'make returned' rc
            say
            call SayErr 'Please inspect the following file to find the cause of the error:'
            call SayErr ''''build_log''''
            call Done 1
            say
        end
    end

    G.!DidCompileQt = (build_target \== '')
    return

/**
 */
CheckGCCPath: procedure expose (Globals)
    parse arg path, beforeCheckVer
    beforeCheckVer = (beforeCheckVer == 1)
    path = FixDirNoSlash(path)
    if (FileExists(path'\bin\gccenv.cmd') & FileExists(path'\bin\gcc.exe')) then do
        if (beforeCheckVer) then do
            Opt.!GCCPath.!addPath = ''
            Opt.!GCCPath.!addLibPath = ''
        end
    end
    else return 0
    return 1

/**
 */
CheckGCCVersion: procedure expose (Globals)
    parse arg path
    path = FixDirNoSlash(path)
    address 'cmd' 'call' path'\bin\gccenv.cmd' path
    address 'cmd' path'\bin\gcc.exe --version | more'
    say
    if (Opt.!GCCPath.!changed \== 1) then def = 'Y'; else def = ''
    return GetYesNo("Accept the above version?", def)

/**
 */
CheckILINKPath: procedure expose (Globals)
    parse arg path, beforeCheckVer
    beforeCheckVer = (beforeCheckVer == 1)
    path = FixDirNoSlash(path)
    if (translate(right(path, 4)) == '\BIN' &,
        FileExists(path'\ilink.exe') & FileExists(path'\..\dll\cppom30.dll')) then do
        if (beforeCheckVer) then do
            Opt.!ILINKPath.!addPath = path
            Opt.!ILINKPath.!addLibPath = left(path, length(path) - 4)'\dll'
        end
    end
    else if (FileExists(path'\ilink.exe') & FileExists(path'\cppom30.dll')) then do
        if (beforeCheckVer) then do
            Opt.!ILINKPath.!addPath = path
            Opt.!ILINKPath.!addLibPath = path
        end
    end
    else return 0
    return 1

/**
 */
CheckILINKVersion: procedure expose (Globals)
    parse arg path
    path = FixDirNoSlash(path)
    call AddPathEnv 'PATH', Opt.!ILINKPath.!addPath, 1
    call AddPathEnv 'BEGINLIBPATH', Opt.!ILINKPath.!addLibPath, 1
    address 'cmd' 'ilink.exe | more'
    say
    if (Opt.!ILINKPath.!changed \== 1) then def = 'Y'; else def = ''
    return GetYesNo("Accept the above version?", def)

/**
 */
CheckGNUMakePath: procedure expose (Globals)
    parse arg path, beforeCheckVer
    beforeCheckVer = (beforeCheckVer == 1)
    path = FixDirNoSlash(path)
    if (FileExists(path'\make.exe')) then do
        if (FileExists(path'\intl.dll')) then do
            if (beforeCheckVer) then do
                Opt.!GNUMakePath.!addPath = path
                Opt.!GNUMakePath.!addLibPath = path
            end
        end
        else do
            if (beforeCheckVer) then do
                Opt.!GNUMakePath.!addPath = path
                Opt.!GNUMakePath.!addLibPath = ''
            end
        end
    end
    else return 0
    return 1

/**
 */
CheckGNUMakeVersion: procedure expose (Globals)
    parse arg path
    path = FixDirNoSlash(path)
    call AddPathEnv 'PATH', Opt.!GNUMakePath.!addPath, 1
    call AddPathEnv 'BEGINLIBPATH', Opt.!GNUMakePath.!addLibPath, 1
    address 'cmd' 'make.exe --version | more'
    say
    if (Opt.!GNUMakePath.!changed \== 1) then def = 'Y'; else def = ''
    return GetYesNo("Accept the above version?", def)

/**
 */
GetEnabledText: procedure expose (Globals)
    parse arg n
    if (n == 1) then return '[X]'
    else return '[ ]'

/* utility functions
 ******************************************************************************/

CopyFile: procedure expose (Globals)
    parse arg fileFrom fileTo
    address 'cmd' 'copy' fileFrom fileTo '1>nul 2>nul'
    if (rc \== 0) then do
        call SayErr 'FATAL: Could not copy '''fileFrom''' to '''fileTo'''!'
        call SayErr 'copy returned 'rc
        call Done 1
    end
    return

DeleteFile: procedure expose (Globals)
    parse arg file
    rc = SysFileDelete(file)
    if (rc \= 0 & rc \= 2) then do
        call SayErr 'FATAL: Could not delete file '''file'''!'
        call SayErr 'SysFileDelete returned 'rc
        call Done 1
    end
    return

MakeDir: procedure expose (Globals)
    parse arg path
    rc = SysMkDir(path)
    if (rc \= 0) then do
        call SayErr 'FATAL: Could not create directory '''path'''!'
        call SayErr 'SysMkDir returned 'rc
        call Done 1
    end
    return

SaySay: procedure expose (Globals)
    parse arg str, noeol
    noeol = (noeol == 1)
    if (noeol) then call charout, '    'str
    else say '    'str
    return

SayErr: procedure expose (Globals)
    parse arg str, noeol
    noeol = (noeol == 1)
    if (noeol) then call charout, str
    else say str
    return

SayPrompt: procedure expose (Globals)
    parse arg str, noeol
    noeol = (noeol == 1)
    if (noeol) then call charout, '>>> 'str
    else say '>>> 'str
    return

/**
 *  Waits for any key.
 */
WaitForAnyKey: procedure expose (Globals)
    call SayPrompt 'Press any key to continue...'
    call SysGetKey 'NOECHO'
    say
    return

/**
 *  Shows the prompt to input a text line and
 *  returns the line entered by the user.
 */
InputLine: procedure expose (Globals)
    parse arg prompt
    call SaySay prompt
    say
    call SayPrompt '', 1
    line = linein()
    say
    return line

/**
 *  Shows the prompt to input a directory path and
 *  returns the path entered by the user. The procedure
 *  does not return until a valid existing path is entered.
 *
 *  @param  prompt  prompt to show
 *  @return         selected directory
 */
InputDir: procedure expose (Globals)
    parse arg prompt
    do forever
        dir = InputLine(prompt)
        if (DirExists(dir)) then leave
        call SayErr 'The entered directory does not exist.'
        say
    end
    return dir

/**
 *  Shows a Yes/No choice.
 *
 *  @param  prompt  prompt to show
 *  @param  default default choice:
 *      ''      - no default choice
 *      'Y'     - default is yes
 *      other   - default is no
 *  @return
 *      1 if Yes is selected, otherwise 0
 */
GetYesNo: procedure expose (Globals)
    parse arg prompt, default
    default = translate(default)
    if (default \== '' & default \== 'Y') then default = 'N'
    call SaySay prompt
    say
    call SayPrompt '[YN] 'default, 1
    yn = ReadChoice('YN',, default, 1)
    say
    say
    return (yn == 'Y')

/**
 *  Shows a menu of choices and returns the
 *  menu item number selected by the user.
 *
 *  @param  prompt  prompt to display
 *  @param  stem    stem containing a list of choices
 *  @param  default default choice
 *  @param  allowEnter
 *      1 allows to press Enter w/o a choice (will return '')
 *  @return
 *      selected menu item number
 */
GetChoice: procedure expose (Globals)
    parse arg prompt, stem, default, allowEnter
    allowEnter = (allowEnter == 1)
    count = value(stem'.0')
    if (count == 0) then return
    call SaySay prompt
    say
    first = 1
    do forever
        extChoices = ''
        last = first + 9
        if (last > count) then last = count
        choices = substr('1234567890', 1, last - first + 1)
        prompt = choices
        if (allowEnter) then prompt = prompt'/Enter'
        if (first > 1) then do
            extChoices = extChoices||'49'x
            prompt = prompt'/PgUp'
            call SaySay '^^'
        end
        do i = first to last
            ii = i - first + 1
            if (ii == 10) then ii = 0
            call SaySay ii')' value(stem'.'i)
        end
        if (last < count) then do
            extChoices = extChoices||'51'x
            prompt = prompt'/PgDn'
            call SaySay 'vv'
        end
        say
        def = ''
        if (default \== '') then do
            def = default - first + 1
            if (def < 1 | def > 10) then def = ''
            else if (def == 10) then def = 0
        end
        call SayPrompt '['prompt'] '||def, 1
        n = ReadChoice(choices, extChoices, def,, allowEnter)
        say
        say
        if (n == '0E49'x) then do
            first = first - 10
            iterate
        end
        if (n == '0E51'x) then do
            first = first + 10
            iterate
        end
        if (n \== '') then do
            if (n == 0) then n = 10
            n = n + first - 1
        end
        leave
    end
    return n

/**
 *  Reads a one-key choice from the keyboard.
 *
 *  @param  choices     string of allowed one-key choices
 *  @param  extChoices  string of allowed one-extended-key choices
 *  @param  default     default choice (can be a key from choices)
 *  @param  ignoreCase  1 ignores case of letters
 *  @param  allowEnter
 *      1 allows to press Enter w/o a choice (will return '')
 *  @return
 *      entered key (prefixed with 'E0'x if from extChoices)
 */
ReadChoice: procedure expose (Globals)
    parse arg choices, extChoices, default, ignoreCase, allowEnter
    ignoreCase = (ignoreCase == 1)
    allowEnter = (allowEnter == 1)
    choice = default
    if (ignoreCase) then choice = translate(choice)
    extended = 0
    do forever
        key = SysGetKey('NOECHO')
        if (key == 'E0'x) then do
            extended = 1
            iterate
        end
        if (\extended & ignoreCase) then key = translate(key)
        select
            when (choice == '' & \extended & verify(key, choices) == 0) then do
                choice = key
            end
            when (extended & verify(key, extChoices) == 0) then do
                choice = '0E'x||key
                leave
            end
            when (\extended & key == '08'x & choice \== '') then do
                /* backspace pressed */
                call charout, key' '
                choice = ''
            end
            when (\extended & key == '0D'x & (choice \== '' | allowEnter)) then do
                leave
            end
            otherwise do
                extended = 0
                iterate
            end
        end
        call charout, key
        extended = 0
    end
    return choice

/**
 *  Shows a menu to select a path.
 *  The last of menu entries allows to enter a new location to search for valid
 *  paths (this operation will completely overwrite all the stem entries passed
 *  to this function).
 *
 *  @param  stem
 *      stem containing entries to choose from (must be prefixed by a name from
 *      Globals), stem'.!choice' must contain a default choice (or '')
 *  @param  prompt
 *      prompt to display
 *  @param  default
 *      default choice
 *  @param  searchPattern
 *      pattern to search for when selecting suitable paths in the new location
 *      (can include the directory prefix, but wildcards are supported in the
 *      filename part only)
 *  @param  checkPath
 *      name of the funciton to check the path. The first argument is the path
 *      to check, the second argument is 1 if this function is called just before
 *      checkVer (this can be used to pass data to checkVer (using global
 *      vafiables) necessary to perform a version check).
 *  @param  checkVer
 *      name of the funciton to check the version. The argument is a path to
 *      check the version for.
 *  @param  errPath
 *      error message to display when a path check fails (%1 will be replaced
 *      with the failed path name)
 *  @return
 *      when both path and version checks succeed, stem variable itself
 *      (i.e. w/o any indexes) will contain a path selected and stem'.!choice'
 *      will contain the selected item number; otherwise the stem variable will
 *      be empty (this also includes the case when a user typed a new location
 *      and the stem was overwritten with a list of new paths found)
 */
MenuSelectPath: procedure expose (Globals)

    parse arg stem, prompt, searchPattern, checkPath, checkVer, errPath

    call value stem, ''

    n = value(stem'.0') + 1
    call SysStemInsert stem, n, '[type a location...]'
    if (n == 1) then default = 1
    else default = value(stem'.!choice')

    choice = GetChoice(prompt, stem, default)
    call SysStemDelete stem, n

    if (choice == n) then do
        path = InputDir('Enter a location where to start searching from:')
        call SaySay 'Please wait...'
        say
        patternPath = translate(filespec('D', searchPattern) || filespec('P', searchPattern))
        patternName = filespec('N', searchPattern)
        call SysFileTree FixDirNoSlash(path)'\'patternName, 'found', 'FSO'
        found2.0 = 0
        if (found.0 > 0) then do
            do i = 1 to found.0
                dir = filespec('D', found.i) || filespec('P', found.i)
                /* check that the found path ends with the pattern path */
                if (translate(right(dir, length(patternPath))) \== patternPath) then
                    iterate
                dir = left(dir, length(dir) - length(patternPath))
                /* check path validity  */
                interpret 'ok = 'checkPath'("'dir'")'
                if (ok) then
                    call SysStemInsert 'found2', 1, FixDir(dir)
            end
        end
        if (found2.0 > 0) then do
            call SysStemCopy 'found2', stem
            call value stem'.!choice', ''
            call value stem'.!changed', 1
            return
        end
    end
    else do
        path = value(stem'.'choice)
        /* check path validity and tell the version check will be done next*/
        interpret 'ok = 'checkPath'("'path'", 1)'
        if (ok) then do
            if (value(stem'.!choice') \== choice) then
                call value stem'.!changed', 1
            interpret 'ok = 'checkVer'("'path'")'
            if (ok) then do
                call value stem, path
                call value stem'.!choice', choice
                return
            end
            return
        end
    end

    call SayErr Replace(errPath, '%1', path)
    say

    return

/**
 *  Encloses the given path with quotes if it contains
 *  space characters, otherwise returns it w/o changes.
 */
QuotePath: procedure expose (Globals)
    parse arg path
    if (verify(path, ' +', 'M') > 0) then path = '"'path'"'
    return path

/**
 *  Fixes the directory path by a) converting all slashes to back
 *  slashes and b) ensuring that the trailing slash is present if
 *  the directory is the root directory, and absent otherwise.
 *
 *  @param dir      the directory path
 *  @param noslash
 *      optional argument. If 1, the path returned will not have a
 *      trailing slash anyway. Useful for concatenating it with a
 *      file name.
 */
FixDir: procedure expose (Globals)
    parse arg dir, noslash
    noslash = (noslash = 1)
    dir = translate(dir, '\', '/')
    if (right(dir, 1) == '\' &,
        (noslash | \(length(dir) == 3 & (substr(dir, 2, 1) == ':')))) then
        dir = substr(dir, 1, length(dir) - 1)
    return dir

/**
 *  Shortcut to FixDir(dir, 1)
 */
FixDirNoSlash: procedure expose (Globals)
    parse arg dir
    return FixDir(dir, 1)

/**
 *  Returns 1 if the specified dir exists and 0 otherwise.
 */
DirExists: procedure expose (Globals)
    parse arg dir
    return (GetAbsDirPath(dir) \== '')

/**
 *  Returns the absolute path to the given directory
 *  or an empty string if no directory exists.
 */
GetAbsDirPath: procedure expose (Globals)
    parse arg dir
    if (dir \== '') then do
        curdir = directory()
        dir = directory(FixDir(dir))
        call directory curdir
    end
    return dir

/**
 *  Returns 1 if the specified file exists and 0 otherwise.
 */
FileExists: procedure expose (Globals)
    parse arg file
    return (GetAbsFilePath(file) \= '')

/**
 *  Returns the absolute path to the given file (including the filename)
 *  or an empty string if no file exists.
 */
GetAbsFilePath: procedure expose (Globals)
    parse arg file
    if (file \= '') then do
        file = stream(FixDir(file), 'C', 'QUERY EXISTS')
    end
    return file

/**
 *  Returns the name of the temporary directory.
 *  The returned value doesn't end with a slash.
 */
GetTempDir: procedure expose (Globals)
    dir = value('TEMP',,'OS2ENVIRONMENT')
    if (dir == '') then dir = value('TMP',,'OS2ENVIRONMENT')
    if (dir == '') then dir = SysBootDrive()
    return dir

/**
 *  Magic log handler.
 */
MagicLogHook: procedure
    parse arg magic'='file
    if (magic \== '--magic-log') then return
    file = strip(file, 'T')
    signal on halt name MagicLogHalt
    do while (stream('STDIN', 'S') == 'READY')
        line = linein()
        call lineout, line
        call lineout file, line
    end
    exit 0

MagicLogHalt:
    exit 255

/**
 *  Adds the given path to the contents of the given variable
 *  containing a list of paths separated by semicolons.
 *  This function guarantees that the given path is contained only once
 *  in the variable.
 *
 *  @param  name        variable name
 *  @param  path        path to add
 *  @param  prepend     1 will put the path to the beginning, otherwise it
 *                      will be appended to the end of the variable's contents.
 *  @param  environment either '' to act on REXX variables or 'OS2ENVIRONMENT'
 *                      to act on OS/2 environment variables
 *
 *  @version 1.0
 */
/* <<< export to qt.cmd starts */
AddPathVar: procedure expose (Globals)
    parse arg name, path, prepend, environment
    if (path == '') then return
    if (verify(path, ' +', 'M') > 0) then path = '"'path'"'
    prepend = (prepend == 1)
    os2Env = (translate(environment) == 'OS2ENVIRONMENT')
    if (os2Env) then do
        extLibPath = (translate(name) == 'BEGINLIBPATH' | translate(name) == 'ENDLIBPATH')
        if (extLibPath) then cur = SysQueryExtLibPath(left(name, 1))
        else cur = value(name,, environment)
    end
    else cur = value(name)
    l = length(path)
    p = pos(translate(path), translate(cur))
    cb = ''; ca = ''
    found = (p > 0)
    if (found) then do
        if (p > 1) then cb = substr(cur, p - 1, 1)
        if (p + l <= length(cur)) then ca = substr(cur, p + l, 1)
        found = (cb == '' | cb == ';') & (ca == '' | ca == ';')
    end
    if (found) then do
        if (\prepend) then return
        if (ca == ';') then l = l + 1
        cur = delstr(cur, p, l)
    end
    if (prepend) then do
        if (left(cur, 1) \== ';') then cur = ';'cur
        cur = path||cur
    end
    else do
        if (cur \== '' & right(cur, 1) \== ';') then cur = cur';'
        cur = cur||path
    end
    if (os2Env) then do
        if (extLibPath) then call SysSetExtLibPath cur, left(name, 1)
        else call value name, cur, environment
    end
    else call value name, cur
    return
/* >>> export to qt.cmd ends */

/**
 *  Shortcut to AddPathVar(name, path, prepend, 'OS2ENVIRONMENT')
 */
/* <<< export to qt.cmd starts */
AddPathEnv: procedure expose (Globals)
    parse arg name, path, prepend
    call AddPathVar name, path, prepend, 'OS2ENVIRONMENT'
    return
/* >>> export to qt.cmd ends */

/**
 *  Replaces all occurences of a given substring in a string with another
 *  substring.
 *
 *  @param  str the string where to replace
 *  @param  s1  the substring which to replace
 *  @param  s2  the substring to replace with
 *  @return     the processed string
 *
 *  @version 1.1
 */
Replace: procedure expose (Globals)
    parse arg str, s1, s2
    l1  = length(s1)
    l2  = length(s2)
    i   = 1
    do while (i > 0)
        i = pos(s1, str, i)
        if (i > 0) then do
            str = delstr(str, i, l1)
            str = insert(s2, str, i-1)
            i = i + l2
        end
    end
    return str

/**
 *  NoValue signal handler.
 */
NoValue:
    errl    = sigl
    say
    say
    say 'EXPRESSION HAS NO VALUE at line #'errl'!'
    say
    say 'This is usually a result of a misnamed variable.'
    say 'Please contact the author.'
    call Done 252

/**
 *  Nonsense handler.
 */
Nonsense:
    errl    = sigl
    say
    say
    say 'NONSENSE at line #'errl'!'
    say
    say 'The author decided that this point of code should'
    say 'have never been reached, but it accidentally had.'
    say 'Please contact the author.'
    call Done 253

/**
 *  Syntax signal handler.
 */
Syntax:
    errn    = rc
    errl    = sigl
    say
    say
    say 'UNEXPECTED PROGRAM TERMINATION!'
    say
    say 'REX'right(errn , 4, '0')': 'ErrorText(rc)' at line #'errl
    say
    say 'Possible reasons:'
    say
    say '  1. Some of REXX libraries are not found but required.'
    say '  2. You have changed this script and made a syntax error.'
    say '  3. Author made a mistake.'
    say '  4. Something else...'
    call Done 254

/**
 *  Halt signal handler.
 */
Halt:
    say
    say 'CTRL-BREAK pressed, exiting.'
    call Done 255

/**
 *  Always called at the end. Should not be called directly.
 *  @param the exit code
 */
Done: procedure expose (Globals)
    parse arg code
    /* protect against recursive calls */
    if (value('G.!Done_done') == 1) then exit code
    call value 'G.!Done_done', 1
    /* cleanup stuff goes there */
    /* ... */
    /* finally, exit */
    exit code

